View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.custom.schedule.model;
21  
22  import java.io.Serializable;
23  import java.util.Calendar;
24  import java.util.Collection;
25  import java.util.Date;
26  import java.util.Iterator;
27  import java.util.SortedSet;
28  import java.util.TimeZone;
29  import java.util.TreeSet;
30  
31  import org.apache.myfaces.custom.schedule.util.ScheduleUtil;
32  
33  /**
34   * <p>
35   * Extend this class to create your own implementation of a ScheduleModel
36   * </p>
37   * 
38   * @author Jurgen Lust (latest modification by $Author: baranda $)
39   * @version $Revision: 372589 $
40   */
41  public abstract class AbstractScheduleModel implements ScheduleModel,
42          Serializable
43  {
44      // ~ Instance fields
45      // --------------------------------------------------------
46  
47      private TreeSet days;
48  
49      private Date selectedDate = new Date();
50  
51      private ScheduleEntry selectedEntry;
52  
53      private int mode;
54  
55      protected final TimeZone timeZone;
56  
57      // ~ Constructors
58      // -----------------------------------------------------------
59  
60      /**
61       * Creates a new AbstractScheduleModel object.
62       */
63      public AbstractScheduleModel()
64      {
65          this(TimeZone.getDefault());
66      }
67  
68      public AbstractScheduleModel(TimeZone timeZone)
69      {
70        this.timeZone = timeZone;
71      }
72  
73      // ~ Methods
74      // ----------------------------------------------------------------
75  
76      /**
77       * Get the set of days. Initialise on first call.
78       * 
79       */
80      protected SortedSet getDays()
81      {
82          if (days == null)
83          {
84              days = new TreeSet();
85              
86              switch (mode)
87              {
88              case DAY:
89                  setDay(this.selectedDate);
90  
91                  break;
92  
93              case WORKWEEK:
94                  setWorkWeek(this.selectedDate);
95  
96                  break;
97  
98              case WEEK:
99                  setWeek(this.selectedDate);
100 
101                 break;
102 
103             case MONTH:
104                 setMonth(this.selectedDate);
105 
106                 break;
107 
108             default:
109                 setDay(this.selectedDate);
110             }        
111         }
112         
113         return days;
114     }
115     
116     /**
117      * Returns the timezone setting for this model
118      */
119     public TimeZone getTimeZone ()
120     {
121       return this.timeZone;
122     }
123 
124     /**
125      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#isEmpty()
126      */
127     public boolean isEmpty()
128     {
129         return getDays().isEmpty();
130     }
131 
132     /**
133      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#setMode(int)
134      */
135     public void setMode(int mode)
136     {
137         this.mode = mode;
138     }
139 
140     /**
141      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#getMode()
142      */
143     public int getMode()
144     {
145         return mode;
146     }
147 
148     /**
149      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#setSelectedDate(java.util.Date)
150      */
151     public void setSelectedDate(Date date)
152     {
153         if (date == null)
154         {
155             // do nothing when the date is null
156             return;
157         }
158 
159         this.selectedDate = date;
160         this.days = null;
161     }
162 
163     /**
164      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#getSelectedDate()
165      */
166     public Date getSelectedDate()
167     {
168         return selectedDate;
169     }
170 
171     /**
172      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#setSelectedEntry(org.apache.myfaces.custom.schedule.model.ScheduleEntry)
173      */
174     public void setSelectedEntry(ScheduleEntry selectedEntry)
175     {
176         this.selectedEntry = selectedEntry;
177     }
178 
179     /**
180      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#getSelectedEntry()
181      */
182     public ScheduleEntry getSelectedEntry()
183     {
184         return selectedEntry;
185     }
186     
187     /**
188      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#isEntrySelected()
189      */
190     public boolean isEntrySelected() {
191         return getSelectedEntry() != null;
192     }
193 
194     /**
195      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#containsDate(java.util.Date)
196      */
197     public boolean containsDate(Date date)
198     {
199         for (Iterator iterator = iterator(); iterator.hasNext();)
200         {
201             ScheduleDay day = (ScheduleDay) iterator.next();
202 
203             if (day.equalsDate(date))
204             {
205                 return true;
206             }
207         }
208 
209         return false;
210     }
211 
212     /**
213      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#get(int)
214      */
215     public Object get(int index)
216     {
217         Object[] dayArray = getDays().toArray();
218 
219         Object returnObject = dayArray[index];
220 
221         return returnObject;
222     }
223 
224     /**
225      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#iterator()
226      */
227     public Iterator iterator()
228     {
229         return getDays().iterator();
230     }
231 
232     /**
233      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#size()
234      */
235     public int size()
236     {
237         return getDays().size();
238     }
239 
240     /**
241      * <p>
242      * Set the day
243      * </p>
244      * 
245      * @param date
246      *            the new day
247      */
248     protected void setDay(Date date)
249     {
250         if (date == null)
251         {
252             return;
253         }
254 
255         clear();
256 
257         ScheduleDay day = add(date);
258         load(day.getDayStart(), day.getDayEnd());
259     }
260 
261     /**
262      * <p>
263      * navigate to the specified month
264      * </p>
265      * 
266      * @param date
267      *            the date to navigate to
268      */
269     protected void setMonth(Date date)
270     {
271         if (date == null)
272         {
273             return;
274         }
275 
276         clear();
277 
278         Calendar cal = getCalendarInstance(date);
279 
280         // go back to the first day of the month;
281         cal.set(Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DAY_OF_MONTH));
282 
283         Date temp = cal.getTime();
284         cal.add(Calendar.MONTH, 1);
285         int nextMonth = cal.get(Calendar.MONTH);
286         cal.setTime(temp);
287 
288         ScheduleDay firstDay = null;
289         ScheduleDay lastDay = null;
290         
291         // we want to show the whole first week, including the days from the previous month
292         cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
293 
294         while (true)
295         {
296             ScheduleDay addedDay = add(cal.getTime());
297 
298             if (firstDay == null)
299             {
300                 firstDay = addedDay;
301             }
302 
303             lastDay = addedDay;
304             cal.add(Calendar.DATE, 1);
305             
306             //stop when we are at the last day of the last week
307             if (cal.get(Calendar.MONTH) == nextMonth && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY)
308             {
309                    break;
310             }
311         }
312 
313         load(firstDay.getDayStart(), lastDay.getDayEnd());
314     }
315 
316     /**
317      * <p>
318      * navigate to the specified week
319      * </p>
320      * 
321      * @param date
322      *            the date to navigate to
323      */
324     protected void setWeek(Date date)
325     {
326         if (date == null)
327         {
328             return;
329         }
330 
331         clear();
332 
333         Calendar cal = getCalendarInstance(date);
334 
335         // go back to the monday of this week
336         cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
337 
338         ScheduleDay firstDay = null;
339         ScheduleDay lastDay = null;
340 
341         for (int i = 0; i < 7; i++)
342         {
343             ScheduleDay addedDay = add(cal.getTime());
344 
345             if (firstDay == null)
346             {
347                 firstDay = addedDay;
348             }
349 
350             lastDay = addedDay;
351             cal.add(Calendar.DATE, 1);
352         }
353 
354         load(firstDay.getDayStart(), lastDay.getDayEnd());
355     }
356 
357     /**
358      * <p>
359      * navigate to the specified workweek
360      * </p>
361      * 
362      * @param date
363      *            the date to navigate to
364      */
365     protected void setWorkWeek(Date date)
366     {
367         if (date == null)
368         {
369             return;
370         }
371 
372         clear();
373 
374         Calendar cal = getCalendarInstance(date);
375 
376         // go back to the monday of this week
377         cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
378 
379         ScheduleDay firstDay = null;
380         ScheduleDay lastDay = null;
381 
382         for (int i = 0; i < 5; i++)
383         {
384             ScheduleDay addedDay = add(cal.getTime());
385 
386             if (firstDay == null)
387             {
388                 firstDay = addedDay;
389             }
390 
391             lastDay = addedDay;
392             cal.add(Calendar.DATE, 1);
393         }
394 
395         load(firstDay.getDayStart(), lastDay.getDayEnd());
396     }
397 
398     /**
399      * <p>
400      * Add a day to the schedule
401      * </p>
402      * 
403      * @param date
404      *            the day to add
405      * 
406      * @return the day that was added
407      */
408     protected ScheduleDay add(Date date)
409     {
410         if (date == null)
411         {
412             return null;
413         }
414 
415         ScheduleDay day = new ScheduleDay(date, getTimeZone());
416         loadDayAttributes(day);
417         getDays().add(day);
418 
419         return day;
420     }
421 
422     /**
423      * <p>
424      * Remove all days
425      * </p>
426      */
427     protected void clear()
428     {
429         if (days != null)
430         {
431             for (Iterator dayIterator = days.iterator(); dayIterator.hasNext();)
432             {
433                 ScheduleDay day = (ScheduleDay) dayIterator.next();
434                 day.clear();
435             }
436 
437             days.clear();
438         }
439     }
440 
441     /**
442      * @see org.apache.myfaces.custom.schedule.model.ScheduleModel#refresh()
443      */
444     public void refresh()
445     {
446         setSelectedDate(selectedDate);
447     }
448 
449     /**
450      * <p>
451      * Load the schedule entries that fall between the startDate and the
452      * endDate.
453      * </p>
454      * 
455      * @param startDate
456      *            0 AM on the start date
457      * @param endDate
458      *            12 PM on the end date
459      */
460     protected abstract Collection loadEntries(Date startDate, Date endDate);
461 
462     /**
463      * <p>
464      * Load any attributes for this day: is it a working day or a holiday, and
465      * what is the name of the day (e.g. "Christmas").
466      * </p>
467      * 
468      * @param day
469      *            the day that should be loaded
470      */
471     protected abstract void loadDayAttributes(Day day);
472 
473     /**
474      * @return true, if each day contains the same set of intervals
475      */
476     public boolean containsRepeatedIntervals() {
477         boolean firstDay = true;
478         TreeSet firstDayIntervals = null;
479         
480         if (mode == DAY)
481         {
482             return true;
483         }
484         
485         for (Iterator dayIterator = iterator(); dayIterator.hasNext(); )
486         {
487             Day day = (Day) dayIterator.next();
488             
489             if (firstDay)
490             {
491                 firstDayIntervals = day.getIntervals();
492                 firstDay = false;
493             }
494             else
495             {
496                 if (firstDayIntervals == null || firstDayIntervals.size() == 0) {
497                     if (day.getIntervals() != null && day.getIntervals().size() > 0)
498                     {
499                         return false;
500                     }
501                 }
502                 else if (!ScheduleUtil.areEquivalentIntervals(firstDayIntervals, day.getIntervals()))
503                 {
504                     
505                     return false;
506                 }
507             }
508         }
509         
510         return true;
511     }
512     
513     private void load(Date startDate, Date endDate)
514     {
515         Collection entries = loadEntries(startDate, endDate);
516 
517         for (Iterator entryIterator = entries.iterator(); entryIterator
518                 .hasNext();)
519         {
520             ScheduleEntry entry = (ScheduleEntry) entryIterator.next();
521 
522             for (Iterator dayIterator = getDays().iterator(); dayIterator.hasNext();)
523             {
524                 ScheduleDay day = (ScheduleDay) dayIterator.next();
525 
526                 day.addEntry(entry);
527             }
528         }
529     }
530     
531     protected Calendar getCalendarInstance(Date date) {
532 
533         return ScheduleUtil.getCalendarInstance(date, getTimeZone());
534     }
535 }
536 // The End