KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nightlabs > util > timepattern > TimePatternSet


1 /* ************************************************************************** *
2  * Copyright (C) 2005 NightLabs GmbH, Marco Schulze, Alexander Bieber *
3  * All rights reserved. *
4  * http://www.NightLabs.de *
5  * *
6  * This program and the accompanying materials are free software; you can re- *
7  * distribute it and/or modify it under the terms of the GNU General Public *
8  * License as published by the Free Software Foundation; either ver 2 of the *
9  * License, or any later version. *
10  * *
11  * This module is distributed in the hope that it will be useful, but WITHOUT *
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- *
13  * NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more *
14  * details. *
15  * *
16  * You should have received a copy of the GNU General Public License along *
17  * with this module; if not, write to the Free Software Foundation, Inc.: *
18  * 59 Temple Place, Suite 330 *
19  * Boston MA 02111-1307 *
20  * USA *
21  * *
22  * Or get it online: *
23  * http://www.opensource.org/licenses/gpl-license.php *
24  * *
25  * In case, you want to use this module or parts of it in a proprietary pro- *
26  * ject, you can purchase it under the NightLabs Commercial License. Please *
27  * contact NightLabs GmbH under info AT nightlabs DOT com for more infos or *
28  * visit http://www.NightLabs.com *
29  * ************************************************************************** */

30
31 /*
32  * Created on 02.06.2004
33  */

34 package com.nightlabs.util.timepattern;
35
36 import java.io.Serializable JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.Collection JavaDoc;
39 import java.util.Date JavaDoc;
40 import java.util.GregorianCalendar JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Set JavaDoc;
44
45 import com.nightlabs.util.timepattern.TimePattern.TimePeriod;
46
47 /**
48  * This class manages a set of TimePatternS to allow more flexibility in defining times.
49  * The patterns are combined by OR; this means, you can check the validity of a time stamp
50  * where it is reckoned to match, if one of the patterns matches.
51  * <br/><br/>
52  * If the TimePatternSet is empty (means it does not contain any TimePattern), the
53  * <code>matches(...)</code> method always returns <code>false</code> (means it never
54  * matches). To make it match always, create one empty pattern with the method
55  * <code>createTimePattern()</code>. The contract for an empty TimePattern is to always
56  * match.
57  *
58  * @author marco
59  */

60 public abstract class TimePatternSet
61     implements Serializable JavaDoc
62 {
63
64     public abstract Set JavaDoc getTimePatterns();
65
66     public TimePatternSet() { }
67     
68     public abstract TimePattern createTimePattern();
69     public abstract TimePattern createTimePattern(String JavaDoc _year, String JavaDoc _month, String JavaDoc _day, String JavaDoc _dayOfWeek, String JavaDoc _hour, String JavaDoc _minute) throws TimePatternFormatException;
70     
71     public void addTimePattern(TimePattern pattern)
72     {
73         if (pattern.getTimePatternSet() != null)
74             throw new IllegalStateException JavaDoc("Given TimePattern "+pattern+" is already associated with a TimePatternSet "+pattern.getTimePatternSet());
75         pattern.setTimePatternSet(this);
76         getTimePatterns().add(pattern);
77     }
78
79     /**
80      * This method checks a given timestamp whether it matches one of the patterns defined
81      * in this set. If this set is empty, this method returns always false.
82      *
83      * @param timeStamp The time to check whether it matches the patterns.
84      * @param maxInclude The maximum pattern part (YEAR-MINUTE) to check
85      * @return True, if one of the patterns in this set matches. Otherwise, false.
86      */

87     public boolean matches(long timeStamp, byte maxInclude)
88     {
89         for (Iterator JavaDoc it = getTimePatterns().iterator(); it.hasNext(); ) {
90             TimePattern pattern = (TimePattern) it.next();
91             if (pattern.matches(timeStamp,maxInclude))
92                 return true;
93         }
94         return false;
95     }
96     
97     public boolean matches(long timeStamp) {
98         return matches(timeStamp,TimePattern.MINUTE);
99     }
100
101     public static class CondensedPeriod
102     {
103         public CondensedPeriod() { }
104         public CondensedPeriod(Date JavaDoc _fromDT, Date JavaDoc _toDT)
105         {
106             this.fromDT = _fromDT;
107             this.toDT = _toDT;
108         }
109         
110         private Date JavaDoc fromDT;
111         private Date JavaDoc toDT;
112
113         /**
114          * @return Returns the fromDT.
115          */

116         public Date JavaDoc getFromDT() {
117             return fromDT;
118         }
119         /**
120          * @param fromDT The fromDT to set.
121          */

122         public void setFromDT(Date JavaDoc fromDT) {
123             this.fromDT = fromDT;
124         }
125         /**
126          * @return Returns the toDT.
127          */

128         public Date JavaDoc getToDT() {
129             return toDT;
130         }
131         /**
132          * @param toDT The toDT to set.
133          */

134         public void setToDT(Date JavaDoc toDT) {
135             this.toDT = toDT;
136         }
137     }
138     
139     protected static final int[] CALFIELDS = {
140             GregorianCalendar.MINUTE,
141             GregorianCalendar.HOUR_OF_DAY,
142             GregorianCalendar.DAY_OF_MONTH,
143             GregorianCalendar.MONTH,
144             GregorianCalendar.YEAR
145     };
146
147     public static int S_MIN = 0;
148     public static int S_HOUR = 1;
149     public static int S_DAY = 2;
150     public static int S_MONTH = 3;
151     public static int S_YEAR = 4;
152
153     protected static final int CPCOMP_MODE_UP = 1;
154     protected static final int CPCOMP_MODE_DOWN = -1;
155     
156     protected static class SimpleCalendar
157     {
158         protected GregorianCalendar JavaDoc cal;
159         
160         public SimpleCalendar()
161         {
162             cal = new GregorianCalendar JavaDoc();
163         }
164         
165         public int get(int fieldIdx)
166         {
167             int value = cal.get(CALFIELDS[fieldIdx]);
168             if (fieldIdx == S_MONTH)
169                 ++value;
170             return value;
171         }
172         
173         public void set(int fieldIdx, int value)
174         {
175             if (fieldIdx == S_MONTH)
176                 --value;
177             
178             cal.set(CALFIELDS[fieldIdx], value);
179             thisString = null;
180         }
181         
182         public int getActualMinimum(int fieldIdx)
183         {
184             if (fieldIdx == S_MONTH)
185                 return 1;
186             
187             if (fieldIdx == S_YEAR)
188                 return 1000;
189
190             return cal.getActualMinimum(CALFIELDS[fieldIdx]);
191         }
192         public int getActualMaximum(int fieldIdx)
193         {
194             if (fieldIdx == S_MONTH)
195                 return 12;
196             
197             if (fieldIdx == S_YEAR)
198                 return 3000;
199
200             return cal.getActualMaximum(CALFIELDS[fieldIdx]);
201         }
202         
203         public void setTime(Date JavaDoc date)
204         {
205             cal.setTime(date);
206             thisString = null;
207         }
208
209         public long getTimeInMillis()
210         {
211             return cal.getTimeInMillis();
212         }
213         public void setTimeInMillis(long millis)
214         {
215             cal.setTimeInMillis(millis);
216             thisString = null;
217         }
218         
219         String JavaDoc thisString = null;
220         /**
221          * @see java.lang.Object#toString()
222          */

223         public String JavaDoc toString() {
224             if (thisString == null) {
225                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc(this.getClass().getName());
226                 sb.append('{');
227                 sb.append(get(S_YEAR));
228                 sb.append('-');
229                 sb.append(get(S_MONTH));
230                 sb.append('-');
231                 sb.append(get(S_DAY));
232                 sb.append(' ');
233                 sb.append(get(S_HOUR));
234                 sb.append(':');
235                 sb.append(get(S_MIN));
236                 sb.append('}');
237                 thisString = sb.toString();
238             }
239             return thisString;
240         }
241     }
242     
243     public static final int YEAR_MIN = 1700;
244     public static final int YEAR_MAX = 2900;
245     
246     
247     /**
248      * This method adds as many TimePatterns as there are necessary to represent the given
249      * CondensedPeriod.
250      *
251      * @param cp The CondensedPeriod to add.
252      */

253     protected void addCondensedPeriod(CondensedPeriod cp)
254     {
255         if (cp.getFromDT().compareTo(cp.getToDT()) > 0)
256             throw new IllegalArgumentException JavaDoc("cp.fromDT > cp.toDT!!!");
257             
258         SimpleCalendar calFromDT = new SimpleCalendar();
259         calFromDT.setTime(cp.getFromDT());
260         SimpleCalendar calToDT = new SimpleCalendar();
261         calToDT.setTime(cp.getToDT());
262         SimpleCalendar calWork = new SimpleCalendar();
263         
264         if (calFromDT.get(S_YEAR) > YEAR_MAX)
265             throw new IllegalArgumentException JavaDoc("cp.fromDT.year > "+YEAR_MAX+"!");
266         
267         if (calFromDT.get(S_YEAR) < YEAR_MIN)
268             throw new IllegalArgumentException JavaDoc("cp.fromDT.year < "+YEAR_MIN+"!");
269         
270         if (calToDT.get(S_YEAR) > YEAR_MAX)
271             throw new IllegalArgumentException JavaDoc("cp.toDT.year > "+YEAR_MAX+"!");
272         
273         if (calToDT.get(S_YEAR) < YEAR_MIN)
274             throw new IllegalArgumentException JavaDoc("cp.toDT.year < "+YEAR_MIN+"!");
275
276         
277         List JavaDoc periodsModeUp = new ArrayList JavaDoc();
278         List JavaDoc periodsModeDown = new ArrayList JavaDoc();
279         boolean isFirstFieldIdx = true;
280         int diffFieldIdx = 0; boolean exitMode = false;
281         int mode = CPCOMP_MODE_UP;
282         int highestFieldIdxModeUp = 0;
283         boolean addPeriod = true;
284 // boolean lastRowHadCompleteField = false;
285
while (diffFieldIdx <= CALFIELDS.length) {
286 // lastRowHadCompleteField = false;
287
addPeriod = true;
288             SimpleCalendar calSource;
289             SimpleCalendar calDest;
290
291             if (mode == CPCOMP_MODE_UP) {
292                 calSource = calFromDT;
293                 calDest = calToDT;
294             }
295             else {
296                 calSource = calToDT;
297                 calDest = calFromDT;
298             }
299
300             calWork.setTimeInMillis(calSource.getTimeInMillis());
301
302             TimePeriod[] fieldPeriods = new TimePeriod[CALFIELDS.length];
303             for (int fieldIdx = 0; fieldIdx < CALFIELDS.length; ++fieldIdx) {
304                 if (fieldIdx < diffFieldIdx) {
305                     fieldPeriods[fieldIdx] = new TimePattern.TimePeriod(-1, -1); // becomes "*"
306
calWork.set(fieldIdx, calDest.get(fieldIdx));
307                 }
308                 else if (fieldIdx > diffFieldIdx) {
309                     int i = calWork.get(fieldIdx);
310                     fieldPeriods[fieldIdx] = new TimePattern.TimePeriod(i, i);
311                 }
312                 else {
313                     int from = calWork.get(fieldIdx);
314                     boolean currFieldIsComplete = false;
315                     
316                     if (isFirstFieldIdx) {
317 // if (!lastRowHadCompleteField)
318
isFirstFieldIdx = false;
319                     }
320                     else
321                         from += mode;
322
323                     if (from == (mode == CPCOMP_MODE_UP ? calWork.getActualMinimum(fieldIdx) : calWork.getActualMaximum(fieldIdx)))
324                     {
325                         calWork.set(fieldIdx, calSource.get(fieldIdx));
326 // if (mode == CPCOMP_MODE_UP)
327
// addPeriod = false;
328
// lastRowHadCompleteField = true;
329
currFieldIsComplete = true;
330                     }
331
332                     int to = mode == CPCOMP_MODE_UP ? calWork.getActualMaximum(fieldIdx) : calWork.getActualMinimum(fieldIdx);
333                     if (mode * from > mode * to) {
334                         addPeriod = false;
335                         fieldPeriods = null;
336                         break;
337                     }
338                     calWork.set(fieldIdx, to);
339                     if (mode * calWork.getTimeInMillis() >= mode * calDest.getTimeInMillis())
340                     {
341                         to = calDest.get(fieldIdx) - mode;
342                         exitMode = true;
343                     }
344                     
345                     if (mode * from > mode * to) {
346                         addPeriod = false;
347                         fieldPeriods = null;
348                         break;
349                     }
350                     
351                     if (mode == CPCOMP_MODE_DOWN) {
352                         int i = from;
353                         from = to;
354                         to = i;
355                     }
356                     if (currFieldIsComplete) {
357                         currFieldIsComplete = false;
358                         fieldPeriods[fieldIdx] = new TimePattern.TimePeriod(-1, -1); // becomes "*"
359
}
360                     else {
361                         fieldPeriods[fieldIdx] = new TimePattern.TimePeriod(from, to);
362                     }
363                 }
364             }
365             
366             if (addPeriod && fieldPeriods != null) {
367                 // DEBUG
368
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
369                 for (int i = 0; i < fieldPeriods.length; ++i) {
370                     sb.append('[');
371                     sb.append(fieldPeriods[i].getFrom());
372                     sb.append(',');
373                     sb.append(fieldPeriods[i].getTo());
374                     sb.append(']');
375                     sb.append(' ');
376                 }
377                 System.out.println(sb.toString());
378                 // END DEBUG
379

380                 if (mode == CPCOMP_MODE_UP)
381                     periodsModeUp.add(0, fieldPeriods);
382                 else
383                     periodsModeDown.add(0, fieldPeriods);
384             }
385
386             if (mode == CPCOMP_MODE_UP && exitMode) {
387                 exitMode = false;
388                 mode = CPCOMP_MODE_DOWN;
389                 highestFieldIdxModeUp = diffFieldIdx;
390                 diffFieldIdx = -1;
391                 isFirstFieldIdx = true;
392             }
393             
394             ++diffFieldIdx;
395             if (mode == CPCOMP_MODE_DOWN && diffFieldIdx >= highestFieldIdxModeUp)
396                 break;
397
398         } // while (diffFieldIdx < CALENDARFIELDS.length) {
399

400         for (int m = 0; m < 2; ++m) {
401             List JavaDoc srcPeriods = m == 0 ? periodsModeUp : periodsModeDown;
402
403             for (int periodIdx = 0; periodIdx < srcPeriods.size(); ++periodIdx) {
404                 TimePeriod[] fieldPeriods0 = (TimePeriod[])srcPeriods.get(periodIdx);
405                 if (periodIdx + 1 < srcPeriods.size()) {
406                     TimePeriod[] fieldPeriods1 = (TimePeriod[])srcPeriods.get(periodIdx + 1);
407                     DoubleWildCardCount wcc = countWildCards(fieldPeriods0, fieldPeriods1);
408                     if (wcc.wildCardCount0 == wcc.wildCardCount1) {
409                         if (fieldPeriods0[wcc.wildCardCount0].getTo() + 1 == fieldPeriods1[wcc.wildCardCount1].getFrom()) {
410                             fieldPeriods0[wcc.wildCardCount0].setTo(fieldPeriods1[wcc.wildCardCount1].getTo());
411                             makeWildCards(fieldPeriods0);
412                             srcPeriods.remove(periodIdx + 1);
413                         }
414                         if (fieldPeriods0[wcc.wildCardCount0].getFrom() == fieldPeriods1[wcc.wildCardCount1].getTo() + 1) {
415                             fieldPeriods0[wcc.wildCardCount0].setFrom(fieldPeriods1[wcc.wildCardCount1].getFrom());
416                             makeWildCards(fieldPeriods1);
417                             srcPeriods.remove(periodIdx + 1);
418                         }
419                     }
420                 }
421             }
422         }
423         
424         if (!periodsModeUp.isEmpty() && !periodsModeDown.isEmpty()) {
425             TimePeriod[] fieldPeriods0 = (TimePeriod[])periodsModeUp.get(0);
426             TimePeriod[] fieldPeriods1 = (TimePeriod[])periodsModeDown.get(0);
427             DoubleWildCardCount wcc = countWildCards(fieldPeriods0, fieldPeriods1);
428             if (wcc.wildCardCount0 == wcc.wildCardCount1) {
429                 if (fieldPeriods0[wcc.wildCardCount0].getTo() + 1 == fieldPeriods1[wcc.wildCardCount1].getFrom()) {
430                     fieldPeriods0[wcc.wildCardCount0].setTo(fieldPeriods1[wcc.wildCardCount1].getTo());
431                     makeWildCards(fieldPeriods0);
432                     periodsModeDown.remove(0);
433                 }
434                 if (fieldPeriods0[wcc.wildCardCount0].getFrom() == fieldPeriods1[wcc.wildCardCount1].getTo() + 1) {
435                     fieldPeriods0[wcc.wildCardCount0].setFrom(fieldPeriods1[wcc.wildCardCount1].getFrom());
436                     makeWildCards(fieldPeriods0);
437                     periodsModeDown.remove(0);
438                 }
439             }
440         }
441     
442 // for (Iterator it = periods.iterator(); it.hasNext(); )
443
// createTimePatternFromFieldPeriods((TimePeriod[]) it.next());
444

445         System.out.println("TimePeriods in mode UP:");
446         for (Iterator JavaDoc it = periodsModeUp.iterator(); it.hasNext(); )
447             createTimePatternFromFieldPeriods((TimePeriod[]) it.next());
448
449         System.out.println("TimePeriods in mode DOWN:");
450         for (Iterator JavaDoc it = periodsModeDown.iterator(); it.hasNext(); )
451             createTimePatternFromFieldPeriods((TimePeriod[]) it.next());
452     }
453     
454     protected static void makeWildCards(TimePeriod[] periods)
455     {
456         SimpleCalendar cal = new SimpleCalendar();
457         int diffFieldIdx = -1;
458         for (int i = CALFIELDS.length - 1; i >= 0; --i) {
459             if (periods[i].getFrom() >= 0) {
460                 cal.set(i, periods[i].getFrom());
461                 if (periods[i].getFrom() != periods[i].getTo())
462                     diffFieldIdx = i;
463             }
464             else
465                 cal.set(i, cal.getActualMinimum(i));
466         }
467         if (diffFieldIdx >= 0) {
468             if (periods[diffFieldIdx].getFrom() == cal.getActualMinimum(diffFieldIdx) &&
469                     periods[diffFieldIdx].getTo() == cal.getActualMaximum(diffFieldIdx)) {
470                 periods[diffFieldIdx].setFrom(-1);
471                 periods[diffFieldIdx].setTo(-1);
472             }
473         }
474     }
475
476     protected static class DoubleWildCardCount
477     {
478         public DoubleWildCardCount(int _wildCardCount0, int _wildCardCount1)
479         {
480             wildCardCount0 = _wildCardCount0;
481             wildCardCount1 = _wildCardCount1;
482         }
483         public int wildCardCount0;
484         public int wildCardCount1;
485     }
486     
487     protected static DoubleWildCardCount countWildCards(TimePeriod[] periods0, TimePeriod[] periods1)
488     {
489         int wildCardCount0 = 0;
490         int wildCardCount1 = 0;
491         for (int i = 0; i < CALFIELDS.length; ++i) {
492             if (periods0[i].getFrom() < 0)
493                 wildCardCount0 = i + 1;
494             if (periods1[i].getFrom() < 0)
495                 wildCardCount1 = i + 1;
496             
497             if (periods0[i].getFrom() >= 0 && periods1[i].getFrom() >= 0)
498                 break;
499         }
500         return new DoubleWildCardCount(wildCardCount0, wildCardCount1);
501     }
502
503     protected void createTimePatternFromFieldPeriods(TimePeriod[] fieldPeriods)
504     {
505         String JavaDoc[] fieldPeriodsStr = new String JavaDoc[fieldPeriods.length];
506
507         for (int i = 0; i < fieldPeriods.length; ++i) {
508             int from = fieldPeriods[i].getFrom();
509             if (from < 0)
510                 fieldPeriodsStr[i] = "*";
511             else {
512                 int to = fieldPeriods[i].getTo();
513                 if (from == to)
514                     fieldPeriodsStr[i] = Integer.toString(from);
515                 else {
516                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc(Integer.toString(from));
517                     if (from != to)
518                         sb.append('-').append(Integer.toString(to));
519                     fieldPeriodsStr[i] = sb.toString();
520                 }
521             }
522         }
523
524         try {
525             System.out.println(
526                     createTimePattern(
527                             fieldPeriodsStr[S_YEAR],
528                             fieldPeriodsStr[S_MONTH],
529                             fieldPeriodsStr[S_DAY],
530                             "*",
531                             fieldPeriodsStr[S_HOUR],
532                             fieldPeriodsStr[S_MIN]));
533         } catch (TimePatternFormatException e) {
534             throw new RuntimeException JavaDoc("Something within the method \"addCondensedPeriod(...)\" went really wrong!", e);
535         }
536     }
537
538     public void setCondensedPeriod(CondensedPeriod condensedPeriod)
539     {
540         setCondensedPeriods(new CondensedPeriod[] {condensedPeriod});
541     }
542
543     public void setCondensedPeriods(CondensedPeriod[] condensedPeriods)
544     {
545         getTimePatterns().clear();
546         
547         for (int i = 0; i < condensedPeriods.length; ++i) {
548             addCondensedPeriod(condensedPeriods[i]);
549         }
550     }
551
552     public void setCondensedPeriods(Collection JavaDoc condensedPeriods)
553     {
554         getTimePatterns().clear();
555         
556         for (Iterator JavaDoc it = condensedPeriods.iterator(); it.hasNext(); ) {
557             CondensedPeriod cp = (CondensedPeriod)it.next();
558             addCondensedPeriod(cp);
559         }
560     }
561
562     public Collection JavaDoc getCondensedPeriods()
563     {
564         ArrayList JavaDoc periods = new ArrayList JavaDoc();
565         
566         return periods;
567     }
568 }
569
Popular Tags