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  
23  import java.io.Serializable;
24  
25  import java.util.ArrayList;
26  import java.util.Calendar;
27  import java.util.Date;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.TimeZone;
31  import java.util.TreeSet;
32  
33  import org.apache.myfaces.custom.schedule.util.ScheduleEntryComparator;
34  
35  
36  /**
37   * <p>
38   * This class represents one day in the schedule component
39   * </p>
40   *
41   * @author Jurgen Lust (latest modification by $Author: werpu $)
42   * @version $Revision: 371736 $
43   */
44  public class ScheduleDay
45      extends Day
46      implements Serializable, Comparable
47  {
48      //~ Instance fields --------------------------------------------------------
49  
50      /**
51       * serial id for serialisation versioning
52       */
53      private static final long serialVersionUID = 1L;
54      private final TreeSet entries;
55  
56      //~ Constructors -----------------------------------------------------------
57  
58      /**
59       * Creates a new ScheduleDay object.
60       *
61       * @param date the date
62       */
63      public ScheduleDay(Date date)
64      {
65          this(date, TimeZone.getDefault());
66      }
67  
68      /**
69       * Creates a new ScheduleDay object.
70       *
71       * @param date the date
72       */
73      public ScheduleDay(Date date, TimeZone tz)
74      {
75          super(date, tz);
76          this.entries = new TreeSet(new ScheduleEntryComparator());
77      }
78  
79      //~ Methods ----------------------------------------------------------------
80  
81      /**
82       * @return true if there are no schedule entries
83       */
84      public boolean isEmpty()
85      {
86          return entries.isEmpty();
87      }
88  
89      /**
90       * <p>
91       * Add an entry to this day
92       * </p>
93       *
94       * @param entry the entry to add
95       *
96       * @return true if successful
97       */
98      public boolean addEntry(ScheduleEntry entry)
99      {
100         if (
101             (entry == null) || (entry.getStartTime() == null) ||
102                 (entry.getEndTime() == null)
103         ) {
104             return false;
105         }
106 
107         Calendar cal = getCalendarInstance(entry.getEndTime());
108         cal.add(Calendar.DATE, 1);
109         cal.set(Calendar.HOUR_OF_DAY, 0);
110         cal.set(Calendar.MINUTE, 0);
111         cal.set(Calendar.SECOND, 0);
112         cal.set(Calendar.MILLISECOND, 0);
113 
114         Date endDate = cal.getTime();
115         cal.setTime(entry.getStartTime());
116 
117         while (cal.getTime().before(endDate)) {
118             if (equalsDate(cal.getTime())) {
119                 entries.add(entry);
120 
121                 return true;
122             }
123 
124             cal.add(Calendar.DATE, 1);
125         }
126 
127         return false;
128     }
129 
130     /**
131      * <p>
132      * Remove all entries from this day
133      * </p>
134      */
135     public void clear()
136     {
137         entries.clear();
138     }
139 
140     /**
141      * @return an iterator for the schedule entries of this day
142      */
143     public Iterator iterator()
144     {
145         return entries.iterator();
146     }
147 
148     /**
149      * <p>
150      * Remove an entry from this day
151      * </p>
152      *
153      * @param entry the entry to remove
154      *
155      * @return true if successful
156      */
157     public boolean remove(ScheduleEntry entry)
158     {
159         return entries.remove(entry);
160     }
161 
162     /**
163      * @return the number of entries that are shown on this day
164      */
165     public int size()
166     {
167         return entries.size();
168     }
169     
170     /**
171      * Get the non-inclusive hour by which all events on this day have completed.
172      * All day events are not included, as their end time is implicit.
173      * 
174      * @return From 0, where there are no events and 24 where events exist up to the last hour
175      */
176     public int getLastEventHour()
177     {
178         // Check all events, as the last to finish may not be the last to begin
179         Date lastEnd = null;
180         
181         for (Iterator it = entries.iterator(); it.hasNext(); ) {
182             ScheduleEntry next = (ScheduleEntry) it.next();
183             
184             if (!next.isAllDay() && (lastEnd == null || lastEnd.before(next.getEndTime()))) {
185                 lastEnd = next.getEndTime();
186             }
187         }
188         if (lastEnd == null) {
189             
190             return 0;
191         }
192         
193         Calendar endTime = getCalendarInstance(lastEnd);
194         
195         if (endTime.get(Calendar.MINUTE) > 0){
196             // Round up to next hour
197             endTime.add(Calendar.HOUR_OF_DAY, 1);
198         }
199 
200         return equalsDate(endTime.getTime()) ? endTime.get(Calendar.HOUR_OF_DAY) : 24;        
201     }
202     
203     /**
204      * Get the inclusive hour in which the first event on this day starts.
205      * All day events are not included, as their start time is implicit.
206      * 
207      * @return From 0, where there is an event in the first hour to 24 where there are no events
208      */
209     public int getFirstEventHour()
210     {
211         Calendar startTime = null;
212 
213         for (Iterator it = entries.iterator(); it.hasNext(); ) {
214             ScheduleEntry next = (ScheduleEntry) it.next();
215             
216             if (!next.isAllDay()) {
217                 startTime = getCalendarInstance(next.getStartTime());
218                 break;
219             }
220         }
221 
222         if (startTime == null) {
223             
224             return 24;
225         }
226 
227         return equalsDate(startTime.getTime()) ? startTime.get(Calendar.HOUR_OF_DAY) : 0;
228     }
229 
230     public Interval getInterval(Date clickedDate)
231     {
232         if (getIntervals() != null)
233         {
234             for (Iterator intervalIt = getIntervals().iterator(); intervalIt.hasNext(); )
235             {
236                 Interval interval = (Interval) intervalIt.next();
237 
238                 if (interval.containsDate(clickedDate)) {
239 
240                     return interval;
241                 }
242             }
243         }
244 
245         return null;
246     }
247     
248     /**
249      * Get an chronologically ordered list of intervals during the day. 
250      * These will consist of user defined intervals, packed with half 
251      * hour intervals to ensure contiguous intervals between the start 
252      * and end hour.
253      *  
254      * @param startHour The first hour
255      * @param endHour The last hour
256      * @return A List<Interval> of intervals covering the day
257      */
258     public List getIntervals(int startHour, int endHour)
259     {
260         Date startTime = initDate(getDate(), startHour);
261         Date endTime = initDate(getDate(), endHour);
262         ArrayList intervals = new ArrayList();
263         Interval last = null;
264         
265         // Iterate over the custom intervals, adding half hour intervals in any gaps
266         if (getIntervals() != null)
267         {
268             for (Iterator intervalIt = getIntervals().iterator(); intervalIt.hasNext(); )
269             {
270                 Interval interval = (Interval) intervalIt.next();
271             
272                 if (last != null)
273                 {
274                     if (!interval.getEndTime().after(last.getEndTime()))
275                     {
276                         // Skip if the interval if entirely overlapped by the previous interval
277                         continue;
278                     }
279                     else if (interval.getStartTime().before(last.getEndTime()))
280                     {
281                         // Truncate the beginning of the interval, to remove overlap
282                         interval.setStartTime(last.getEndTime());
283                     }
284                 }
285                 
286                 // Don't add any intervals before the start time
287                 if (interval.getEndTime().before(startTime))
288                 {
289                     continue;
290                 }
291                 // Don't add any intervals beyond the end time
292                 if (interval.getStartTime().after(endTime)) 
293                 {
294                     break;
295                 }
296             
297                 if (last == null) 
298                 {
299                     // Calculate the first interval of the day
300                     last = new HalfHourInterval(initDate(getDate(), startHour), interval.getStartTime());
301                 } 
302                 else 
303                 {
304                     // Calculate a half hour interval following the last user defined interval
305                     last = HalfHourInterval.next(last, interval.getStartTime());                
306                 }
307                 // Add half hours up to the current interval
308                 while (last != null && interval.after(last))
309                 {
310                     intervals.add(last);
311                     last = HalfHourInterval.next(last, interval.getStartTime());
312                 }
313                 
314                 // Truncate the interval to fit within start and end times
315                 if (interval.getStartTime().before(startTime))
316                 {
317                     interval.setStartTime(startTime);
318                 }
319                 if (interval.getEndTime().after(endTime))
320                 {
321                     interval.setEndTime(endTime);
322                 }
323                 
324                 intervals.add(interval);
325                 last = interval;
326             }
327         }
328 
329         if (last == null)
330         {
331             // There are no user defined intervals, so start at the beginning of the day
332             last = new HalfHourInterval(initDate(getDate(), startHour), endTime);            
333         }
334         else 
335         {
336             // Move on to the next interval after the last user defined one
337             last = HalfHourInterval.next(last, endTime);                
338         }
339         
340         // Add half hour intervals up to the end time
341         while(last != null)
342         {
343             intervals.add(last);
344             last = HalfHourInterval.next(last, endTime);
345         }
346         
347         return intervals;
348     }
349 
350     private Date initDate(Date date, int hour) {
351         Calendar calendar = getCalendarInstance(date);
352         calendar.set(Calendar.HOUR_OF_DAY, hour);
353         calendar.set(Calendar.MINUTE, 0);
354         calendar.set(Calendar.SECOND, 0);
355         calendar.set(Calendar.MILLISECOND, 0);
356 
357         return calendar.getTime();
358     }
359 }
360 //The End