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