This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/release24.09 by this push:
new 21e918308f Keep temporal expressions with the same sequence apart in
sorted sets
21e918308f is described below
commit 21e918308fb78a4b6633ac8291548aa5750a7b66
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 b5d2e40475..edebdfc7a7 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 8658c4d406..6ba4012b28 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 = (Calendar) 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 = (Calendar) cal.clone();
@@ -605,6 +645,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);
@@ -720,6 +767,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);
@@ -882,6 +939,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 = (Calendar) cal.clone();
@@ -1049,6 +1113,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 = (Calendar) cal.clone();
@@ -1172,6 +1241,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 = (Calendar) cal.clone();
@@ -1332,6 +1408,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 = (Calendar) cal.clone();
@@ -1494,6 +1577,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);
@@ -1610,6 +1703,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) {