Author: adrianc
Date: Tue Sep 16 19:39:19 2008
New Revision: 696134
URL: http://svn.apache.org/viewvc?rev=696134&view=rev
Log:
Safety/sanity checks for the temporal expression Java code.
Yes, there is millisecond arithmetic in this code. No, I haven't changed my
view on it - millisecond arithmetic is still Evil. In this case I'm just using
it to get a java.util.Calendar instance in the neighborhood of where I need it.
Modified:
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java
Modified:
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java?rev=696134&r1=696133&r2=696134&view=diff
==============================================================================
---
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java
(original)
+++
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java
Tue Sep 16 19:39:19 2008
@@ -96,6 +96,10 @@
return set;
}
+ protected boolean containsExpression(TemporalExpression expression) {
+ return false;
+ }
+
protected Calendar setStartOfDay(Calendar cal) {
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
Modified:
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java?rev=696134&r1=696133&r2=696134&view=diff
==============================================================================
---
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java
(original)
+++
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java
Tue Sep 16 19:39:19 2008
@@ -56,6 +56,9 @@
throw new IllegalArgumentException("expressionSet argument
cannot be null");
}
this.expressionSet = expressionSet;
+ if (containsExpression(this)) {
+ throw new IllegalArgumentException("recursive expression");
+ }
if (this.expressionSet.size() > 0) {
TemporalExpression that = this.expressionSet.iterator().next();
if (this.compareTo(that) > 0) {
@@ -126,6 +129,15 @@
}
return finalSet;
}
+
+ protected boolean containsExpression(TemporalExpression expression) {
+ for (TemporalExpression setItem : this.expressionSet) {
+ if (setItem.containsExpression(expression)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/** This class represents a mathematical intersection of all of its
@@ -139,7 +151,15 @@
if (expressionSet == null) {
throw new IllegalArgumentException("expressionSet argument
cannot be null");
}
+ for (TemporalExpression that : expressionSet) {
+ if (this == that) {
+ throw new IllegalArgumentException("recursive expression");
+ }
+ }
this.expressionSet = expressionSet;
+ if (containsExpression(this)) {
+ throw new IllegalArgumentException("recursive expression");
+ }
if (this.expressionSet.size() > 0) {
TemporalExpression that = this.expressionSet.iterator().next();
if (this.compareTo(that) > 0) {
@@ -235,6 +255,15 @@
}
return finalSet;
}
+
+ protected boolean containsExpression(TemporalExpression expression) {
+ for (TemporalExpression setItem : this.expressionSet) {
+ if (setItem.containsExpression(expression)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/** This class represents a difference of two temporal expressions. */
@@ -246,11 +275,11 @@
if (included == null) {
throw new IllegalArgumentException("included argument cannot
be null");
}
- if (excluded == null) {
- throw new IllegalArgumentException("excluded argument cannot
be null");
- }
this.included = included;
this.excluded = excluded;
+ if (containsExpression(this)) {
+ throw new IllegalArgumentException("recursive expression");
+ }
if (this.compareTo(included) > 0) {
this.sequence = included.sequence;
this.subSequence = included.subSequence;
@@ -307,6 +336,10 @@
}
return finalSet;
}
+
+ protected boolean containsExpression(TemporalExpression expression) {
+ return this.included.containsExpression(expression) ||
this.excluded.containsExpression(expression);
+ }
}
/** A temporal expression that represents a range of dates. */
@@ -648,33 +681,19 @@
public boolean includesDate(Calendar cal) {
int dom = cal.get(Calendar.DAY_OF_MONTH);
- int end = this.end;
- if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) < end) {
- end = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
- }
- return dom >= this.start && dom <= end;
+ return dom >= this.start && dom <= this.end;
}
public Calendar first(Calendar cal) {
- int month = cal.get(Calendar.MONTH);
- Calendar first = (Calendar) cal.clone();
- if (first.get(Calendar.DAY_OF_MONTH) >
first.getActualMaximum(Calendar.DAY_OF_MONTH)) {
- first.set(Calendar.DAY_OF_MONTH,
first.getActualMaximum(Calendar.DAY_OF_MONTH));
- }
- setStartOfDay(first);
+ Calendar first = setStartOfDay((Calendar) cal.clone());
while (!includesDate(first)) {
first.add(Calendar.DAY_OF_MONTH, 1);
- if (first.get(Calendar.MONTH) != month) {
- first.set(Calendar.MONTH, month);
- first.set(Calendar.DAY_OF_MONTH, 1);
- }
}
return first;
}
public Calendar next(Calendar cal) {
- Calendar next = (Calendar) cal.clone();
- setStartOfDay(next);
+ Calendar next = setStartOfDay((Calendar) cal.clone());
next.add(Calendar.DAY_OF_MONTH, 1);
while (!includesDate(next)) {
next.add(Calendar.DAY_OF_MONTH, 1);
@@ -737,9 +756,7 @@
public Calendar first(Calendar cal) {
int month = cal.get(Calendar.MONTH);
- Calendar first = (Calendar) cal.clone();
- alignDayOfWeek(first);
- setStartOfDay(first);
+ Calendar first = setStartOfDay(alignDayOfWeek((Calendar)
cal.clone()));
if (first.before(cal)) {
first.set(Calendar.DAY_OF_MONTH, 1);
if (first.get(Calendar.MONTH) == month) {
@@ -752,9 +769,7 @@
public Calendar next(Calendar cal) {
int month = cal.get(Calendar.MONTH);
- Calendar next = (Calendar) cal.clone();
- alignDayOfWeek(next);
- setStartOfDay(next);
+ Calendar next = setStartOfDay(alignDayOfWeek((Calendar)
cal.clone()));
if (next.before(cal) || next.equals(cal)) {
next.set(Calendar.DAY_OF_MONTH, 1);
if (next.get(Calendar.MONTH) == month) {
@@ -765,7 +780,7 @@
return next;
}
- protected void alignDayOfWeek(Calendar cal) {
+ protected Calendar alignDayOfWeek(Calendar cal) {
cal.set(Calendar.DAY_OF_MONTH, 1);
if (this.occurrence > 0) {
while (cal.get(Calendar.DAY_OF_WEEK) != this.dayOfWeek) {
@@ -780,6 +795,7 @@
}
cal.add(Calendar.DAY_OF_MONTH, (this.occurrence + 1) * 7);
}
+ return cal;
}
}
@@ -840,8 +856,7 @@
}
public Calendar first(Calendar cal) {
- Calendar first = (Calendar) cal.clone();
- first.setTime(this.start);
+ Calendar first = prepareCal(cal);
while (first.before(cal)) {
first.add(this.freqType, this.freqCount);
}
@@ -849,12 +864,41 @@
}
public Calendar next(Calendar cal) {
- Calendar next = (Calendar) cal.clone();
- next.setTime(this.start);
- while (next.before(cal) || next.equals(cal)) {
+ Calendar next = first(cal);
+ if (next.equals(cal)) {
next.add(this.freqType, this.freqCount);
}
return next;
}
+
+ protected Calendar prepareCal(Calendar cal) {
+ // Performs a "sane" skip forward in time - avoids time consuming
loops
+ // like incrementing every second from Jan 1 2000 until today
+ Calendar skip = (Calendar) cal.clone();
+ skip.setTime(this.start);
+ long deltaMillis = cal.getTimeInMillis() - this.start.getTime();
+ if (deltaMillis < 1000) {
+ return skip;
+ }
+ long divisor = deltaMillis;
+ if (this.freqType == Calendar.DAY_OF_MONTH) {
+ divisor = 86400000;
+ } else if (this.freqType == Calendar.HOUR) {
+ divisor = 3600000;
+ } else if (this.freqType == Calendar.MINUTE) {
+ divisor = 60000;
+ } else if (this.freqType == Calendar.SECOND) {
+ divisor = 1000;
+ } else {
+ return skip;
+ }
+ float units = deltaMillis / divisor;
+ units = (units / this.freqCount) * this.freqCount;
+ skip.add(this.freqType, (int)units);
+ while (skip.after(cal)) {
+ skip.add(this.freqType, -this.freqCount);
+ }
+ return skip;
+ }
}
}