import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
import scala.collection.immutable.{TreeMap, SortedMap}
+import scala.collection.mutable.ListBuffer
+import scala.annotation.tailrec
/**
*
* The head role is the most recent. The same rule applies for the tail.
*/
roles: List[RoleHistoryItem]) {
- def rolesByTimeslot: SortedMap[Timeslot, String] = {
- TreeMap(roles.map(role => (role.timeslot, role.name)): _*)
+
+ def roleNamesByTimeslot: SortedMap[Timeslot, String] = {
+ TreeMap(roles.map(role ⇒ (role.timeslot, role.name)): _*)
}
- /**
- * Insert the new role in front of the other ones and adjust the `validTo` limit of the previous role.
- */
- def addMostRecentRole(role: String, validFrom: Long) = {
- val newItem = RoleHistoryItem(role, validFrom)
- val newRoles = roles match {
- case head :: tail ⇒
- newItem :: head.withNewValidTo(validFrom) :: tail
+ def rolesByTimeslot: SortedMap[Timeslot, RoleHistoryItem] = {
+ TreeMap(roles.map(role ⇒ (role.timeslot, role)): _*)
+ }
+
+ def updateWithRole(role: String, validFrom: Long) = {
+ def fixValidTo(validFrom: Long, validTo: Long): Long = {
+ if(validTo == validFrom) {
+ // Since validTo is exclusive, make at least 1ms gap
+ validFrom + 1
+ } else {
+ validTo
+ }
+ }
+ val newItems = roles match {
case Nil ⇒
- newItem :: Nil
+ RoleHistoryItem(role, validFrom) :: Nil
+
+ case head :: tail ⇒
+ if(head.startsStrictlyAfter(validFrom)) {
+ // must search history items to find where this fits in
+ @tailrec
+ def check(allChecked: ListBuffer[RoleHistoryItem],
+ lastCheck: RoleHistoryItem,
+ toCheck: List[RoleHistoryItem]): List[RoleHistoryItem] = {
+
+ toCheck match {
+ case Nil ⇒
+ allChecked.append(RoleHistoryItem(role, validFrom, fixValidTo(validFrom, lastCheck.validFrom)))
+ allChecked.toList
+
+ case toCheckHead :: toCheckTail ⇒
+ if(toCheckHead.startsStrictlyAfter(validFrom)) {
+ allChecked.append(toCheckHead)
+
+ check(allChecked, toCheckHead, toCheckTail)
+ } else {
+ allChecked.append(RoleHistoryItem(role, validFrom, fixValidTo(validFrom, lastCheck.validFrom)))
+ allChecked.toList
+ }
+ }
+ }
+
+ val buffer = new ListBuffer[RoleHistoryItem]
+ buffer.append(head)
+ check(buffer, head, tail)
+ } else {
+ // assume head.validTo goes to infinity,
+ RoleHistoryItem(role, validFrom) :: head.copyWithValidTo(fixValidTo(head.validFrom, validFrom)) :: tail
+ }
}
- RoleHistory(newRoles)
+ RoleHistory(newItems)
+ }
+
+ /**
+ * Returns the first, chronologically, role.
+ */
+ def firstRole: Option[RoleHistoryItem] = {
+ rolesByTimeslot.valuesIterator.toList.lastOption
+ }
+
+ /**
+ * Returns the name of the first, chronologically, role.
+ */
+ def firstRoleName: Option[String] = {
+ roleNamesByTimeslot.valuesIterator.toList.lastOption
+ }
+
+ /**
+ * Returns the last, chronologically, role.
+ */
+ def lastRole: Option[RoleHistoryItem] = {
+ rolesByTimeslot.valuesIterator.toList.headOption
+ }
+
+ /**
+ * Returns the name of the last, chronologically, role.
+ */
+ def lastRoleName: Option[String] = {
+ roleNamesByTimeslot.valuesIterator.toList.headOption
}
}