package gr.grnet.aquarium.logic.accounting.dsl
import java.util.Date
+import scala.collection.mutable
/**
* A representation of a timeslot with a start and end date.
assert(to != null)
assert(from.before(to))
+ def startsBefore(t: Timeslot) : Boolean = this.from.before(t.from)
+
+ def startsAfter(t: Timeslot) : Boolean = this.from.after(t.from)
+
+ def endsBefore(t: Timeslot) : Boolean = this.to.before(t.to)
+
+ def endsAfter(t: Timeslot) : Boolean = this.to.after(t.to)
+
/**
* Check whether this time slot fully contains the provided one.
*/
- def contains(t: Timeslot) : Boolean = {
- if (this.from.after(t.from))
- return false
-
- if (this.to.before(t.to))
- return false
-
- true
- }
+ def contains(t: Timeslot) : Boolean = t.startsAfter(this) && t.endsBefore(this)
/**
* Check whether this timeslot contains the provided time instant.
else
List(t, this)
}
+
+ /**
+ * Split the timeslot in two parts at the provided timestamp, if the
+ * timestamp falls within the timeslot boundaries.
+ */
+ def slice(d: Date) : List[Timeslot] =
+ if (includes(d))
+ List(Timeslot(from, d), Timeslot(d,to))
+ else
+ List(this)
+
+ /**
+ * Find and return the timeslots whithin which this Timeslot overrides
+ * with the provided list of timeslots. For example if:
+ *
+ * - `this == Timeslot(7,20)`
+ * - `list == List(Timeslot(1,3), Timeslot(6,8), Timeslot(11,15))`
+ *
+ * the result will be: `List(Timeslot(7,8), Timeslot(11,15))`
+ */
+ def overlappingTimeslots(list: List[Timeslot]) : List[Timeslot] = {
+
+ val result = new mutable.ListBuffer[Timeslot]()
+
+ list.foreach {
+ t =>
+ if (t.contains(this) || this.contains(t)) result += t
+ else if (t.overlaps(this) && t.startsBefore(this)) result += this.slice(t.to).head
+ else if (t.overlaps(this) && t.startsAfter(this)) result += this.slice(t.from).tail.head
+ }
+ result.toList
+ }
+
+ /**
+ * Find and return the timeslots whithin which this Timeslot does not
+ * override with the provided list of timeslots. For example if:
+ *
+ * - `this == Timeslot(7,20)`
+ * - `list == List(Timeslot(1,3), Timeslot(6,8), Timeslot(11,15))`
+ *
+ * the result will be: `List(Timeslot(9,10), Timeslot(15,20))`
+ */
+ def nonOverlappingTimeslots(list: List[Timeslot]): List[Timeslot] = {
+
+ def build(acc: List[Timeslot], listPart: List[Timeslot]): List[Timeslot] = {
+ list match {
+ case Nil => acc
+ case x :: Nil => computeGap1(x, this)
+ case x :: y :: rest =>
+ val gap = computeGap2(x, y, this)
+ build(acc ++ gap, y :: rest)
+ }
+ }
+
+ def computeGap1(x: Timeslot, to: Timeslot) : List[Timeslot] =
+ if (x.startsBefore(to) && x.endsBefore(to))
+ List(Timeslot(to.from, x.from))
+ else if (x.startsBefore(to) && x.endsAfter(to))
+ List()
+ else if (x.startsAfter(to) && x.endsAfter(to))
+ List(Timeslot(to.from, x.from))
+ else if (x.startsAfter(to) && x.endsBefore(to))
+ List(Timeslot(to.from, x.from), Timeslot(to.to, x.to))
+ else
+ List()
+
+ def computeGap2(x: Timeslot, y: Timeslot, to: Timeslot) : List[Timeslot] = List()
+
+ build(Nil, list)
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2011 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+
+package gr.grnet.aquarium.logic.test
+
+import gr.grnet.aquarium.util.TestMethods
+import org.junit.Assert._
+import org.junit.{Test}
+import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
+import java.util.Date
+
+/**
+ * Tests for the Timeslot class
+ *
+ * @author Georgios Gousios <gousiosg@gmail.com>
+ */
+class TimeslotTest extends TestMethods {
+
+ @Test
+ def testOverlappingTimeslots = {
+ var t = Timeslot(new Date(7), new Date(20))
+ val list = List(Timeslot(new Date(1), new Date(3)),
+ Timeslot(new Date(6), new Date(8)),
+ Timeslot(new Date(11), new Date(15)))
+
+ var result = t.overlappingTimeslots(list)
+ assertEquals(2, result.size)
+ assertEquals(Timeslot(new Date(7), new Date(8)), result.head)
+ assertEquals(Timeslot(new Date(11), new Date(15)), result.tail.head)
+
+ t = Timeslot(new Date(9), new Date(10))
+ result = t.overlappingTimeslots(list)
+ assertEquals(0, result.size)
+ }
+
+ @Test
+ def testNonOverlappingTimeslots = {
+ var t = Timeslot(new Date(7), new Date(20))
+ val list = List(Timeslot(new Date(1), new Date(3)),
+ Timeslot(new Date(6), new Date(8)),
+ Timeslot(new Date(11), new Date(15)))
+
+ //var result = t.nonOverlappingTimeslots(list)
+
+ }
+}
\ No newline at end of file