This is an automated email from the ASF dual-hosted git repository.
dgriffon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/unomi.git
The following commit(s) were added to refs/heads/master by this push:
new 34b390d UNOMI-523 : add date expression support to isDay / isNotDay
property comparison (#359)
34b390d is described below
commit 34b390d42c63824ea7d855f8c93a0822bfebc5a7
Author: David Griffon <[email protected]>
AuthorDate: Mon Nov 8 13:48:06 2021 +0100
UNOMI-523 : add date expression support to isDay / isNotDay property
comparison (#359)
* UNOMI-523 : add date expression to isDay / isNotDay property comparison
operator. (bonus, fix double property type support)
* DMF-5016 : add support of date expression for multiple values
---
.../org/apache/unomi/itests/ConditionBuilder.java | 24 +++++++++++++++++
.../apache/unomi/itests/ConditionEvaluatorIT.java | 7 +++++
.../PropertyConditionESQueryBuilder.java | 6 +++--
.../conditions/PropertyConditionEvaluator.java | 30 ++++++++++++++--------
4 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/itests/src/test/java/org/apache/unomi/itests/ConditionBuilder.java
b/itests/src/test/java/org/apache/unomi/itests/ConditionBuilder.java
index 2d01f97..69a210f 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ConditionBuilder.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ConditionBuilder.java
@@ -141,6 +141,10 @@ public class ConditionBuilder {
return op("in").stringValues(values);
}
+ public ComparisonCondition inDateExpr(String... values) {
+ return op("in").dateExprValues(values);
+ }
+
public ComparisonCondition in(Date... values) {
return op("in").dateValues(values);
}
@@ -149,10 +153,18 @@ public class ConditionBuilder {
return op("isDay").dateValue(value);
}
+ public ComparisonCondition isDay(String expression) {
+ return op("isDay").dateValueExpr(expression);
+ }
+
public ComparisonCondition isNotDay(Date value) {
return op("isNotDay").dateValue(value);
}
+ public ComparisonCondition isNotDay(String expression) {
+ return op("isNotDay").dateValueExpr(expression);
+ }
+
public ComparisonCondition in(Integer... values) {
return op("in").integerValues(values);
}
@@ -221,6 +233,10 @@ public class ConditionBuilder {
return op("notIn").dateValues(values);
}
+ public ComparisonCondition notInDateExpr(String... values) {
+ return op("notIn").dateExprValues(values);
+ }
+
public ComparisonCondition notIn(Integer... values) {
return op("notIn").integerValues(values);
}
@@ -262,6 +278,10 @@ public class ConditionBuilder {
return parameter("propertyValueDate", value);
}
+ private ComparisonCondition dateValueExpr(String value) {
+ return parameter("propertyValueDateExpr", value);
+ }
+
private ComparisonCondition stringValues(String... values) {
return parameter("propertyValues", values != null ?
Arrays.asList(values) : null);
}
@@ -277,6 +297,10 @@ public class ConditionBuilder {
private ComparisonCondition dateValues(Date... values) {
return parameter("propertyValuesDate", values != null ?
Arrays.asList(values) : null);
}
+
+ private ComparisonCondition dateExprValues(String... values) {
+ return parameter("propertyValuesDateExpr", values != null ?
Arrays.asList(values) : null);
+ }
}
public class CompoundCondition extends ConditionItem {
diff --git
a/itests/src/test/java/org/apache/unomi/itests/ConditionEvaluatorIT.java
b/itests/src/test/java/org/apache/unomi/itests/ConditionEvaluatorIT.java
index 427f45f..da837e5 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ConditionEvaluatorIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ConditionEvaluatorIT.java
@@ -17,6 +17,7 @@
package org.apache.unomi.itests;
+import org.apache.commons.lang3.time.DateUtils;
import org.apache.unomi.api.Item;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.conditions.Condition;
@@ -32,6 +33,7 @@ import org.ops4j.pax.exam.util.Filter;
import javax.inject.Inject;
import java.util.*;
+import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
@@ -116,6 +118,11 @@ public class ConditionEvaluatorIT extends BaseIT {
assertTrue(eval(builder.profileProperty("properties.lastVisit").isDay(lastVisit).build()));
assertTrue(eval(builder.profileProperty("properties.lastVisit").isNotDay(new
Date(lastVisit.getTime() + (24*60*60*1000))).build()));
+ long daysFromToday =
TimeUnit.MILLISECONDS.toDays(DateUtils.truncate(new Date(),
Calendar.DAY_OF_MONTH).getTime() - DateUtils.truncate(lastVisit,
Calendar.DAY_OF_MONTH).getTime());
+
assertTrue(eval(builder.profileProperty("properties.lastVisit").isDay("now-" +
daysFromToday + "d").build()));
+
assertTrue(eval(builder.profileProperty("properties.lastVisit").isNotDay("now-"
+ (daysFromToday + 1) + "d").build()));
+
assertTrue(eval(builder.profileProperty("properties.lastVisit").inDateExpr("" +
lastVisit.getTime()).build()));
+
assertTrue(eval(builder.profileProperty("properties.lastVisit").notInDateExpr("now-"
+ (daysFromToday + 1) + "d").build()));
}
@Test
diff --git
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
index 4f2612b..a7df6c7 100644
---
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
+++
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
@@ -33,6 +33,8 @@ import org.joda.time.format.ISODateTimeFormat;
import java.util.*;
+import static
org.apache.unomi.plugins.baseplugin.conditions.PropertyConditionEvaluator.getDate;
+
public class PropertyConditionESQueryBuilder implements
ConditionESQueryBuilder {
DateTimeFormatter dateTimeFormatter;
@@ -144,10 +146,10 @@ public class PropertyConditionESQueryBuilder implements
ConditionESQueryBuilder
return boolQueryBuilder;
case "isDay":
checkRequiredValue(value, name, comparisonOperator, false);
- return getIsSameDayRange(value, name);
+ return getIsSameDayRange(getDate(value), name);
case "isNotDay":
checkRequiredValue(value, name, comparisonOperator, false);
- return
QueryBuilders.boolQuery().mustNot(getIsSameDayRange(value, name));
+ return
QueryBuilders.boolQuery().mustNot(getIsSameDayRange(getDate(value), name));
case "distance":
final String unitString = (String)
condition.getParameter("unit");
final Object centerObj = condition.getParameter("center");
diff --git
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java
index 064a460..7ad182e 100644
---
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java
+++
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java
@@ -42,6 +42,7 @@ import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* Evaluator for property comparison conditions
@@ -69,7 +70,7 @@ public class PropertyConditionEvaluator implements
ConditionEvaluator {
}
private int compare(Object actualValue, String expectedValue, Object
expectedValueDate, Object expectedValueInteger, Object expectedValueDateExpr,
Object expectedValueDouble) {
- if (expectedValue == null && expectedValueDate == null &&
expectedValueInteger == null && getDate(expectedValueDateExpr) == null) {
+ if (expectedValue == null && expectedValueDate == null &&
expectedValueInteger == null && getDate(expectedValueDateExpr) == null &&
expectedValueDouble == null) {
return actualValue == null ? 0 : 1;
} else if (actualValue == null) {
return -1;
@@ -88,9 +89,13 @@ public class PropertyConditionEvaluator implements
ConditionEvaluator {
}
}
- private boolean compareMultivalue(Object actualValue, Collection<?>
expectedValues, Collection<?> expectedValuesDate, Collection<?>
expectedValuesNumber, Collection<?> expectedValuesDateExpr, String op) {
+ private boolean compareValues(Object actualValue, Collection<?>
expectedValues, Collection<?> expectedValuesInteger, Collection<?>
expectedValuesDouble, Collection<?> expectedValuesDate, Collection<?>
expectedValuesDateExpr, String op) {
+ Collection<Object> expectedDateExpr = null;
+ if (expectedValuesDateExpr != null) {
+ expectedDateExpr =
expectedValuesDateExpr.stream().map(PropertyConditionEvaluator::getDate).collect(Collectors.toList());
+ }
@SuppressWarnings("unchecked")
- Collection<?> expected = ObjectUtils.firstNonNull(expectedValues,
expectedValuesDate, expectedValuesNumber);
+ Collection<?> expected = ObjectUtils.firstNonNull(expectedValues,
expectedValuesDate, expectedValuesInteger, expectedValuesDouble,
expectedDateExpr);
if (actualValue == null) {
return expected == null;
} else if (expected == null) {
@@ -202,11 +207,11 @@ public class PropertyConditionEvaluator implements
ConditionEvaluator {
}
protected boolean isMatch(String op, Object actualValue, String
expectedValue, Object expectedValueInteger, Object expectedValueDouble,
- Object expectedValueDate, Object
expectedValueDateExpr, Condition condition) {
+ Object expectedValueDate, Object
expectedValueDateExpr, Condition condition) {
if (op == null) {
return false;
} else if (actualValue == null) {
- return op.equals("missing")|| op.equals("notIn") ||
op.equals("notEquals") || op.equals("hasNoneOf");
+ return op.equals("missing") || op.equals("notIn") ||
op.equals("notEquals") || op.equals("hasNoneOf");
} else if (op.equals("exists")) {
if (actualValue instanceof List) {
return ((List) actualValue).size() > 0;
@@ -266,12 +271,15 @@ public class PropertyConditionEvaluator implements
ConditionEvaluator {
Collection<?> expectedValuesInteger = (Collection<?>)
condition.getParameter("propertyValuesInteger");
Collection<?> expectedValuesDate = (Collection<?>)
condition.getParameter("propertyValuesDate");
Collection<?> expectedValuesDateExpr = (Collection<?>)
condition.getParameter("propertyValuesDateExpr");
+ Collection<?> expectedValuesDouble = (Collection<?>)
condition.getParameter("propertyValuesDouble");
- return compareMultivalue(actualValue, expectedValues,
expectedValuesDate, expectedValuesInteger, expectedValuesDateExpr, op);
- } else if (op.equals("isDay") && expectedValueDate != null) {
- return
yearMonthDayDateFormat.format(getDate(actualValue)).equals(yearMonthDayDateFormat.format(getDate(expectedValueDate)));
- } else if (op.equals("isNotDay") && expectedValueDate != null) {
- return
!yearMonthDayDateFormat.format(getDate(actualValue)).equals(yearMonthDayDateFormat.format(getDate(expectedValueDate)));
+ return compareValues(actualValue, expectedValues,
expectedValuesInteger, expectedValuesDouble, expectedValuesDate,
expectedValuesDateExpr, op);
+ } else if (op.equals("isDay") && (expectedValueDate != null ||
expectedValueDateExpr != null)) {
+ Object expectedDate = expectedValueDate == null ?
expectedValueDateExpr : expectedValueDate;
+ return
yearMonthDayDateFormat.format(getDate(actualValue)).equals(yearMonthDayDateFormat.format(getDate(expectedDate)));
+ } else if (op.equals("isNotDay") && (expectedValueDate != null ||
expectedValueDateExpr != null)) {
+ Object expectedDate = expectedValueDate == null ?
expectedValueDateExpr : expectedValueDate;
+ return
!yearMonthDayDateFormat.format(getDate(actualValue)).equals(yearMonthDayDateFormat.format(getDate(expectedDate)));
} else if (op.equals("distance")) {
GeoPoint actualCenter = null;
if (actualValue instanceof GeoPoint) {
@@ -433,7 +441,7 @@ public class PropertyConditionEvaluator implements
ConditionEvaluator {
return accessor;
}
- private Date getDate(Object value) {
+ protected static Date getDate(Object value) {
if (value == null) {
return null;
}