001: /*
002: * $Id: RecurrenceInfo.java,v 1.3 2003/12/15 09:13:12 jonesde Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.service.calendar;
026:
027: import java.util.ArrayList;
028: import java.util.Collection;
029: import java.util.Collections;
030: import java.util.Date;
031: import java.util.Iterator;
032: import java.util.List;
033:
034: import org.ofbiz.base.util.Debug;
035: import org.ofbiz.base.util.StringUtil;
036: import org.ofbiz.base.util.UtilMisc;
037: import org.ofbiz.entity.GenericDelegator;
038: import org.ofbiz.entity.GenericEntityException;
039: import org.ofbiz.entity.GenericValue;
040:
041: /**
042: * Recurrence Info Object
043: *
044: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
045: * @version $Revision: 1.3 $
046: * @since 2.0
047: */
048: public class RecurrenceInfo {
049:
050: public static final String module = RecurrenceInfo.class.getName();
051:
052: protected GenericValue info;
053: protected Date startDate;
054: protected List rRulesList;
055: protected List eRulesList;
056: protected List rDateList;
057: protected List eDateList;;
058:
059: /** Creates new RecurrenceInfo */
060: public RecurrenceInfo(GenericValue info)
061: throws RecurrenceInfoException {
062: this .info = info;
063: if (!info.getEntityName().equals("RecurrenceInfo"))
064: throw new RecurrenceInfoException(
065: "Invalid RecurrenceInfo Value object.");
066: init();
067: }
068:
069: /** Initializes the rules for this RecurrenceInfo object. */
070: public void init() throws RecurrenceInfoException {
071:
072: if (info.get("startDateTime") == null)
073: throw new RecurrenceInfoException(
074: "Recurrence startDateTime cannot be null.");
075:
076: // Get start date
077: long startTime = info.getTimestamp("startDateTime").getTime();
078:
079: if (startTime > 0) {
080: int nanos = info.getTimestamp("startDateTime").getNanos();
081:
082: startTime += (nanos / 1000000);
083: } else {
084: throw new RecurrenceInfoException(
085: "Recurrence startDateTime must have a value.");
086: }
087: startDate = new Date(startTime);
088:
089: // Get the recurrence rules objects
090: try {
091: Collection c = info.getRelated("RecurrenceRule");
092: Iterator i = c.iterator();
093:
094: rRulesList = new ArrayList();
095: while (i.hasNext()) {
096: rRulesList.add(new RecurrenceRule((GenericValue) i
097: .next()));
098: }
099: } catch (GenericEntityException gee) {
100: rRulesList = null;
101: } catch (RecurrenceRuleException rre) {
102: throw new RecurrenceInfoException("Illegal rule format.",
103: rre);
104: }
105:
106: // Get the exception rules objects
107: try {
108: Collection c = info.getRelated("ExceptionRecurrenceRule");
109: Iterator i = c.iterator();
110:
111: eRulesList = new ArrayList();
112: while (i.hasNext()) {
113: eRulesList.add(new RecurrenceRule((GenericValue) i
114: .next()));
115: }
116: } catch (GenericEntityException gee) {
117: eRulesList = null;
118: } catch (RecurrenceRuleException rre) {
119: throw new RecurrenceInfoException("Illegal rule format",
120: rre);
121: }
122:
123: // Get the recurrence date list
124: rDateList = RecurrenceUtil.parseDateList(StringUtil.split(info
125: .getString("recurrenceDateTimes"), ","));
126: // Get the exception date list
127: eDateList = RecurrenceUtil.parseDateList(StringUtil.split(info
128: .getString("exceptionDateTimes"), ","));
129:
130: // Sort the lists.
131: Collections.sort(rDateList);
132: Collections.sort(eDateList);
133: }
134:
135: /** Returns the primary key for this value object */
136: public String getID() {
137: return info.getString("recurrenceInfoId");
138: }
139:
140: /** Returns the startDate Date object. */
141: public Date getStartDate() {
142: return this .startDate;
143: }
144:
145: /** Returns the long value of the startDate. */
146: public long getStartTime() {
147: return this .startDate.getTime();
148: }
149:
150: /** Returns a recurrence rule iterator */
151: public Iterator getRecurrenceRuleIterator() {
152: return rRulesList.iterator();
153: }
154:
155: /** Returns a sorted recurrence date iterator */
156: public Iterator getRecurrenceDateIterator() {
157: return rDateList.iterator();
158: }
159:
160: /** Returns a exception recurrence iterator */
161: public Iterator getExceptionRuleIterator() {
162: return eRulesList.iterator();
163: }
164:
165: /** Returns a sorted exception date iterator */
166: public Iterator getExceptionDateIterator() {
167: return eDateList.iterator();
168: }
169:
170: /** Returns the current count of this recurrence. */
171: public long getCurrentCount() {
172: if (info.get("recurrenceCount") != null)
173: return info.getLong("recurrenceCount").longValue();
174: return 0;
175: }
176:
177: /** Increments the current count of this recurrence and updates the record. */
178: public void incrementCurrentCount() throws GenericEntityException {
179: incrementCurrentCount(true);
180: }
181:
182: /** Increments the current count of this recurrence. */
183: public void incrementCurrentCount(boolean store)
184: throws GenericEntityException {
185: Long count = new Long(getCurrentCount() + 1);
186:
187: if (store) {
188: info.set("recurrenceCount", count);
189: info.store();
190: }
191: }
192:
193: /** Removes the recurrence from persistant store. */
194: public void remove() throws RecurrenceInfoException {
195: List rulesList = new ArrayList();
196:
197: rulesList.addAll(rRulesList);
198: rulesList.addAll(eRulesList);
199: Iterator i = rulesList.iterator();
200:
201: try {
202: while (i.hasNext())
203: ((RecurrenceRule) i.next()).remove();
204: info.remove();
205: } catch (RecurrenceRuleException rre) {
206: throw new RecurrenceInfoException(rre.getMessage(), rre);
207: } catch (GenericEntityException gee) {
208: throw new RecurrenceInfoException(gee.getMessage(), gee);
209: }
210: }
211:
212: /** Returns the first recurrence. */
213: public long first() {
214: return startDate.getTime();
215: // First recurrence is always the start time
216: }
217:
218: /** Returns the estimated last recurrence. */
219: public long last() {
220: // TODO: find the last recurrence.
221: return 0;
222: }
223:
224: /** Returns the next recurrence from now. */
225: public long next() {
226: return next(RecurrenceUtil.now());
227: }
228:
229: /** Returns the next recurrence from the specified time. */
230: public long next(long fromTime) {
231: // Check for the first recurrence (StartTime is always the first recurrence)
232: if (getCurrentCount() == 0 || fromTime == 0
233: || fromTime == startDate.getTime()) {
234: return first();
235: }
236:
237: if (Debug.verboseOn()) {
238: Debug.logVerbose("Date List Size: "
239: + (rDateList == null ? 0 : rDateList.size()),
240: module);
241: Debug.logVerbose("Rule List Size: "
242: + (rRulesList == null ? 0 : rRulesList.size()),
243: module);
244: }
245:
246: // Check the rules and date list
247: if (rDateList == null && rRulesList == null) {
248: return 0;
249: }
250:
251: long nextRuleTime = fromTime;
252: boolean hasNext = true;
253:
254: // Get the next recurrence from the rule(s).
255: Iterator rulesIterator = getRecurrenceRuleIterator();
256: while (rulesIterator.hasNext()) {
257: RecurrenceRule rule = (RecurrenceRule) rulesIterator.next();
258: while (hasNext) {
259: // Gets the next recurrence time from the rule.
260: nextRuleTime = getNextTime(rule, nextRuleTime);
261: // Tests the next recurrence against the rules.
262: if (nextRuleTime == 0 || isValid(nextRuleTime)) {
263: hasNext = false;
264: }
265: }
266: }
267: return nextRuleTime;
268: }
269:
270: private long getNextTime(RecurrenceRule rule, long fromTime) {
271: long nextTime = rule.next(getStartTime(), fromTime,
272: getCurrentCount());
273: if (Debug.verboseOn())
274: Debug.logVerbose(
275: "Next Time Before Date Check: " + nextTime, module);
276: return checkDateList(rDateList, nextTime, fromTime);
277: }
278:
279: private long checkDateList(List dateList, long time, long fromTime) {
280: long nextTime = time;
281:
282: if (dateList != null && dateList.size() > 0) {
283: Iterator dateIterator = dateList.iterator();
284:
285: while (dateIterator.hasNext()) {
286: Date this Date = (Date) dateIterator.next();
287:
288: if (nextTime > 0 && this Date.getTime() < nextTime
289: && this Date.getTime() > fromTime)
290: nextTime = this Date.getTime();
291: else if (nextTime == 0 && this Date.getTime() > fromTime)
292: nextTime = this Date.getTime();
293: }
294: }
295: return nextTime;
296: }
297:
298: private boolean isValid(long time) {
299: Iterator exceptRulesIterator = getExceptionRuleIterator();
300:
301: while (exceptRulesIterator.hasNext()) {
302: RecurrenceRule except = (RecurrenceRule) exceptRulesIterator
303: .next();
304:
305: if (except.isValid(getStartTime(), time)
306: || eDateList.contains(new Date(time)))
307: return false;
308: }
309: return true;
310: }
311:
312: public String primaryKey() {
313: return info.getString("recurrenceInfoId");
314: }
315:
316: public static RecurrenceInfo makeInfo(GenericDelegator delegator,
317: long startTime, int frequency, int interval, int count)
318: throws RecurrenceInfoException {
319: return makeInfo(delegator, startTime, frequency, interval,
320: count, 0);
321: }
322:
323: public static RecurrenceInfo makeInfo(GenericDelegator delegator,
324: long startTime, int frequency, int interval, long endTime)
325: throws RecurrenceInfoException {
326: return makeInfo(delegator, startTime, frequency, interval, -1,
327: endTime);
328: }
329:
330: public static RecurrenceInfo makeInfo(GenericDelegator delegator,
331: long startTime, int frequency, int interval, int count,
332: long endTime) throws RecurrenceInfoException {
333: try {
334: RecurrenceRule r = RecurrenceRule.makeRule(delegator,
335: frequency, interval, count, endTime);
336: String ruleId = r.primaryKey();
337: String infoId = delegator.getNextSeqId("RecurrenceInfo")
338: .toString();
339: GenericValue value = delegator.makeValue("RecurrenceInfo",
340: UtilMisc.toMap("recurrenceInfoId", infoId));
341:
342: value.set("recurrenceRuleId", ruleId);
343: value.set("startDateTime",
344: new java.sql.Timestamp(startTime));
345: delegator.create(value);
346: RecurrenceInfo newInfo = new RecurrenceInfo(value);
347:
348: return newInfo;
349: } catch (RecurrenceRuleException re) {
350: throw new RecurrenceInfoException(re.getMessage(), re);
351: } catch (GenericEntityException ee) {
352: throw new RecurrenceInfoException(ee.getMessage(), ee);
353: } catch (RecurrenceInfoException rie) {
354: throw rie;
355: }
356: }
357: }
|