This is an automated email from the ASF dual-hosted git repository. shuber pushed a commit to branch unomi-1.5.x in repository https://gitbox.apache.org/repos/asf/unomi.git
commit bdbf7fb3b4362e3d6eb08984fb54ef0d828eddb3 Author: liatiusim <[email protected]> AuthorDate: Wed Oct 14 11:16:51 2020 +0300 Add toDate and fromDate to pastEventCondition (#204) (cherry picked from commit 2c0140bf79325f387c7e7a5f05fc2d4d9b0ab2ae) --- .../org/apache/unomi/itests/EventServiceIT.java | 77 ++++++++++++++++++++++ plugins/baseplugin/pom.xml | 6 ++ .../actions/SetEventOccurenceCountAction.java | 71 ++++++++++++++++---- .../PastEventConditionESQueryBuilder.java | 20 ++++++ .../conditions/PastEventConditionEvaluator.java | 19 ++++++ .../cxs/conditions/pastEventCondition.json | 10 +++ .../services/impl/segments/SegmentServiceImpl.java | 29 ++++++++ 7 files changed, 218 insertions(+), 14 deletions(-) diff --git a/itests/src/test/java/org/apache/unomi/itests/EventServiceIT.java b/itests/src/test/java/org/apache/unomi/itests/EventServiceIT.java index 5e38d19..ea0f83b 100644 --- a/itests/src/test/java/org/apache/unomi/itests/EventServiceIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/EventServiceIT.java @@ -20,10 +20,16 @@ import org.apache.unomi.api.services.EventService; import org.apache.unomi.api.services.ProfileService; import org.apache.unomi.api.Event; import org.apache.unomi.api.Profile; +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.api.query.Query; +import org.apache.unomi.api.PartialList; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.Assert; + + import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerSuite; @@ -31,6 +37,11 @@ import org.ops4j.pax.exam.util.Filter; import javax.inject.Inject; import java.util.Date; + +import java.text.SimpleDateFormat; +import java.text.ParseException; + + import org.junit.Assert; @@ -65,4 +76,70 @@ public class EventServiceIT extends BaseIT { Assert.assertTrue(exist); } + @Test + public void test_PastEventWithDateRange() throws InterruptedException, ParseException { + String eventId = "past-event-id" + System.currentTimeMillis(); + String profileId = "past-event-profile-id" + System.currentTimeMillis(); + String eventType = "past-event-with-date-range-type"; + Profile profile = new Profile(profileId); + Date timestamp = null; + timestamp = new SimpleDateFormat("yyyy-MM-dd").parse("2000-06-30"); + Event event = new Event(eventId, eventType, null, profile, null, null, null, timestamp); + + profileService.save(profile); + eventService.send(event); + refreshPersistence(); + Thread.sleep(2000); + + Condition eventTypeCondition = new Condition(definitionsService.getConditionType("eventTypeCondition")); + eventTypeCondition.setParameter("eventTypeId",eventType); + + Condition pastEventCondition = new Condition(definitionsService.getConditionType("pastEventCondition")); + pastEventCondition.setParameter("minimumEventCount", 1); + pastEventCondition.setParameter("fromDate","1999-01-15T07:00:00Z"); + pastEventCondition.setParameter("toDate","2001-01-15T07:00:00Z"); + + pastEventCondition.setParameter("eventCondition",eventTypeCondition); + + Query query = new Query(); + query.setCondition(pastEventCondition); + + PartialList<Profile> profiles = profileService.search(query, Profile.class); + Assert.assertEquals(1, profiles.getList().size()); + Assert.assertEquals(profiles.getList().get(0).getItemId(), profileId); + + } + + @Test + public void test_PastEventNotInRange_NoProfilesShouldReturn() throws InterruptedException, ParseException{ + String eventId = "past-event-id" + System.currentTimeMillis(); + String profileId = "past-event-profile-id" + System.currentTimeMillis(); + String eventType = "past-event-with-date-range-type"; + Profile profile = new Profile(profileId); + Date timestamp = null; + timestamp = new SimpleDateFormat("yyyy-MM-dd").parse("2000-06-30"); + Event event = new Event(eventId, eventType, null, profile, null, null, null, timestamp); + + profileService.save(profile); + eventService.send(event); + refreshPersistence(); + Thread.sleep(2000); + + Condition eventTypeCondition = new Condition(definitionsService.getConditionType("eventTypeCondition")); + eventTypeCondition.setParameter("eventTypeId",eventType); + + Condition pastEventCondition = new Condition(definitionsService.getConditionType("pastEventCondition")); + pastEventCondition.setParameter("minimumEventCount", 1); + pastEventCondition.setParameter("fromDate","2000-07-15T07:00:00Z"); + pastEventCondition.setParameter("toDate","2001-01-15T07:00:00Z"); + + pastEventCondition.setParameter("eventCondition",eventTypeCondition); + + Query query = new Query(); + query.setCondition(pastEventCondition); + + PartialList<Profile> profiles = profileService.search(query, Profile.class); + Assert.assertEquals(0, profiles.getList().size()); + } + } diff --git a/plugins/baseplugin/pom.xml b/plugins/baseplugin/pom.xml index 9ed2f67..5f084fd 100644 --- a/plugins/baseplugin/pom.xml +++ b/plugins/baseplugin/pom.xml @@ -37,6 +37,12 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.2.11</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> </dependency> diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java index d3e80b9..d74674f 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java @@ -26,7 +26,6 @@ import org.apache.unomi.api.services.EventService; import org.apache.unomi.persistence.spi.PersistenceService; import java.time.Duration; -import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; @@ -34,6 +33,8 @@ import java.util.Calendar; import java.util.LinkedHashMap; import java.util.Map; +import javax.xml.bind.DatatypeConverter; + public class SetEventOccurenceCountAction implements ActionExecutor { private DefinitionsService definitionsService; @@ -65,16 +66,32 @@ public class SetEventOccurenceCountAction implements ActionExecutor { c.setParameter("propertyValue", event.getProfileId()); conditions.add(c); - int numberOfDays = 0; - if (pastEventCondition.getParameter("numberOfDays") != null) { - numberOfDays = (Integer) pastEventCondition.getParameter("numberOfDays"); - - Condition timeCondition = new Condition(definitionsService.getConditionType("eventPropertyCondition")); - timeCondition.setParameter("propertyName", "timeStamp"); - timeCondition.setParameter("comparisonOperator", "greaterThan"); - timeCondition.setParameter("propertyValueDateExpr", "now-" + numberOfDays + "d"); + Integer numberOfDays = (Integer) pastEventCondition.getParameter("numberOfDays"); + String fromDate = (String) pastEventCondition.getParameter("fromDate"); + String toDate = (String) pastEventCondition.getParameter("toDate"); - conditions.add(timeCondition); + if (numberOfDays != null) { + Condition numberOfDaysCondition = new Condition(definitionsService.getConditionType("eventPropertyCondition")); + numberOfDaysCondition.setParameter("propertyName", "timeStamp"); + numberOfDaysCondition.setParameter("comparisonOperator", "greaterThan"); + numberOfDaysCondition.setParameter("propertyValueDateExpr", "now-" + numberOfDays + "d"); + conditions.add(numberOfDaysCondition); + } + if (fromDate != null) { + Condition startDateCondition = new Condition(); + startDateCondition.setConditionType(definitionsService.getConditionType("eventPropertyCondition")); + startDateCondition.setParameter("propertyName", "timeStamp"); + startDateCondition.setParameter("comparisonOperator", "greaterThanOrEqualTo"); + startDateCondition.setParameter("propertyValueDate", fromDate); + conditions.add(startDateCondition); + } + if (toDate != null) { + Condition endDateCondition = new Condition(); + endDateCondition.setConditionType(definitionsService.getConditionType("eventPropertyCondition")); + endDateCondition.setParameter("propertyName", "timeStamp"); + endDateCondition.setParameter("comparisonOperator", "lessThanOrEqualTo"); + endDateCondition.setParameter("propertyValueDate", toDate); + conditions.add(endDateCondition); } andCondition.setParameter("subConditions", conditions); @@ -87,11 +104,14 @@ public class SetEventOccurenceCountAction implements ActionExecutor { event.getProfile().getSystemProperties().put("pastEvents", pastEvents); } - //Only increase the counter by 1 if the current event is in the now-numberOfDays range - LocalDateTime now = LocalDateTime.now(ZoneId.of("UTC")); + Calendar fromDateCalendar = DatatypeConverter.parseDateTime(fromDate); + Calendar toDateCalendar = DatatypeConverter.parseDateTime(toDate); + LocalDateTime eventTime = LocalDateTime.ofInstant(event.getTimeStamp().toInstant(),ZoneId.of("UTC")); - Duration durationDiff = Duration.between(eventTime,now); - if (!durationDiff.isNegative() && durationDiff.toDays() <= numberOfDays) { + LocalDateTime fromDateTime = LocalDateTime.ofInstant(fromDateCalendar.toInstant(), ZoneId.of("UTC")); + LocalDateTime toDateTime = LocalDateTime.ofInstant(toDateCalendar.toInstant(), ZoneId.of("UTC")); + + if (inTimeRange(eventTime, numberOfDays, fromDateTime, toDateTime)) { count++; } @@ -99,4 +119,27 @@ public class SetEventOccurenceCountAction implements ActionExecutor { return EventService.PROFILE_UPDATED; } + + private boolean inTimeRange(LocalDateTime eventTime, Integer numberOfDays, LocalDateTime fromDate, LocalDateTime toDate) { + boolean inTimeRange = true; + + if (numberOfDays != null) { + LocalDateTime now = LocalDateTime.now(ZoneId.of("UTC")); + if (eventTime.isAfter(now)) { + inTimeRange = false; + } + long daysDiff = Duration.between(eventTime, now).toDays(); + if (daysDiff > numberOfDays) { + inTimeRange = false; + } + } + if (fromDate != null && fromDate.isAfter(eventTime)) { + inTimeRange = false; + } + if (toDate != null && toDate.isBefore(eventTime)) { + inTimeRange = false; + } + + return inTimeRange; + } } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java index a33f6fe..6afffb1 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java @@ -184,6 +184,9 @@ public class PastEventConditionESQueryBuilder implements ConditionESQueryBuilder l.add(ConditionContextHelper.getContextualCondition(eventCondition, context, scriptExecutor)); Integer numberOfDays = (Integer) condition.getParameter("numberOfDays"); + String fromDate = (String) condition.getParameter("fromDate"); + String toDate = (String) condition.getParameter("toDate"); + if (numberOfDays != null) { Condition numberOfDaysCondition = new Condition(); numberOfDaysCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); @@ -192,6 +195,23 @@ public class PastEventConditionESQueryBuilder implements ConditionESQueryBuilder numberOfDaysCondition.setParameter("propertyValueDateExpr", "now-" + numberOfDays + "d"); l.add(numberOfDaysCondition); } + if (fromDate != null) { + Condition startDateCondition = new Condition(); + startDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + startDateCondition.setParameter("propertyName", "timeStamp"); + startDateCondition.setParameter("comparisonOperator", "greaterThanOrEqualTo"); + startDateCondition.setParameter("propertyValueDate", fromDate); + l.add(startDateCondition); + } + if (toDate != null) { + Condition endDateCondition = new Condition(); + endDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + endDateCondition.setParameter("propertyName", "timeStamp"); + endDateCondition.setParameter("comparisonOperator", "lessThanOrEqualTo"); + endDateCondition.setParameter("propertyValueDate", toDate); + l.add(endDateCondition); + } + return andCondition; } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java index 0d4aaa6..5ca8e10 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java @@ -93,6 +93,9 @@ public class PastEventConditionEvaluator implements ConditionEvaluator { l.add(profileCondition); Integer numberOfDays = (Integer) condition.getParameter("numberOfDays"); + String fromDate = (String) condition.getParameter("fromDate"); + String toDate = (String) condition.getParameter("toDate"); + if (numberOfDays != null) { Condition numberOfDaysCondition = new Condition(); numberOfDaysCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); @@ -101,6 +104,22 @@ public class PastEventConditionEvaluator implements ConditionEvaluator { numberOfDaysCondition.setParameter("propertyValueDateExpr", "now-" + numberOfDays + "d"); l.add(numberOfDaysCondition); } + if (fromDate != null) { + Condition startDateCondition = new Condition(); + startDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + startDateCondition.setParameter("propertyName", "timeStamp"); + startDateCondition.setParameter("comparisonOperator", "greaterThanOrEqualTo"); + startDateCondition.setParameter("propertyValueDate", fromDate); + l.add(startDateCondition); + } + if (toDate != null) { + Condition endDateCondition = new Condition(); + endDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + endDateCondition.setParameter("propertyName", "timeStamp"); + endDateCondition.setParameter("comparisonOperator", "lessThanOrEqualTo"); + endDateCondition.setParameter("propertyValueDate", toDate); + l.add(endDateCondition); + } count = persistenceService.queryCount(andCondition, Event.ITEM_TYPE); } diff --git a/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/pastEventCondition.json b/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/pastEventCondition.json index 71a87f3..6740a73 100644 --- a/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/pastEventCondition.json +++ b/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/pastEventCondition.json @@ -21,6 +21,16 @@ "multivalued": false }, { + "id": "fromDate", + "type": "date", + "multivalued": false + }, + { + "id": "toDate", + "type": "date", + "multivalued": false + }, + { "id": "minimumEventCount", "type": "integer", "multivalued": false diff --git a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java index 9c362ed..03400f1 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java @@ -770,6 +770,9 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentSe l.add(eventCondition); Integer numberOfDays = (Integer) parentCondition.getParameter("numberOfDays"); + String fromDate = (String) parentCondition.getParameter("fromDate"); + String toDate = (String) parentCondition.getParameter("toDate"); + if (numberOfDays != null) { Condition numberOfDaysCondition = new Condition(); numberOfDaysCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); @@ -778,6 +781,22 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentSe numberOfDaysCondition.setParameter("propertyValue", "now-" + numberOfDays + "d"); l.add(numberOfDaysCondition); } + if (fromDate != null) { + Condition startDateCondition = new Condition(); + startDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + startDateCondition.setParameter("propertyName", "timeStamp"); + startDateCondition.setParameter("comparisonOperator", "greaterThanOrEqualTo"); + startDateCondition.setParameter("propertyValueDate", fromDate); + l.add(startDateCondition); + } + if (toDate != null) { + Condition endDateCondition = new Condition(); + endDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + endDateCondition.setParameter("propertyName", "timeStamp"); + endDateCondition.setParameter("comparisonOperator", "lessThanOrEqualTo"); + endDateCondition.setParameter("propertyValueDate", toDate); + l.add(endDateCondition); + } String propertyKey = (String) parentCondition.getParameter("generatedPropertyKey"); Map<String, Double> m = persistenceService.getSingleValuesMetrics(andCondition, new String[]{"card"}, "profileId.keyword", Event.ITEM_TYPE); @@ -811,6 +830,16 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentSe Map<String, Object> m = new HashMap<>(); m.put("condition", condition); m.put("numberOfDays", parentCondition.getParameter("numberOfDays")); + // Put fromDate and toDate only if exist - for backward compatibility + Object fromDate = parentCondition.getParameter("fromDate"); + if (fromDate != null) { + m.put("fromDate", parentCondition.getParameter("fromDate")); + } + Object toDate = parentCondition.getParameter("toDate"); + if (toDate != null) { + m.put("fromDate", parentCondition.getParameter("toDate")); + } + String key = CustomObjectMapper.getObjectMapper().writeValueAsString(m); return "eventTriggered" + getMD5(key); } catch (JsonProcessingException e) {
