You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2020/11/11 09:20:54 UTC

[unomi] 08/17: Add toDate and fromDate to pastEventCondition (#204)

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 <62...@users.noreply.github.com>
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) {