svn commit: r900662 - in /ofbiz/trunk/framework: service/src/org/ofbiz/service/calendar/ webtools/webapp/webtools/tempexpr/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r900662 - in /ofbiz/trunk/framework: service/src/org/ofbiz/service/calendar/ webtools/webapp/webtools/tempexpr/

adrianc
Author: adrianc
Date: Tue Jan 19 05:57:10 2010
New Revision: 900662

URL: http://svn.apache.org/viewvc?rev=900662&view=rev
Log:
A lot more work on the temporal expressions. The previous implementation would handle simple expressions just fine, but complicated expressions didn't work. I also added a pretty printer class.

Added:
    ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java   (with props)
Modified:
    ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java
    ofbiz/trunk/framework/webtools/webapp/webtools/tempexpr/tempExprMaint.ftl

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java?rev=900662&r1=900661&r2=900662&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java Tue Jan 19 05:57:10 2010
@@ -365,7 +365,7 @@
             return this.info.isValidCurrent(cal.getTimeInMillis());
         }
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             long result = this.info.next(cal.getTimeInMillis());
             if (result == 0) {
                 return null;

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=900662&r1=900661&r2=900662&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 Jan 19 05:57:10 2010
@@ -27,41 +27,32 @@
 /** Temporal expression abstract class. */
 @SuppressWarnings("serial")
 public abstract class TemporalExpression implements Serializable, Comparable<TemporalExpression> {
-    protected TemporalExpression() {}
-
     /** Field used to sort expressions. Expression evaluation depends
      * on correct ordering. Expressions are evaluated from lowest value
      * to highest value. */
     protected int sequence = Integer.MAX_VALUE;
 
-    /** Field used to sort expressions. Expression evaluation depends
-     * on correct ordering. Expressions are evaluated from lowest value
-     * to highest value. */
-    protected int subSequence = Integer.MAX_VALUE;
-
     /** A unique ID for this expression. This field is intended to be used by
      * persistence classes. */
     protected String id = null;
 
-    /** Returns true if this expression includes the specified date.
-     * @param cal A date to evaluate
-     * @return true if this expression includes the date represented by
-     * <code>cal</code>
-     */
-    public abstract boolean includesDate(Calendar cal);
+    protected TemporalExpression() {}
 
-    /** Returns true if this expression is a candidate for substitution
-     * using the expression <code>expressionToTest</code> for the date
-     * <code>cal</code>. A <code>Substitution</code> object will call this
-     * method when it needs to know if this expression could have produced
-     * the date <code>cal</code> based on the expression
-     * <code>expressionToTest</code>.
-     * @param cal A date to evaluate
-     * @param expressionToTest An expression to evaluate
-     * @return true if this expression could have produced the date
-     * <code>cal</code> using the expression <code>expressionToTest</code>
+    /** Handles a <code>TemporalExpressionVisitor</code> visit.
+     * @param visitor
      */
-    public abstract boolean isSubstitutionCandidate(Calendar cal, TemporalExpression expressionToTest);
+    public abstract void accept(TemporalExpressionVisitor visitor);
+
+    public int compareTo(TemporalExpression obj) {
+        if (this.equals(obj) || obj.sequence == this.sequence) {
+            return 0;
+        }
+         return obj.sequence < this.sequence ? 1 : -1;
+    }
+
+    protected boolean containsExpression(TemporalExpression expression) {
+        return false;
+    }
 
     /** Returns a date representing the first occurrence of this expression
      * on or after a specified date. Returns <code>null</code> if there
@@ -72,30 +63,11 @@
      */
     public abstract Calendar first(Calendar cal);
 
-    /** Returns a date representing the next occurrence of this expression
-     * after a specified date. Returns <code>null</code> if there
-     * is no matching date.
-     * @param cal A date to evaluate
-     * @return A Calendar instance representing the first matching date,
-     * or <code>null</code> if no matching date is found
-     */
-    public abstract Calendar next(Calendar cal);
-
-    /** Handles a <code>TemporalExpressionVisitor</code> visit.
-     * @param visitor
+    /** Returns this expression's ID.
+     * @return Expression ID String
      */
-    public abstract void accept(TemporalExpressionVisitor visitor);
-
-    public int compareTo(TemporalExpression obj) {
-        if (this.equals(obj)) {
-            return 0;
-        }
-        if (obj.sequence < this.sequence) {
-            return 1;
-        } else if (obj.sequence > this.sequence) {
-            return -1;
-        }
-        return obj.subSequence < this.subSequence ? 1 : -1;
+    public String getId() {
+        return this.id;
     }
 
     /** Returns a range of dates matching this expression. Returns an
@@ -119,13 +91,39 @@
         return set;
     }
 
-    /** Returns this expression's ID.
-     * @return Expression ID String
+    /** Returns true if this expression includes the specified date.
+     * @param cal A date to evaluate
+     * @return true if this expression includes the date represented by
+     * <code>cal</code>
      */
-    public String getId() {
-        return this.id;
+    public abstract boolean includesDate(Calendar cal);
+
+    /** Returns true if this expression is a candidate for substitution
+     * using the expression <code>expressionToTest</code> for the date
+     * <code>cal</code>. A <code>Substitution</code> object will call this
+     * method when it needs to know if this expression could have produced
+     * the date <code>cal</code> based on the expression
+     * <code>expressionToTest</code>.
+     * @param cal A date to evaluate
+     * @param expressionToTest An expression to evaluate
+     * @return true if this expression could have produced the date
+     * <code>cal</code> using the expression <code>expressionToTest</code>
+     */
+    public abstract boolean isSubstitutionCandidate(Calendar cal, TemporalExpression expressionToTest);
+
+    /** Returns a date representing the next occurrence of this expression
+     * after a specified date. Returns <code>null</code> if there
+     * is no matching date.
+     * @param cal A date to evaluate
+     * @return A Calendar instance representing the first matching date,
+     * or <code>null</code> if no matching date is found
+     */
+    public Calendar next(Calendar cal) {
+        return next(cal, new ExpressionContext());
     }
 
+    protected abstract Calendar next(Calendar cal, ExpressionContext context);
+
     /** Sets this expression's ID.
      * @param id Expression ID String
      */
@@ -133,15 +131,14 @@
         this.id = id;
     }
 
-    protected boolean containsExpression(TemporalExpression expression) {
-        return false;
+    @Override
+    public String toString() {
+        return this.getClass().getSimpleName() + " [" + this.id + "]";
     }
 
-    protected Calendar setStartOfDay(Calendar cal) {
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-        return cal;
+    protected class ExpressionContext {
+        public boolean hourBumped = false;
+        public boolean dayBumped = false;
+        public boolean monthBumped = false;
     }
 }

Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java?rev=900662&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java Tue Jan 19 05:57:10 2010
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.service.calendar;
+
+import org.ofbiz.service.calendar.TemporalExpressions.DateRange;
+import org.ofbiz.service.calendar.TemporalExpressions.DayInMonth;
+import org.ofbiz.service.calendar.TemporalExpressions.DayOfMonthRange;
+import org.ofbiz.service.calendar.TemporalExpressions.DayOfWeekRange;
+import org.ofbiz.service.calendar.TemporalExpressions.Difference;
+import org.ofbiz.service.calendar.TemporalExpressions.Frequency;
+import org.ofbiz.service.calendar.TemporalExpressions.HourRange;
+import org.ofbiz.service.calendar.TemporalExpressions.Intersection;
+import org.ofbiz.service.calendar.TemporalExpressions.MinuteRange;
+import org.ofbiz.service.calendar.TemporalExpressions.MonthRange;
+import org.ofbiz.service.calendar.TemporalExpressions.Null;
+import org.ofbiz.service.calendar.TemporalExpressions.Substitution;
+import org.ofbiz.service.calendar.TemporalExpressions.TimeOfDayRange;
+import org.ofbiz.service.calendar.TemporalExpressions.Union;
+
+/** Temporal expression pretty printer. */
+@SuppressWarnings("deprecation")
+public class TemporalExpressionPrinter implements TemporalExpressionVisitor {
+    protected final TemporalExpression expression;
+    protected final StringBuilder sb = new StringBuilder();
+    protected int indentSize = 2;
+    protected int currentIndent = 0;
+    
+    public TemporalExpressionPrinter(TemporalExpression expression) {
+        this.expression = expression;
+    }
+
+    public TemporalExpressionPrinter(TemporalExpression expression, int indentSize) {
+        this.expression = expression;
+        if (indentSize > 0) {
+            this.indentSize = indentSize;
+        }
+    }
+
+    protected void appendExpression(TemporalExpression expression) {
+        appendIndent();
+        this.sb.append(expression);
+        this.sb.append("\n");
+    }
+
+    protected void appendIndent() {
+        for (int i = 0; i < this.currentIndent; i++) {
+            this.sb.append(" ");
+        }
+    }
+
+    protected void indent() {
+        this.currentIndent += this.indentSize;
+    }
+
+    @Override
+    public String toString() {
+        this.expression.accept(this);
+        return this.sb.toString();
+    }
+
+    protected void unIndent() {
+        this.currentIndent -= this.indentSize;
+    }
+
+    @Override
+    public void visit(DateRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(DayInMonth expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(DayOfMonthRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(DayOfWeekRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(Difference expr) {
+        appendIndent();
+        this.sb.append("Difference [");
+        this.sb.append(expr.getId());
+        this.sb.append("]:\n");
+        indent();
+        appendIndent();
+        this.sb.append("Include:\n");
+        indent();
+        expr.included.accept(this);
+        unIndent();
+        appendIndent();
+        this.sb.append("Exclude:\n");
+        indent();
+        expr.excluded.accept(this);
+        unIndent();
+        unIndent();
+    }
+
+    @Override
+    public void visit(Frequency expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(HourRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(Intersection expr) {
+        appendIndent();
+        this.sb.append("Intersection [");
+        this.sb.append(expr.getId());
+        this.sb.append("]:\n");
+        indent();
+        for (TemporalExpression member: expr.expressionSet) {
+            member.accept(this);
+        }
+        unIndent();
+    }
+
+    @Override
+    public void visit(MinuteRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(MonthRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(Null expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(Substitution expr) {
+        appendIndent();
+        this.sb.append("Substitution [");
+        this.sb.append(expr.getId());
+        this.sb.append("]:\n");
+        indent();
+        appendIndent();
+        this.sb.append("Include:\n");
+        indent();
+        expr.included.accept(this);
+        unIndent();
+        appendIndent();
+        this.sb.append("Exclude:\n");
+        indent();
+        expr.excluded.accept(this);
+        unIndent();
+        appendIndent();
+        this.sb.append("Substitute:\n");
+        indent();
+        expr.substitute.accept(this);
+        unIndent();
+        unIndent();
+    }
+
+    @Override
+    public void visit(TimeOfDayRange expr) {
+        appendExpression(expr);
+    }
+
+    @Override
+    public void visit(Union expr) {
+        appendIndent();
+        this.sb.append("Union [");
+        this.sb.append(expr.getId());
+        this.sb.append("]:\n");
+        indent();
+        for (TemporalExpression member: expr.expressionSet) {
+            member.accept(this);
+        }
+        unIndent();
+    }
+}

Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionPrinter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java?rev=900662&r1=900661&r2=900662&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java Tue Jan 19 05:57:10 2010
@@ -30,7 +30,6 @@
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.condition.EntityCondition;
-import org.ofbiz.entity.util.EntityUtil;
 
 /** TemporalExpression persistence worker. */
 public class TemporalExpressionWorker {
@@ -68,7 +67,12 @@
         if (UtilValidate.isEmpty(exprValue)) {
             throw new IllegalArgumentException("tempExprId argument invalid - expression not found");
         }
-        return makeTemporalExpression(delegator, exprValue);
+        TemporalExpression result = makeTemporalExpression(delegator, exprValue);
+        if (Debug.verboseOn()) {
+            TemporalExpressionPrinter printer = new TemporalExpressionPrinter(result);
+            Debug.logVerbose(printer.toString(), module);
+        }
+        return result;
     }
 
     /** Create a <code>TemporalExpression</code> instance from a TemporalExpression
@@ -84,35 +88,53 @@
         String tempExprId = exprValue.getString("tempExprId");
         String tempExprTypeId = exprValue.getString("tempExprTypeId");
         if (DateRange.equals(tempExprTypeId)) {
-            return new TemporalExpressions.DateRange(exprValue.getTimestamp("date1"), exprValue.getTimestamp("date2"));
+            return setExpressionId(exprValue, new TemporalExpressions.DateRange(exprValue.getTimestamp("date1"), exprValue.getTimestamp("date2")));
         } else if (DayInMonth.equals(tempExprTypeId)) {
-            return new TemporalExpressions.DayInMonth(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.DayInMonth(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (DayOfMonthRange.equals(tempExprTypeId)) {
-            return new TemporalExpressions.DayOfMonthRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.DayOfMonthRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (DayOfWeekRange.equals(tempExprTypeId)) {
-            return new TemporalExpressions.DayOfWeekRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.DayOfWeekRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (Difference.equals(tempExprTypeId)) {
-            GenericValue inclAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "INCLUDE")), null, null, null, true));
-            GenericValue exclAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "EXCLUDE")), null, null, null, true));
+            List<GenericValue> childExpressions = delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition("fromTempExprId", tempExprId), null, null, null, true);
+            GenericValue inclAssoc = null;
+            GenericValue exclAssoc = null;
+            for (GenericValue childExpression : childExpressions) {
+                if ("INCLUDE".equals(childExpression.get("exprAssocType"))) {
+                    inclAssoc = childExpression;
+                } else if ("EXCLUDE".equals(childExpression.get("exprAssocType"))) {
+                    exclAssoc = childExpression;
+                }
+            }
             if (inclAssoc != null && exclAssoc != null) {
-                return new TemporalExpressions.Difference(getTemporalExpression(delegator, inclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, exclAssoc.getString("toTempExprId")));
+                return setExpressionId(exprValue, new TemporalExpressions.Difference(getTemporalExpression(delegator, inclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, exclAssoc.getString("toTempExprId"))));
             }
         } else if (Frequency.equals(tempExprTypeId)) {
-            return new TemporalExpressions.Frequency(exprValue.getTimestamp("date1"), exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.Frequency(exprValue.getTimestamp("date1"), exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (HourRange.equals(tempExprTypeId)) {
-            return new TemporalExpressions.HourRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.HourRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (Intersection.equals(tempExprTypeId)) {
-            return new TemporalExpressions.Intersection(getChildExpressions(delegator, tempExprId));
+            return setExpressionId(exprValue, new TemporalExpressions.Intersection(getChildExpressions(delegator, tempExprId)));
         } else if (MinuteRange.equals(tempExprTypeId)) {
-            return new TemporalExpressions.MinuteRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.MinuteRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (MonthRange.equals(tempExprTypeId)) {
-            return new TemporalExpressions.MonthRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue());
+            return setExpressionId(exprValue, new TemporalExpressions.MonthRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()));
         } else if (Substitution.equals(tempExprTypeId)) {
-            GenericValue inclAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "INCLUDE")), null, null, null, true));
-            GenericValue exclAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "EXCLUDE")), null, null, null, true));
-            GenericValue substAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "SUBSTITUTION")), null, null, null, true));
+            List<GenericValue> childExpressions = delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition("fromTempExprId", tempExprId), null, null, null, true);
+            GenericValue inclAssoc = null;
+            GenericValue exclAssoc = null;
+            GenericValue substAssoc = null;
+            for (GenericValue childExpression : childExpressions) {
+                if ("INCLUDE".equals(childExpression.get("exprAssocType"))) {
+                    inclAssoc = childExpression;
+                } else if ("EXCLUDE".equals(childExpression.get("exprAssocType"))) {
+                    exclAssoc = childExpression;
+                } else if ("SUBSTITUTION".equals(childExpression.get("exprAssocType"))) {
+                    substAssoc = childExpression;
+                }
+            }
             if (inclAssoc != null && exclAssoc != null && substAssoc != null) {
-                return new TemporalExpressions.Substitution(getTemporalExpression(delegator, inclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, exclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, substAssoc.getString("toTempExprId")));
+                return setExpressionId(exprValue, new TemporalExpressions.Substitution(getTemporalExpression(delegator, inclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, exclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, substAssoc.getString("toTempExprId"))));
             }
         } else if (TimeOfDayRange.equals(tempExprTypeId)) {
             Debug.logWarning(TimeOfDayRange + " has been deprecated. Use " + HourRange + " and/or " + MinuteRange, module);
@@ -126,9 +148,9 @@
             if (longObj != null) {
                 count = longObj.intValue();
             }
-            return new TemporalExpressions.TimeOfDayRange(exprValue.getString("string1"), exprValue.getString("string2"), interval, count);
+            return setExpressionId(exprValue, new TemporalExpressions.TimeOfDayRange(exprValue.getString("string1"), exprValue.getString("string2"), interval, count));
         } else if (Union.equals(tempExprTypeId)) {
-            return new TemporalExpressions.Union(getChildExpressions(delegator, tempExprId));
+            return setExpressionId(exprValue, new TemporalExpressions.Union(getChildExpressions(delegator, tempExprId)));
         }
         return TemporalExpressions.NullExpression;
     }
@@ -144,4 +166,9 @@
         }
         return exprList;
     }
+
+    protected static TemporalExpression setExpressionId(GenericValue value, TemporalExpression expression) {
+        expression.setId(value.getString("tempExprId"));
+        return expression;
+    }
 }

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=900662&r1=900661&r2=900662&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 Jan 19 05:57:10 2010
@@ -37,23 +37,21 @@
 public class TemporalExpressions implements Serializable {
     public static final String module = TemporalExpressions.class.getName();
     public static final TemporalExpression NullExpression = new Null();
-    // Expressions are evaluated from largest unit of time to smallest.
+    // Expressions are evaluated from smallest unit of time to largest.
     // When unit of time is the same, then they are evaluated from
     // least ambiguous to most. Frequency should always be first -
     // since it is the most specific. Date range should always be last.
     // The idea is to evaluate all other expressions, then check to see
     // if the result falls within the date range.
-    public static final int SEQUENCE_DATE_RANGE = 10000;
-    public static final int SEQUENCE_DAY_IN_MONTH = 400;
-    public static final int SEQUENCE_DOM_RANGE = 300;
-    public static final int SEQUENCE_DOW_RANGE = 500;
+    public static final int SEQUENCE_DATE_RANGE = 800;
+    public static final int SEQUENCE_DAY_IN_MONTH = 460;
+    public static final int SEQUENCE_DOM_RANGE = 400;
+    public static final int SEQUENCE_DOW_RANGE = 450;
     public static final int SEQUENCE_FREQ = 100;
-    public static final int SEQUENCE_HOUR_RANGE = 700;
-    public static final int SEQUENCE_MINUTE_RANGE = 800;
-    public static final int SEQUENCE_MONTH_RANGE = 200;
-    public static final int SEQUENCE_SUBSTITUTION = 9000;
-    public static final int SEQUENCE_TOD_RANGE = 600;
-    
+    public static final int SEQUENCE_HOUR_RANGE = 300;
+    public static final int SEQUENCE_MINUTE_RANGE = 200;
+    public static final int SEQUENCE_MONTH_RANGE = 600;
+    public static final int SEQUENCE_TOD_RANGE = 350;
 
     /** A temporal expression that represents a range of dates. */
     public static class DateRange extends TemporalExpression {
@@ -64,8 +62,8 @@
         }
 
         public DateRange(Date start, Date end) {
-            this.sequence = SEQUENCE_DATE_RANGE;
             this.range = new org.ofbiz.base.util.DateRange(start, end);
+            this.sequence = SEQUENCE_DATE_RANGE;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -110,7 +108,7 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             return includesDate(cal) ? cal : null;
         }
 
@@ -137,10 +135,15 @@
             if (occurrence < -5 || occurrence == 0 || occurrence > 5) {
                 throw new IllegalArgumentException("Invalid occurrence argument");
             }
-            this.sequence = SEQUENCE_DAY_IN_MONTH;
-            this.subSequence = (occurrence * 7) + dayOfWeek;
             this.dayOfWeek = dayOfWeek;
             this.occurrence = occurrence;
+            int result = occurrence;
+            if (result < 0) {
+                // Make negative values a higher sequence
+                // Example: Last Monday should come after first Monday
+                result += 11;
+            }
+            this.sequence = SEQUENCE_DAY_IN_MONTH + (result * 10) + dayOfWeek;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -184,7 +187,7 @@
         @Override
         public Calendar first(Calendar cal) {
             int month = cal.get(Calendar.MONTH);
-            Calendar first = setStartOfDay(alignDayOfWeek((Calendar) cal.clone()));
+            Calendar first = alignDayOfWeek((Calendar) cal.clone());
             if (first.before(cal)) {
                 first.set(Calendar.DAY_OF_MONTH, 1);
                 if (first.get(Calendar.MONTH) == month) {
@@ -235,9 +238,9 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             int month = cal.get(Calendar.MONTH);
-            Calendar next = setStartOfDay(alignDayOfWeek((Calendar) cal.clone()));
+            Calendar next = alignDayOfWeek((Calendar) cal.clone());
             if (next.before(cal) || next.equals(cal)) {
                 next.set(Calendar.DAY_OF_MONTH, 1);
                 if (next.get(Calendar.MONTH) == month) {
@@ -274,8 +277,7 @@
             if (end < 1 || end > 31) {
                 throw new IllegalArgumentException("Invalid end argument");
             }
-            this.sequence = SEQUENCE_DOM_RANGE;
-            this.subSequence = start;
+            this.sequence = SEQUENCE_DOM_RANGE + start;
             this.start = start;
             this.end = end;
             if (Debug.verboseOn()) {
@@ -302,7 +304,7 @@
 
         @Override
         public Calendar first(Calendar cal) {
-            Calendar first = setStartOfDay((Calendar) cal.clone());
+            Calendar first = (Calendar) cal.clone();
             while (!includesDate(first)) {
                 first.add(Calendar.DAY_OF_MONTH, 1);
             }
@@ -343,8 +345,8 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
-            Calendar next = setStartOfDay((Calendar) cal.clone());
+        public Calendar next(Calendar cal, ExpressionContext context) {
+            Calendar next = (Calendar) cal.clone();
             next.add(Calendar.DAY_OF_MONTH, 1);
             while (!includesDate(next)) {
                 next.add(Calendar.DAY_OF_MONTH, 1);
@@ -380,8 +382,7 @@
             if (end < Calendar.SUNDAY || end > Calendar.SATURDAY) {
                 throw new IllegalArgumentException("Invalid end argument");
             }
-            this.sequence = SEQUENCE_DOW_RANGE;
-            this.subSequence = start;
+            this.sequence = SEQUENCE_DOW_RANGE + start;
             this.start = start;
             this.end = end;
             if (Debug.verboseOn()) {
@@ -412,7 +413,7 @@
             while (!includesDate(first)) {
                 first.add(Calendar.DAY_OF_MONTH, 1);
             }
-            return setStartOfDay(first);
+            return first;
         }
 
         /** Returns the ending day of this range.
@@ -462,13 +463,21 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = (Calendar) cal.clone();
-            next.add(Calendar.DAY_OF_MONTH, 1);
+            if (includesDate(next)) {
+                if (context.dayBumped) {
+                    return next;
+                }
+                next.add(Calendar.DAY_OF_MONTH, 1);
+            }
             while (!includesDate(next)) {
                 next.add(Calendar.DAY_OF_MONTH, 1);
             }
-            return setStartOfDay(next);
+            if (cal.get(Calendar.MONTH) != next.get(Calendar.MONTH)) {
+                context.monthBumped = true;
+            }
+            return next;
         }
 
         @Override
@@ -491,10 +500,7 @@
             if (containsExpression(this)) {
                 throw new IllegalArgumentException("recursive expression");
             }
-            if (this.compareTo(included) > 0) {
-                this.sequence = included.sequence;
-                this.subSequence = included.subSequence;
-            }
+            this.sequence = included.sequence;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -546,20 +552,6 @@
         }
 
         @Override
-        public Set<Date> getRange(org.ofbiz.base.util.DateRange range, Calendar cal) {
-            Set<Date> finalSet = new TreeSet<Date>();
-            Set<Date> rawSet = this.included.getRange(range, cal);
-            Calendar checkCal = (Calendar) cal.clone();
-            for (Date date : rawSet) {
-                checkCal.setTime(date);
-                if (!this.excluded.includesDate(checkCal)) {
-                    finalSet.add(date);
-                }
-            }
-            return finalSet;
-        }
-
-        @Override
         public boolean includesDate(Calendar cal) {
             return this.included.includesDate(cal) && !this.excluded.includesDate(cal);
         }
@@ -570,10 +562,10 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
-            Calendar next = this.included.next(cal);
+        public Calendar next(Calendar cal, ExpressionContext context) {
+            Calendar next = this.included.next(cal, context);
             while (next != null && this.excluded.includesDate(next)) {
-                next = this.included.next(next);
+                next = this.included.next(next, context);
             }
             return next;
         }
@@ -611,8 +603,7 @@
             } else {
                 this.start = new Date();
             }
-            this.sequence = SEQUENCE_FREQ;
-            this.subSequence = freqType;
+            this.sequence = SEQUENCE_FREQ + freqType;
             this.freqType = freqType;
             this.freqCount = freqCount;
             if (Debug.verboseOn()) {
@@ -687,7 +678,7 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = first(cal);
             if (next.equals(cal)) {
                 next.add(this.freqType, this.freqCount);
@@ -757,8 +748,7 @@
             }
             this.start = start;
             this.end = end;
-            this.sequence = SEQUENCE_HOUR_RANGE;
-            this.subSequence = start;
+            this.sequence = SEQUENCE_HOUR_RANGE + start;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -850,12 +840,20 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = (Calendar) cal.clone();
-            next.add(Calendar.HOUR_OF_DAY, 1);
+            if (includesDate(next)) {
+                if (context.hourBumped) {
+                    return next;
+                }
+                next.add(Calendar.HOUR_OF_DAY, 1);
+            }
             while (!includesDate(next)) {
                 next.add(Calendar.HOUR_OF_DAY, 1);
             }
+            if (cal.get(Calendar.DAY_OF_MONTH) != next.get(Calendar.DAY_OF_MONTH)) {
+                context.dayBumped = true;
+            }
             return next;
         }
 
@@ -864,6 +862,7 @@
             return super.toString() + ", start = " + this.start + ", end = " + this.end;
         }
     }
+
     /** A temporal expression that represents a mathematical intersection of all of its
      * member expressions. */
     public static class Intersection extends TemporalExpression {
@@ -878,11 +877,13 @@
                 throw new IllegalArgumentException("recursive expression");
             }
             if (this.expressionSet.size() > 0) {
-                TemporalExpression that = this.expressionSet.iterator().next();
-                if (this.compareTo(that) > 0) {
-                    this.sequence = that.sequence;
-                    this.subSequence = that.subSequence;
+                int result = 0;
+                TemporalExpression[] exprArray = this.expressionSet.toArray(new TemporalExpression[this.expressionSet.size()]);
+                for (int i = exprArray.length - 1; i >= 0; i--) {
+                    result += exprArray[i].sequence;
+                    result *= 10;
                 }
+                this.sequence = result;
             }
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
@@ -940,30 +941,6 @@
         }
 
         @Override
-        public Set<Date> getRange(org.ofbiz.base.util.DateRange range, Calendar cal) {
-            Set<Date> finalSet = new TreeSet<Date>();
-            Set<Date> rawSet = new TreeSet<Date>();
-            Date last = range.start();
-            Calendar next = first(cal);
-            while (next != null && range.includesDate(next.getTime())) {
-                last = next.getTime();
-                rawSet.add(last);
-                next = next(next);
-                if (next != null && last.equals(next.getTime())) {
-                    break;
-                }
-            }
-            Calendar checkCal = (Calendar) cal.clone();
-            for (Date date : rawSet) {
-                checkCal.setTime(date);
-                if (includesDate(checkCal)) {
-                    finalSet.add(date);
-                }
-            }
-            return finalSet;
-        }
-
-        @Override
         public boolean includesDate(Calendar cal) {
             for (TemporalExpression expression : this.expressionSet) {
                 if (!expression.includesDate(cal)) {
@@ -984,19 +961,15 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = (Calendar) cal.clone();
             for (TemporalExpression expression : this.expressionSet) {
-                next = expression.next(next);
+                next = expression.next(next, context);
                 if (next == null) {
                     return null;
                 }
             }
-            if (includesDate(next)) {
-                return next;
-            } else {
-                return null;
-            }
+            return next;
         }
 
         @Override
@@ -1030,8 +1003,7 @@
             }
             this.start = start;
             this.end = end;
-            this.sequence = SEQUENCE_MINUTE_RANGE;
-            this.subSequence = start;
+            this.sequence = SEQUENCE_MINUTE_RANGE + start;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -1123,12 +1095,17 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = (Calendar) cal.clone();
-            next.add(Calendar.MINUTE, 1);
+            if (includesDate(next)) {
+                next.add(Calendar.MINUTE, 1);
+            }
             while (!includesDate(next)) {
                 next.add(Calendar.MINUTE, 1);
             }
+            if (cal.get(Calendar.HOUR_OF_DAY) != next.get(Calendar.HOUR_OF_DAY)) {
+                context.hourBumped = true;
+            }
             return next;
         }
 
@@ -1160,8 +1137,7 @@
             if (end < Calendar.JANUARY || end > Calendar.UNDECIMBER) {
                 throw new IllegalArgumentException("Invalid end argument");
             }
-            this.sequence = SEQUENCE_MONTH_RANGE;
-            this.subSequence = start;
+            this.sequence = SEQUENCE_MONTH_RANGE + start;
             this.start = start;
             this.end = end;
             if (Debug.verboseOn()) {
@@ -1243,7 +1219,7 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = (Calendar) cal.clone();
             next.set(Calendar.DAY_OF_MONTH, 1);
             next.add(Calendar.MONTH, 1);
@@ -1278,7 +1254,7 @@
             return false;
         }
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             return null;
         }
     }
@@ -1305,10 +1281,7 @@
             if (containsExpression(this)) {
                 throw new IllegalArgumentException("recursive expression");
             }
-            if (this.compareTo(included) > 0) {
-                this.sequence = included.sequence;
-                this.subSequence = included.subSequence;
-            }
+            this.sequence = included.sequence;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -1359,25 +1332,6 @@
             return this.included;
         }
 
-        @Override
-        public Set<Date> getRange(org.ofbiz.base.util.DateRange range, Calendar cal) {
-            Set<Date> finalSet = new TreeSet<Date>();
-            Set<Date> rawSet = this.included.getRange(range, cal);
-            Calendar checkCal = (Calendar) cal.clone();
-            for (Date date : rawSet) {
-                checkCal.setTime(date);
-                if (this.excluded.includesDate(checkCal)) {
-                    Calendar substCal = this.excluded.first(checkCal);
-                    if (substCal != null) {
-                        finalSet.add(substCal.getTime());
-                    }
-                } else {
-                    finalSet.add(checkCal.getTime());
-                }
-            }
-            return finalSet;
-        }
-
         /** Returns the substitute expression.
          * @return The substitute <code>TemporalExpression</code>
          */
@@ -1399,10 +1353,10 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
-            Calendar next = this.included.next(cal);
+        public Calendar next(Calendar cal, ExpressionContext context) {
+            Calendar next = this.included.next(cal, context);
             if (next != null && this.excluded.includesDate(next)) {
-                next = this.substitute.next(next);
+                next = this.substitute.next(next, context);
             }
             return next;
         }
@@ -1473,8 +1427,7 @@
             if (this.endHrs > 23 || this.endMins > 59 || this.endSecs > 59) {
                 throw new IllegalArgumentException("Invalid end time argument");
             }
-            this.sequence = SEQUENCE_TOD_RANGE;
-            this.subSequence = this.startHrs;
+            this.sequence = SEQUENCE_TOD_RANGE + this.startHrs;
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
             }
@@ -1564,7 +1517,7 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar next = (Calendar) cal.clone();
             next.add(this.interval, this.count);
             if (!includesDate(next)) {
@@ -1616,10 +1569,7 @@
             }
             if (this.expressionSet.size() > 0) {
                 TemporalExpression that = this.expressionSet.iterator().next();
-                if (this.compareTo(that) > 0) {
-                    this.sequence = that.sequence;
-                    this.subSequence = that.subSequence;
-                }
+                this.sequence = that.sequence;
             }
             if (Debug.verboseOn()) {
                 Debug.logVerbose("Created " + this, module);
@@ -1672,23 +1622,6 @@
         }
 
         @Override
-        public Set<Date> getRange(org.ofbiz.base.util.DateRange range, Calendar cal) {
-            Set<Date> rawSet = new TreeSet<Date>();
-            Set<Date> finalSet = new TreeSet<Date>();
-            for (TemporalExpression expression : this.expressionSet) {
-                rawSet.addAll(expression.getRange(range, cal));
-            }
-            Calendar checkCal = (Calendar) cal.clone();
-            for (Date date : rawSet) {
-                checkCal.setTime(date);
-                if (includesDate(checkCal)) {
-                    finalSet.add(date);
-                }
-            }
-            return finalSet;
-        }
-
-        @Override
         public boolean includesDate(Calendar cal) {
             for (TemporalExpression expression : this.expressionSet) {
                 if (expression.includesDate(cal)) {
@@ -1709,11 +1642,11 @@
         }
 
         @Override
-        public Calendar next(Calendar cal) {
+        public Calendar next(Calendar cal, ExpressionContext context) {
             Calendar result = null;
             for (TemporalExpression expression : this.expressionSet) {
-                Calendar next = expression.next(cal);
-                if (next != null && includesDate(next)) {
+                Calendar next = expression.next(cal, context);
+                if (next != null) {
                     if (result == null || next.before(result)) {
                         result = next;
                     }

Modified: ofbiz/trunk/framework/webtools/webapp/webtools/tempexpr/tempExprMaint.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webtools/webapp/webtools/tempexpr/tempExprMaint.ftl?rev=900662&r1=900661&r2=900662&view=diff
==============================================================================
--- ofbiz/trunk/framework/webtools/webapp/webtools/tempexpr/tempExprMaint.ftl (original)
+++ ofbiz/trunk/framework/webtools/webapp/webtools/tempexpr/tempExprMaint.ftl Tue Jan 19 05:57:10 2010
@@ -84,7 +84,7 @@
             <td><@CreateExprAssocForm formName="excludeExpression" exprAssocType="EXCLUDE"/></td>
           </tr>
         </#if>
-        <#if !hasSubstitution>
+        <#if !hasSubstitution && temporalExpression.tempExprTypeId == "SUBSTITUTION">
           <tr>
             <td class="label">${uiLabelMap.TemporalExpression_SUBSTITUTION}</td>
             <td><@CreateExprAssocForm formName="substitutionExpression" exprAssocType="SUBSTITUTION"/></td>