Fix a compilation error (did not implement a MemStore method)
[aquarium] / src / main / scala / gr / grnet / aquarium / logic / accounting / dsl / DSLCronSpec.scala
1 /*
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35
36 package gr.grnet.aquarium.logic.accounting.dsl
37
38 import org.quartz.CronExpression
39 import java.util.Date
40
41 /**
42  * @author Prodromos Gerakios <pgerakios@grnet.gr>
43  */
44
45 case class DSLCronSpec(cronSpec: String) {
46
47     private val cronExpr = {
48       val e = "00 " + cronSpec.trim //IMPORTANT: WE DO NOT CARE ABOUT SECONDS!!!
49       val l = e.split(" ")
50       assert(l.size == 6,"Invalid cron specification")
51       //for {ll <- l } Console.err.println(ll)
52       (l(3),l(5))  match {
53         case ("?",_) | (_,"?") => ()
54         case (_,"*") => l.update(5,"?")
55         case ("*",_) => l.update(3,"?")
56       }
57       val e1 = l.foldLeft("") { (s,elt) => s + " " + elt}
58       //Console.err.println("e = " + e + " and e1 = " + e1)
59       new CronExpression(e1)
60     }
61
62     def includes(d:Date) : Boolean =
63       cronExpr isSatisfiedBy d
64
65   /* the next valid date cannot outlive (min,max)*/
66   def nextValidDate(min0:Date,max0:Date,d:Date) : Option[Date] =
67     (cronExpr getNextValidTimeAfter d) match {
68       case null =>
69         None
70       case d1 =>
71         val (min,max,e) = (min0.getTime,max0.getTime,d1.getTime)
72         if(e < min || e>max)
73           None
74         else
75           Some({assert(d1.getTime>=d.getTime);d1})
76     }
77
78   /*def nextValidDate(d:Date) : Date = {
79    val ret = cronExpr getNextValidTimeAfter d
80    ret
81  } */
82
83   /*def nextContinuousValidDate(d:Date) : Date = {
84       val d1 = cronExpr getNextInvalidTimeAfter d
85       if (d1 != null)
86         d1.setTime(d1.getTime - 1000) /* 1 sec before was valid so return this*/
87       d1
88     }
89
90
91     def getMaxValidBeforeDate(min0:Date , max0:Date,d:Date) : Option[Date] ={
92       val (min,max,e) = (min0.getTime,max0.getTime,d.getTime)
93       if(min > e || max < e) None
94       else if(includes(d)) Some(d)
95       else {
96         var end = e
97         var start = min //0L
98         var best:Date = null
99         var iterations=0L
100         val tmp = new Date(0L)
101         val step = 10000L * 60L // 1 minute
102         while(start < end) {
103           iterations += 1
104           val pivot = (end - start) / 2 + start
105           tmp.setTime(pivot)
106           val next = nextValidDate(tmp)
107           if(next == null){ /* no valid time after pivot*/
108             end = pivot-step; // pivot minus one
109           } else {
110             val p = next.getTime()
111             if(p < e) { /* next date occurs before e*/
112               val post =  next.getTime < d.getTime
113               assert(post,"BUG!!!")
114               best = next
115               start = p + step
116             } else if( p > e) { /* next date occurs after e*/
117               end = pivot-step
118             }
119             else assert(false,"This should not happen")
120           }
121         //  System.err.println("Start: " + new Date(start) + " end: " + new Date(end));
122         }
123         System.err.println("Iterations " + iterations);
124         if(best!=null) Some(best) else None
125       }
126     }
127     */
128 }
129
130 object DSLCronSpec {
131   val emptyCronSpec = new DSLCronSpec("? ? ? ? ?")
132 }