This is an automated email from the ASF dual-hosted git repository.

mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 7d9d6ac478 Keep temporal expressions with the same sequence apart in 
sorted sets
7d9d6ac478 is described below

commit 7d9d6ac47800eb020f94b06517d3109622b8f870
Author: Mridul Pathak <[email protected]>
AuthorDate: Fri Oct 30 20:08:05 2026 +0530

    Keep temporal expressions with the same sequence apart in sorted sets
    
    TemporalExpression.compareTo returned 0 for two different expressions with 
the same sequence, so a TreeSet of Union or Intersection members kept only one 
of them: two date ranges, or two hour ranges starting at the same hour, 
collapsed into one and the dropped dates were silently missing from the 
schedule. compareTo now returns 0 only for equal expressions; expressions with 
the same sequence are ordered by class name and then by the fields their equals 
method compares, through a new p [...]
---
 .../ofbiz/service/calendar/TemporalExpression.java | 27 +++++-
 .../service/calendar/TemporalExpressions.java      | 98 ++++++++++++++++++++++
 2 files changed, 122 insertions(+), 3 deletions(-)

diff --git 
a/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpression.java
 
b/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpression.java
index df557e95e5..81592d1ae4 100644
--- 
a/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpression.java
+++ 
b/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpression.java
@@ -19,6 +19,7 @@
 package org.apache.ofbiz.service.calendar;
 
 import java.io.Serializable;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.Set;
 import java.util.TreeSet;
@@ -62,10 +63,30 @@ public abstract class TemporalExpression implements 
Serializable, Comparable<Tem
 
     @Override
     public int compareTo(TemporalExpression obj) {
-        if (this.equals(obj)) {
-            return 0;
+        int result = Integer.compare(this.sequence, obj.sequence);
+        if (result != 0 || this.equals(obj)) {
+            return result;
         }
-        return Integer.compare(this.sequence, obj.sequence);
+        // Different expressions with the same sequence must not compare as 
equal,
+        // otherwise sorted sets (Union, Intersection members) drop one of 
them.
+        result = this.getClass().getName().compareTo(obj.getClass().getName());
+        if (result != 0) {
+            return result;
+        }
+        return compareToSameClass(obj);
+    }
+
+    /**
+     * Orders this expression against an expression of the same class and the 
same
+     * sequence that is not equal to it. Subclasses that override 
<code>equals</code>
+     * compare the same fields here, so that <code>compareTo</code> returns 0 
only for
+     * equal expressions. This implementation compares the expression IDs.
+     * @param other an expression of the same class as this one
+     * @return a negative integer, zero, or a positive integer as this 
expression
+     * sorts before, together with, or after <code>other</code>
+     */
+    protected int compareToSameClass(TemporalExpression other) {
+        return 
Comparator.nullsFirst(Comparator.<String>naturalOrder()).compare(this.id, 
other.id);
     }
 
     @Override
diff --git 
a/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpressions.java
 
b/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpressions.java
index 2f623affe5..c84a227045 100644
--- 
a/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpressions.java
+++ 
b/framework/service/src/main/java/org/apache/ofbiz/service/calendar/TemporalExpressions.java
@@ -21,6 +21,7 @@ package org.apache.ofbiz.service.calendar;
 import java.io.Serializable;
 import java.util.Collections;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -55,6 +56,19 @@ public class TemporalExpressions implements Serializable {
     public static final int SEQUENCE_MINUTE_RANGE = 200;
     public static final int SEQUENCE_MONTH_RANGE = 600;
 
+    /** Compares two member sets element by element, in evaluation order. */
+    private static int compareMembers(Set<TemporalExpression> members, 
Set<TemporalExpression> otherMembers) {
+        Iterator<TemporalExpression> iter = new TreeSet<>(members).iterator();
+        Iterator<TemporalExpression> otherIter = new 
TreeSet<>(otherMembers).iterator();
+        while (iter.hasNext() && otherIter.hasNext()) {
+            int result = iter.next().compareTo(otherIter.next());
+            if (result != 0) {
+                return result;
+            }
+        }
+        return Boolean.compare(iter.hasNext(), otherIter.hasNext());
+    }
+
     /** A temporal expression that represents a range of dates. */
     public static class DateRange extends TemporalExpression {
         private static final String MODULE = DateRange.class.getName();
@@ -100,6 +114,11 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            return this.range.compareTo(((DateRange) other).range);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             return includesDate(cal) ? cal : null;
@@ -218,6 +237,13 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            DayInMonth that = (DayInMonth) other;
+            int result = Integer.compare(this.dayOfWeek, that.dayOfWeek);
+            return result != 0 ? result : Integer.compare(this.occurrence, 
that.occurrence);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             int month = cal.get(Calendar.MONTH);
@@ -350,6 +376,13 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            DayOfMonthRange that = (DayOfMonthRange) other;
+            int result = Integer.compare(this.start, that.start);
+            return result != 0 ? result : Integer.compare(this.end, that.end);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = cal.clone();
@@ -469,6 +502,13 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            DayOfWeekRange that = (DayOfWeekRange) other;
+            int result = Integer.compare(this.start, that.start);
+            return result != 0 ? result : Integer.compare(this.end, that.end);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = cal.clone();
@@ -602,6 +642,13 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            Difference that = (Difference) other;
+            int result = this.included.compareTo(that.included);
+            return result != 0 ? result : 
this.excluded.compareTo(that.excluded);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = this.included.first(cal);
@@ -717,6 +764,16 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            Frequency that = (Frequency) other;
+            int result = this.start.compareTo(that.start);
+            if (result == 0) {
+                result = Integer.compare(this.freqType, that.freqType);
+            }
+            return result != 0 ? result : Integer.compare(this.freqCount, 
that.freqCount);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = prepareCal(cal);
@@ -879,6 +936,13 @@ public class TemporalExpressions implements Serializable {
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            HourRange that = (HourRange) other;
+            int result = Integer.compare(this.start, that.start);
+            return result != 0 ? result : Integer.compare(this.end, that.end);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = cal.clone();
@@ -1043,6 +1107,11 @@ public class TemporalExpressions implements Serializable 
{
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            return compareMembers(this.expressionSet, ((Intersection) 
other).expressionSet);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = cal.clone();
@@ -1166,6 +1235,13 @@ public class TemporalExpressions implements Serializable 
{
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            MinuteRange that = (MinuteRange) other;
+            int result = Integer.compare(this.start, that.start);
+            return result != 0 ? result : Integer.compare(this.end, that.end);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = cal.clone();
@@ -1323,6 +1399,13 @@ public class TemporalExpressions implements Serializable 
{
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            MonthRange that = (MonthRange) other;
+            int result = Integer.compare(this.start, that.start);
+            return result != 0 ? result : Integer.compare(this.end, that.end);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = cal.clone();
@@ -1485,6 +1568,16 @@ public class TemporalExpressions implements Serializable 
{
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            Substitution that = (Substitution) other;
+            int result = this.included.compareTo(that.included);
+            if (result == 0) {
+                result = this.excluded.compareTo(that.excluded);
+            }
+            return result != 0 ? result : 
this.substitute.compareTo(that.substitute);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             Calendar first = this.included.first(cal);
@@ -1601,6 +1694,11 @@ public class TemporalExpressions implements Serializable 
{
             return false;
         }
 
+        @Override
+        protected int compareToSameClass(TemporalExpression other) {
+            return compareMembers(this.expressionSet, ((Union) 
other).expressionSet);
+        }
+
         @Override
         public Calendar first(Calendar cal) {
             for (TemporalExpression expression : this.expressionSet) {

Reply via email to