001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright © 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.pm.calendar;
051:
052: import java.io.IOException;
053: import java.io.ObjectInputStream;
054: import java.io.ObjectOutputStream;
055: import java.io.Serializable;
056: import java.util.ArrayList;
057: import java.util.Calendar;
058: import java.util.Collection;
059: import java.util.Collections;
060: import java.util.Date;
061: import java.util.HashSet;
062: import java.util.Iterator;
063:
064: import org.apache.commons.collections.Closure;
065:
066: import com.projity.configuration.CircularDependencyException;
067: import com.projity.grouping.core.Node;
068: import com.projity.grouping.core.hierarchy.NodeHierarchy;
069: import com.projity.options.CalendarOption;
070: import com.projity.pm.key.HasCommonKeyImpl;
071: import com.projity.strings.Messages;
072: import com.projity.util.DateTime;
073:
074: /**
075: * Calendar functions
076: */
077: public class WorkingCalendar implements WorkCalendar, Serializable,
078: Comparable {
079: static final long serialVersionUID = 27738049223431L;
080: private int fixedId = 0;
081: public static final WorkingCalendar INVALID_INTERSECTION_CALENDAR = new WorkingCalendar();
082:
083: // the objects that use this calendar
084: private transient HashSet objectsUsing = null;
085:
086: public final HashSet getObjectsUsing() {
087: if (objectsUsing == null)
088: objectsUsing = new HashSet();
089: return objectsUsing;
090: }
091:
092: public void addObjectUsing(HasCalendar cal) {
093: getObjectsUsing().add(cal);
094: }
095:
096: public void removeObjectUsing(HasCalendar cal) {
097: getObjectsUsing().remove(cal);
098: }
099:
100: private transient HasCommonKeyImpl hasKey = new HasCommonKeyImpl(
101: true, this ); //true if calendars aren't internal
102:
103: private WorkingCalendar() { // for static
104: super ();
105: }
106:
107: public boolean equals(Object arg0) {
108: return (this == arg0);
109: }
110:
111: public static WorkingCalendar getInstance() {
112: return new WorkingCalendar();
113: }
114:
115: public static WorkingCalendar getInstanceBasedOn(WorkCalendar base) {
116: WorkingCalendar cal = getInstance();
117: try {
118: cal.setBaseCalendar(base);
119: } catch (CircularDependencyException e) {
120: // TODO Auto-generated catch block
121: e.printStackTrace();
122: }
123: return cal;
124: }
125:
126: public static WorkingCalendar getStandardBasedInstance() {
127: WorkingCalendar cal = getInstance();
128: try {
129: cal.setBaseCalendar(WorkingCalendar.getStandardInstance());
130: } catch (CircularDependencyException e) {
131: // TODO Auto-generated catch block
132: e.printStackTrace();
133: }
134: return cal; //TODO should share this instance
135: }
136:
137: public Object clone() throws CloneNotSupportedException {
138: WorkingCalendar cal = (WorkingCalendar) super .clone();
139: // cal.hasKey = new HasCommonKeyImpl(this);
140: cal.setName(getName());
141: return cal;
142: }
143:
144: public WorkingCalendar makeScratchCopy() {
145: WorkingCalendar newOne = null;
146: try {
147: newOne = new WorkingCalendar();
148: newOne.baseCalendar = baseCalendar;
149: newOne.setName(getName());
150: newOne.differences = (CalendarDefinition) differences
151: .clone();
152: } catch (CloneNotSupportedException e) {
153: // TODO Auto-generated catch block
154: e.printStackTrace();
155: }
156: return newOne;
157: }
158:
159: public long getId() {
160: return hasKey.getId();
161: }
162:
163: public void setId(long id) {
164: hasKey.setId(id);
165: }
166:
167: public long getUniqueId() {
168: return hasKey.getUniqueId();
169: }
170:
171: public void setUniqueId(long id) {
172: hasKey.setUniqueId(id);
173: }
174:
175: // public boolean isNew() {
176: // return hasKey.isNew();
177: // }
178: // public void setNew(boolean isNew) {
179: // hasKey.setNew(isNew);
180: // }
181: public void assignFrom(WorkingCalendar source) {
182: baseCalendar = source.baseCalendar;
183: if (!source.getName().equals(getName())) {
184: setName(source.getName());
185: // CalendarService.getInstance().add(this);
186: }
187: differences = source.differences;
188: concrete = null;
189: }
190:
191: private WorkCalendar baseCalendar = null;
192: private CalendarDefinition differences = new CalendarDefinition();
193:
194: public WorkDay[] getExceptionDays() { // get day exceptions in derived cal
195: return differences.getExceptions();
196: }
197:
198: /**
199: * @return Returns the name.
200: */
201: public String getName() {
202: return hasKey.getName();
203: }
204:
205: /**
206: * @param name The name to set.
207: */
208: public void setName(String name) {
209: hasKey.setName(name);
210: }
211:
212: public void addOrReplaceException(WorkDay exceptionDay) {
213: exceptionDay.initialize(); // make sure cached duration is set
214: differences.addOrReplaceException(exceptionDay);
215: }
216:
217: public void removeException(WorkDay exceptionDay) {
218: differences.dayExceptions.remove(exceptionDay); // remove any existing
219: }
220:
221: /**
222: * This function will return a concrete calendar instance. That is, one for which the days are already merged
223: * @return concrete instance
224: */
225: private transient CalendarDefinition concrete = null;
226:
227: public CalendarDefinition getConcreteInstance() {
228: if (concrete == null) {
229: WorkCalendar base = baseCalendar;
230: concrete = new CalendarDefinition(base == null ? null
231: : base.getConcreteInstance(), differences);
232: }
233: return concrete;
234: }
235:
236: public void invalidate() {
237: concrete = null;
238: CalendarService.getInstance().invalidate(this );
239: }
240:
241: /**
242: * @return Returns the baseCalendar.
243: */
244: public WorkCalendar getBaseCalendar() {
245: return baseCalendar;
246: }
247:
248: /**
249: * Test for ciruclar dependency
250: */
251: public boolean dependsOn(WorkCalendar cal) {
252: if (this == cal)
253: return true;
254: WorkCalendar base = getBaseCalendar();
255: if (base == null)
256: return false;
257: return base.dependsOn(cal);
258: }
259:
260: /**
261: * @param baseCalendar The baseCalendar to set.
262: */
263: public void setBaseCalendar(WorkCalendar baseCalendar)
264: throws CircularDependencyException {
265: if (baseCalendar != null && baseCalendar.dependsOn(this )) // avoid circular
266: throw new CircularDependencyException(Messages
267: .getString("Calendar.ExceptionCircular"));
268: this .baseCalendar = baseCalendar;
269: }
270:
271: public void changeBaseCalendar(WorkCalendar baseCalendar)
272: throws CircularDependencyException {
273: setBaseCalendar(baseCalendar);
274: }
275:
276: /**
277: * @param dayNum
278: * @return
279: */
280: public WorkDay getWeekDay(int dayNum) {
281: return differences.week.getWeekDay(dayNum);
282: }
283:
284: public WorkDay getDerivedWeekDay(int dayNum) {
285: WorkDay day = differences.week.getWeekDay(dayNum);
286: if (day == null && baseCalendar != null)
287: day = ((WorkingCalendar) baseCalendar)
288: .getDerivedWeekDay(dayNum);
289: return day;
290: }
291:
292: /**
293: * @param dayNum
294: * @param day
295: */
296: public void setWeekDay(int dayNum, WorkDay day) {
297: differences.week.setWeekDay(dayNum, day);
298: }
299:
300: /**
301: * @param day
302: */
303: public void setWeekDays(WorkDay day) {
304: differences.week.setWeekDays(day);
305: }
306:
307: /**
308: * @param day
309: */
310: public void setWeekends(WorkDay day) {
311: differences.week.setWeekends(day);
312: }
313:
314: /* (non-Javadoc)
315: * @see com.projity.pm.time.WorkCalendar#add(long, long, boolean)
316: */
317: public long add(long date, long duration, boolean useSooner) {
318: // if (date == 0)
319: // DebugUtils.dumpStack("0 date");
320: return getConcreteInstance().add(date, duration, useSooner);
321: }
322:
323: /* (non-Javadoc)
324: * @see com.projity.pm.time.WorkCalendar#compare(long, long, boolean)
325: */
326: public long compare(long laterDate, long earlierDate,
327: boolean elapsed) {
328: return getConcreteInstance().compare(laterDate, earlierDate,
329: elapsed);
330: }
331:
332: public long adjustInsideCalendar(long date, boolean useSooner) {
333: return getConcreteInstance().adjustInsideCalendar(date,
334: useSooner);
335: }
336:
337: public String getCategory() {
338: return CALENDAR_CATEGORY;
339: }
340:
341: /* (non-Javadoc)
342: * @see java.lang.Object#toString()
343: */
344: public String toString() {
345: return getName();
346: }
347:
348: private static WorkingCalendar standardInstance = null;
349: private static WorkingCalendar defaultInstance = null;
350:
351: static WorkingCalendar getStandardInstance() {
352: if (standardInstance != null)
353: return standardInstance;
354:
355: standardInstance = WorkingCalendar.getInstance();
356: WorkDay nonWorking = null;
357: WorkDay working = null;
358: nonWorking = new WorkDay();
359: working = new WorkDay();
360: nonWorking.getWorkingHours().setNonWorking();
361:
362: try {
363: working.getWorkingHours().setInterval(0, hourTime(8),
364: hourTime(12));
365: working.getWorkingHours().setInterval(1, hourTime(13),
366: hourTime(17));
367: } catch (WorkRangeException e) {
368: e.printStackTrace();
369: }
370:
371: standardInstance.setWeekends(nonWorking);
372: standardInstance.setWeekDays(working); // 8 hours
373:
374: standardInstance.setName("default base");
375: return standardInstance;
376:
377: }
378:
379: static WorkingCalendar getDefaultInstance() {
380: if (defaultInstance != null)
381: return defaultInstance;
382:
383: defaultInstance = getStandardBasedInstance();
384: defaultInstance
385: .setName(Messages.getString("Calendar.Standard"));
386: defaultInstance.setFixedId(1);
387: CalendarService.getInstance().add(defaultInstance);
388:
389: get24HoursInstance();
390: getNightShiftInstance();
391:
392: return defaultInstance;
393: }
394:
395: private static WorkingCalendar _24HoursInstance = null;
396:
397: static WorkingCalendar get24HoursInstance() {
398: if (_24HoursInstance != null)
399: return _24HoursInstance;
400: _24HoursInstance = getStandardBasedInstance();
401: WorkDay working = null;
402: working = new WorkDay();
403: try {
404: working.getWorkingHours().setInterval(0, hourTime(0),
405: hourTime(0));
406: } catch (WorkRangeException e) {
407: e.printStackTrace();
408: }
409:
410: _24HoursInstance.setWeekends(working);
411: _24HoursInstance.setWeekDays(working);
412:
413: _24HoursInstance
414: .setName(Messages.getString("Calendar.24Hours"));
415: _24HoursInstance.setFixedId(2);
416: CalendarService.getInstance().add(_24HoursInstance); // put standard calendar in list
417: return _24HoursInstance;
418: }
419:
420: private static WorkingCalendar nightShiftInstance = null;
421:
422: static WorkingCalendar getNightShiftInstance() {
423: if (nightShiftInstance != null)
424: return nightShiftInstance;
425: nightShiftInstance = WorkingCalendar.getStandardBasedInstance();
426: WorkDay nonWorking = null;
427: WorkDay working = null;
428: nonWorking = new WorkDay();
429: working = new WorkDay();
430: nonWorking.getWorkingHours().setNonWorking();
431:
432: nightShiftInstance.setWeekDay(Calendar.SUNDAY - 1, null); // will revert to overall default for sunday which is not working
433:
434: WorkDay monday = new WorkDay();
435: try {
436: monday.getWorkingHours().setInterval(0, hourTime(23),
437: hourTime(0));
438: } catch (WorkRangeException e) {
439: e.printStackTrace();
440: }
441: nightShiftInstance.setWeekDay(Calendar.MONDAY - 1, monday);
442:
443: try {
444: working.getWorkingHours().setInterval(0, hourTime(0),
445: hourTime(3));
446: working.getWorkingHours().setInterval(1, hourTime(4),
447: hourTime(8));
448: working.getWorkingHours().setInterval(2, hourTime(23),
449: hourTime(0));
450: } catch (WorkRangeException e) {
451: e.printStackTrace();
452: }
453: nightShiftInstance.setWeekDay(Calendar.TUESDAY - 1, working);
454: nightShiftInstance.setWeekDay(Calendar.WEDNESDAY - 1, working);
455: nightShiftInstance.setWeekDay(Calendar.THURSDAY - 1, working);
456: nightShiftInstance.setWeekDay(Calendar.FRIDAY - 1, working);
457:
458: WorkDay saturday = new WorkDay();
459: try {
460: saturday.getWorkingHours().setInterval(0, hourTime(0),
461: hourTime(3));
462: saturday.getWorkingHours().setInterval(1, hourTime(4),
463: hourTime(8));
464: } catch (WorkRangeException e) {
465: e.printStackTrace();
466: }
467: nightShiftInstance.setWeekDay(Calendar.SATURDAY - 1, saturday);
468:
469: nightShiftInstance.setName(Messages
470: .getString("Calendar.NightShift"));
471: nightShiftInstance.setFixedId(3);
472:
473: CalendarService.getInstance().add(nightShiftInstance); // put night shift calendar in list
474: return nightShiftInstance;
475: }
476:
477: private static long hourTime(int hour) {
478: return WorkingHours.hourTime(hour);
479: }
480:
481: public String dump() {
482: String result = "Calendar " + getName() + "\n";
483: result += "weekdays\n";
484: for (int i = 0; i < 7; i++) {
485: result += "day[" + i + "]" + getWeekDay(i) + "\n";
486: }
487: result += "There are " + differences.dayExceptions
488: + " exceptions\n";
489: Iterator i = differences.dayExceptions.iterator();
490: while (i.hasNext()) {
491: result += "exception" + i.next().toString();
492: }
493: return result;
494:
495: }
496:
497: private static WorkDay getDay(Collection collection, long day) {
498: Iterator i = collection.iterator();
499: Date date = new Date(day);
500: WorkDay current = null;
501: while (i.hasNext()) {
502: current = (WorkDay) i.next();
503: if (current.compareTo(date) == 0) {
504: return current;
505: }
506: }
507: return null;
508: }
509:
510: DayDescriptor getMonthDayDescriptor(long date) {
511: DayDescriptor descriptor = new DayDescriptor();
512: int dayNum = CalendarDefinition.getDayOfWeek(date);
513: descriptor.workDay = getDay(differences.dayExceptions, date); // is this day modified in derived calendar?
514: descriptor.modified = descriptor.workDay != null;
515:
516: if (descriptor.workDay == null)
517: descriptor.workDay = differences.week.getWeekDay(dayNum); // try difference week day
518:
519: if (descriptor.workDay == null) // if not overrideen in derived calendar, see if base calendar has a special day
520: descriptor.workDay = getConcreteInstance().getWorkDay(date);
521:
522: if (descriptor.workDay == null) // return week day
523: descriptor.workDay = getConcreteInstance().week
524: .getWeekDay(CalendarDefinition.getDayOfWeek(date));
525: return descriptor;
526: }
527:
528: DayDescriptor getWeekDayDescriptor(int dayNum) {
529: dayNum -= 1; // SUNDAY is 1, so need to subtract 1
530: DayDescriptor descriptor = new DayDescriptor();
531: descriptor.workDay = differences.week.getWeekDay(dayNum);
532:
533: descriptor.modified = descriptor.workDay != null;
534: descriptor.workDay = getConcreteInstance().week
535: .getWeekDay(dayNum);
536: // if (isBaseCalendar()) {
537: // // for base calendars, the notion of modified is based on the default work week
538: // WorkDay baseDay = WorkingCalendar.getDefaultInstance(null).getWeekDay(dayNum);
539: // descriptor.modified = !(baseDay.hasSameWorkHours(descriptor.workDay));
540: // } else {
541: // if (descriptor.workDay == null)
542: // descriptor.workDay = getConcreteInstance().week.getWeekDay(dayNum);
543: // }
544: return descriptor;
545: }
546:
547: void makeDefaultDay(long date) {
548: WorkDay day = getDay(differences.dayExceptions, date);
549: if (day != null)
550: differences.dayExceptions.remove(day);
551: concrete = null;
552: }
553:
554: void makeDefaultWeekDay(int dayNum) {
555: dayNum -= 1; // SUNDAY is 1, so need to subtract 1
556: differences.week.setWeekDay(dayNum, null);
557: concrete = null;
558: }
559:
560: void setDayNonWorking(long date) {
561: WorkDay day = new WorkDay(date, date);
562: addOrReplaceException(day);
563: concrete = null;
564: }
565:
566: void setWeekDayNonWorking(int dayNum) {
567: dayNum -= 1; // SUNDAY is 1, so need to subtract 1
568: WorkDay day = new WorkDay();
569: differences.week.setWeekDay(dayNum, day);
570: concrete = null;
571: }
572:
573: void setDayWorkingHours(long date, WorkingHours workingHours)
574: throws WorkRangeException {
575: workingHours.validate();
576: WorkDay day = new WorkDay(date, date);
577: day.setWorkingHours(workingHours);
578: addOrReplaceException(day);
579: concrete = null;
580: }
581:
582: void setWeekDayWorkingHours(int dayNum, WorkingHours workingHours)
583: throws WorkRangeException {
584: dayNum -= 1; // SUNDAY is 1, so need to subtract 1
585: workingHours.validate();
586: WorkDay day = new WorkDay();
587: day.setWorkingHours(workingHours);
588: differences.week.setWeekDay(dayNum, day);
589: concrete = null;
590: }
591:
592: String serializedName = ""; // non transient version of name for serialization
593:
594: private void writeObject(ObjectOutputStream s) throws IOException {
595: serializedName = getName();
596: if (baseCalendar == CalendarService.getInstance()
597: .getStandardInstance()) // don't serialize default base. treat it as null
598: baseCalendar = null;
599: s.defaultWriteObject();
600: hasKey.serialize(s);
601: if (baseCalendar == null)
602: baseCalendar = CalendarService.getInstance()
603: .getStandardInstance(); // put it back so program will work
604: }
605:
606: private void readObject(ObjectInputStream s) throws IOException,
607: ClassNotFoundException {
608: s.defaultReadObject();
609: hasKey = HasCommonKeyImpl.deserialize(s, this );
610: if (serializedName == null)
611: serializedName = "";
612: setName(serializedName);
613: if (baseCalendar == null)
614: baseCalendar = CalendarService.getInstance()
615: .getStandardInstance();
616: CalendarService.getInstance().add(this );
617: }
618:
619: public boolean isBaseCalendar() {
620: return baseCalendar == getStandardInstance();
621: }
622:
623: public final int getFixedId() {
624: return fixedId;
625: }
626:
627: public final void setFixedId(int fixedId) {
628: this .fixedId = fixedId;
629: }
630:
631: public static ArrayList extractCalendars(Collection collection) {
632: ArrayList list = new ArrayList();
633: Iterator i = collection.iterator();
634: WorkingCalendar cal;
635: while (i.hasNext()) {
636: cal = (WorkingCalendar) ((HasCalendar) i.next())
637: .getWorkCalendar();
638: if (cal != null)
639: list.add(cal);
640: }
641: Collections.sort(list);
642: return list;
643: }
644:
645: public static ArrayList extractCalendars(NodeHierarchy hierarchy) {
646: final ArrayList list = new ArrayList();
647: hierarchy.visitAll(new Closure() {
648:
649: public void execute(Object arg0) {
650: if (arg0 != null) {
651: Object impl = ((Node) arg0).getImpl();
652: if (impl instanceof HasCalendar)
653: list.add(impl);
654: }
655: }
656: });
657: return WorkingCalendar.extractCalendars(list);
658: }
659:
660: /* (non-Javadoc)
661: * @see java.lang.Comparable#compareTo(java.lang.Object)
662: */
663: public int compareTo(Object arg0) {
664: if (arg0 == null)
665: return 1;
666: if (!(arg0 instanceof WorkingCalendar))
667: return -1;
668: return getName().compareTo(((WorkingCalendar) arg0).getName());
669: }
670:
671: public void notifyChanged() {
672: concrete = null;
673: }
674:
675: /* (non-Javadoc)
676: * @see com.projity.pm.calendar.WorkCalendar#isInvalid()
677: */
678: public boolean isInvalid() {
679: return concrete == null;
680: }
681:
682: public WorkingCalendar intersectWith(WorkingCalendar other)
683: throws InvalidCalendarIntersectionException {
684: CalendarDefinition newDef = new CalendarDefinition();
685:
686: // do week
687: WorkWeek weekResult = new WorkWeek();
688: for (int i = 0; i < WorkWeek.DAYS_IN_WEEK; i++)
689: weekResult.workDay[i] = getDerivedWeekDay(i).intersectWith(
690: other.getDerivedWeekDay(i));
691: weekResult.updateWorkingDuration();
692:
693: if (weekResult.getDuration() == 0) // a calendar cannot have no working time for its work week
694: throw new InvalidCalendarIntersectionException();
695:
696: // do exceptions
697: CalendarDefinition this Def = getConcreteInstance();
698: CalendarDefinition otherDef = other.getConcreteInstance();
699: WorkDay exceptionDay;
700: // merge exceptions
701: for (int i = 0; i < this Def.exceptions.length; i++) {
702: exceptionDay = this Def.exceptions[i];
703: newDef.dayExceptions.add(exceptionDay
704: .intersectWith(otherDef.getWorkDay(exceptionDay
705: .getStart())));
706: }
707: for (int i = 0; i < otherDef.exceptions.length; i++) {
708: exceptionDay = otherDef.exceptions[i];
709: newDef.dayExceptions.add(exceptionDay.intersectWith(this Def
710: .getWorkDay(exceptionDay.getStart())));
711: }
712: newDef.addSentinelsAndMakeArray();
713: newDef.week = weekResult;
714:
715: WorkingCalendar intersection = new WorkingCalendar();
716: intersection.concrete = newDef;
717: intersection.setName("AssignCal: " + getName() + "/"
718: + other.getName());
719: return intersection;
720:
721: }
722:
723: public void addCalendarTime(long start, long end) {
724: start = DateTime.dayFloor(start);
725: end = DateTime.dayFloor(end);
726:
727: for (long day = start; day < end; day = DateTime.nextDay(day)) {
728: WorkDay workDay = new WorkDay(day, day);
729: WorkingHours hours = (WorkingHours) (CalendarOption
730: .getInstance().isAddedCalendarTimeIsNonStop() ? WorkingHours
731: .getNonStop().clone()
732: : WorkingHours.getDefault().clone());
733:
734: workDay.setWorkingHours(hours);
735: addOrReplaceException(workDay);
736: }
737: invalidate(); // the calendar needs to be reevaluated
738: }
739:
740: private transient boolean dirty;
741:
742: public boolean isDirty() {
743: return dirty;
744: }
745:
746: public void setDirty(boolean dirty) {
747: this .dirty = dirty;
748: }
749:
750: public void removeEmptyDays() {
751: int nullCount = 0;
752: for (int i = 0; i < 7; i++) {
753: WorkDay w = getWeekDay(i);
754: if (w == null)
755: continue;
756: if (w.getWorkingHours() == null
757: || !w.getWorkingHours().hasHours())
758: setWeekDay(i, null);
759: if (getWeekDay(i) == null)
760: nullCount++;
761: }
762: // if ( nullCount == 7) { // if all nulls, copy default cal
763: // for (int i = 0; i < 7; i++) {
764: // setWeekDay(i,(WorkDay) getDefaultInstance().getWeekDay(i).clone());
765: // }
766: // }
767:
768: }
769:
770: }
|