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

jsinovassinnaik pushed a commit to branch UNOMI-817
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit ac7a3e12281f5a823ff75fefc54f3379599daf03
Author: jsinovassin <jsinovassinn...@jahia.com>
AuthorDate: Mon Apr 29 15:36:36 2024 +0200

    feedback
---
 .../apache/unomi/api/utils/ConditionHelper.java    | 113 +++++++++++++++++++++
 .../resources/OSGI-INF/blueprint/blueprint.xml     |   7 +-
 .../actions/SetEventOccurenceCountAction.java      |  33 ++++--
 .../PastEventConditionESQueryBuilder.java          | 101 ++++++------------
 .../conditions/PastEventConditionEvaluator.java    |  17 ++--
 .../resources/OSGI-INF/blueprint/blueprint.xml     |   2 +-
 .../services/impl/segments/SegmentServiceImpl.java |  80 ++++++---------
 .../2.5.0/update_pastEvents_profile.painless       |   1 -
 8 files changed, 211 insertions(+), 143 deletions(-)

diff --git a/api/src/main/java/org/apache/unomi/api/utils/ConditionHelper.java 
b/api/src/main/java/org/apache/unomi/api/utils/ConditionHelper.java
new file mode 100644
index 000000000..1a170987d
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/utils/ConditionHelper.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.unomi.api.utils;
+
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.services.DefinitionsService;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Utility class for creating various types of {@link Condition} objects.
+ * This class provides methods to easily construct conditions used for 
querying data based on specific criteria.
+ */
+public class ConditionHelper {
+
+    private DefinitionsService definitionsService;
+
+    /**
+     * Constructs a new ConditionHelper with a specified DefinitionsService.
+     *
+     * @param definitionsService the DefinitionsService to use for obtaining 
condition types.
+     */
+    public ConditionHelper(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+
+    public void setDefinitionsService(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+
+
+    /**
+     * Creates a profile property condition.
+     * This condition is used to evaluate specific properties of profiles.
+     *
+     * @param propertyName the name of the property to check.
+     * @param operator     the comparison operator to apply.
+     * @param value        the value to compare against the profile property.
+     * @param valueKey     the key of the parameter where to store the value. 
Can be one of
+     *                     [propertyValue, propertyValueInteger, 
propertyValueDouble, propertyValueDate, propertyValueDateExpr, propertyValues, 
propertyValuesInteger, propertyValuesDouble, propertyValuesDate, 
propertyValuesDateExpr]
+     * @return a new Condition to evaluate the specified profile property.
+     */
+    public Condition createProfilePropertyCondition(String propertyName, 
String operator, Object value, String valueKey) {
+        Condition condition = new 
Condition(definitionsService.getConditionType("profilePropertyCondition"));
+        condition.setParameter("propertyName", propertyName);
+        condition.setParameter("comparisonOperator", operator);
+        condition.setParameter(valueKey, value);
+        return condition;
+    }
+
+    /**
+     * Creates a boolean condition.
+     * This condition can combine multiple sub-conditions using a logical 
operator (e.g., AND, OR).
+     *
+     * @param operator      the logical operator to use for combining 
sub-conditions.
+     * @param subConditions the list of sub-conditions to combine.
+     * @return a new Condition configured with the specified logical operator 
and sub-conditions.
+     */
+    public Condition createBooleanCondition(String operator, List<Condition> 
subConditions) {
+        Condition condition = new 
Condition(definitionsService.getConditionType("booleanCondition"));
+        condition.setParameter("operator", operator);
+        condition.setParameter("subConditions", subConditions);
+        return condition;
+    }
+
+    /**
+     * Creates a nested condition.
+     * This condition applies another condition to a nested path within a 
profile or other entity.
+     *
+     * @param path         the path within the entity to which the condition 
should apply.
+     * @param subCondition the condition to apply at the specified path.
+     * @return a new Condition configured to evaluate the specified path with 
the provided sub-condition.
+     */
+    public Condition createNestedCondition(String path, Condition 
subCondition) {
+        Condition nestedCondition = new 
Condition(definitionsService.getConditionType("nestedCondition"));
+        nestedCondition.setParameter("path", path);
+        nestedCondition.setParameter("subCondition", subCondition);
+        return nestedCondition;
+    }
+
+
+    /**
+     * Creates a condition to filter profiles based on a set of IDs.
+     * This method constructs a condition that specifies which profiles to 
include or exclude based on their IDs.
+     *
+     * @param ids         a {@link Set} of String representing the profile IDs 
to match.
+     * @param shouldMatch a boolean indicating whether the condition should 
match the profiles with the specified IDs or not.
+     * @return a new Condition configured to filter profiles based on the 
specified IDs and matching criteria.
+     */
+    public Condition createProfileIdsCondition(Set<String> ids, boolean 
shouldMatch) {
+        Condition idsCondition = new Condition();
+        
idsCondition.setConditionType(definitionsService.getConditionType("idsCondition"));
+        idsCondition.setParameter("ids", ids);
+        idsCondition.setParameter("match", shouldMatch);
+        return idsCondition;
+    }
+
+}
diff --git 
a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
 
b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 32efdd022..d14235171 100644
--- 
a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ 
b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -20,12 +20,7 @@
            
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0";
            xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0";
            xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
-
-
-
-
-
-  http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 
http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd";>
+           http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 
http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd";>
 
     <cm:property-placeholder 
persistent-id="org.apache.unomi.persistence.elasticsearch"
                              update-strategy="reload" 
placeholder-prefix="${es.">
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 e70922d04..aa953853d 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
@@ -129,17 +129,32 @@ public class SetEventOccurenceCountAction implements 
ActionExecutor {
     }
 
     private boolean updatePastEvents(Event event, String generatedPropertyKey, 
long count) {
-        ArrayList<Map<String, Object>> pastEvents = new ArrayList<>();
-        ArrayList<Map<String, Object>> existingPastEvents = 
(ArrayList<Map<String, Object>>) 
event.getProfile().getSystemProperties().get("pastEvents");
-        if (existingPastEvents != null) {
-            pastEvents.addAll(existingPastEvents.stream().filter(pastEvent -> 
!pastEvent.get("key").equals(generatedPropertyKey)).collect(Collectors.toList()));
+        List<Map<String, Object>> existingPastEvents = (List<Map<String, 
Object>>) event.getProfile().getSystemProperties().get("pastEvents");
+        if (existingPastEvents == null) {
+            existingPastEvents = new ArrayList<>();
+            event.getProfile().getSystemProperties().put("pastEvents", 
existingPastEvents);
         }
 
-        Map<String, Object> pastEvent = new HashMap<>();
-        pastEvent.put("key", generatedPropertyKey);
-        pastEvent.put("count", count);
-        pastEvents.add(pastEvent);
-        return PropertyHelper.setProperty(event.getProfile(), 
"systemProperties.pastEvents", pastEvents, "alwaysSet");
+        for (Map<String, Object> pastEvent : existingPastEvents) {
+            if (generatedPropertyKey.equals(pastEvent.get("key"))) {
+                long existingCount = (long) pastEvent.get("count");
+                if (count != existingCount) {
+                    pastEvent.put("count", count);
+                    return true;
+                }
+                return false;
+            }
+        }
+
+        return addNewPastEvent(existingPastEvents, generatedPropertyKey, 
count);
+    }
+
+    private boolean addNewPastEvent(List<Map<String, Object>> 
existingPastEvents, String key, long count) {
+        Map<String, Object> newPastEvent = new HashMap<>();
+        newPastEvent.put("key", key);
+        newPastEvent.put("count", count);
+        existingPastEvents.add(newPastEvent);
+        return true;  // New event added
     }
 
     private boolean inTimeRange(LocalDateTime eventTime, Integer numberOfDays, 
LocalDateTime fromDate, LocalDateTime toDate) {
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 772be5f71..e04ace16e 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
@@ -23,6 +23,7 @@ import org.apache.unomi.api.conditions.Condition;
 import org.apache.unomi.api.conditions.ConditionType;
 import org.apache.unomi.api.services.DefinitionsService;
 import org.apache.unomi.api.services.SegmentService;
+import org.apache.unomi.api.utils.ConditionHelper;
 import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper;
 import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
 import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
@@ -45,6 +46,8 @@ public class PastEventConditionESQueryBuilder implements 
ConditionESQueryBuilder
     private int aggregateQueryBucketSize = 5000;
     private boolean pastEventsDisablePartitions = false;
 
+    private ConditionHelper conditionHelper;
+
     public void setDefinitionsService(DefinitionsService definitionsService) {
         this.definitionsService = definitionsService;
     }
@@ -73,6 +76,9 @@ public class PastEventConditionESQueryBuilder implements 
ConditionESQueryBuilder
         this.segmentService = segmentService;
     }
 
+    public void init(){
+        conditionHelper = new ConditionHelper(definitionsService);
+    }
     @Override
     public QueryBuilder buildQuery(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
         boolean eventsOccurred = getStrategyFromOperator((String) 
condition.getParameter("operator"));
@@ -88,7 +94,7 @@ public class PastEventConditionESQueryBuilder implements 
ConditionESQueryBuilder
             // TODO see for deprecation, this should not happen anymore each 
past event condition should have a generatedPropertyKey
             Condition eventCondition = getEventCondition(condition, context, 
null, definitionsService, scriptExecutor);
             Set<String> ids = getProfileIdsMatchingEventCount(eventCondition, 
minimumEventCount, maximumEventCount);
-            return dispatcher.buildFilter(getProfileIdsCondition(ids, 
eventsOccurred), context);
+            return 
dispatcher.buildFilter(conditionHelper.createProfileIdsCondition(ids, 
eventsOccurred), context);
         }
     }
 
@@ -111,7 +117,7 @@ public class PastEventConditionESQueryBuilder implements 
ConditionESQueryBuilder
             }
 
             Set<String> profileIds = 
getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, 
maximumEventCount);
-            return eventsOccurred ? profileIds.size() : 
persistenceService.queryCount(getProfileIdsCondition(profileIds, false), 
Profile.ITEM_TYPE);
+            return eventsOccurred ? profileIds.size() : 
persistenceService.queryCount(conditionHelper.createProfileIdsCondition(profileIds,
 false), Profile.ITEM_TYPE);
         }
     }
 
@@ -122,84 +128,43 @@ public class PastEventConditionESQueryBuilder implements 
ConditionESQueryBuilder
         return operator == null || operator.equals("eventsOccurred");
     }
 
-    private Condition getProfileIdsCondition(Set<String> ids, boolean 
shouldMatch) {
-        Condition idsCondition = new Condition();
-        
idsCondition.setConditionType(definitionsService.getConditionType("idsCondition"));
-        idsCondition.setParameter("ids", ids);
-        idsCondition.setParameter("match", shouldMatch);
-        return idsCondition;
-    }
-
     private Condition getProfileConditionForCounter(String 
generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount, 
boolean eventsOccurred) {
-        Condition countCondition = new Condition();
-
-        
countCondition.setConditionType(definitionsService.getConditionType("nestedCondition"));
-        countCondition.setParameter("path", "systemProperties.pastEvents");
-
-        Condition subConditionCount = new 
Condition(definitionsService.getConditionType("profilePropertyCondition"));
-
-        Condition subConditionKey = 
getKeyEqualsCondition(generatedPropertyKey);
-
-        ConditionType profilePropertyConditionType = 
definitionsService.getConditionType("profilePropertyCondition");
         if (eventsOccurred) {
-            subConditionCount.setParameter("propertyName", 
"systemProperties.pastEvents.count");
-            subConditionCount.setParameter("comparisonOperator", "between");
-            subConditionCount.setParameter("propertyValuesInteger", 
Arrays.asList(minimumEventCount, maximumEventCount));
-
-            Condition booleanCondition = new 
Condition(definitionsService.getConditionType("booleanCondition"));
-            booleanCondition.setParameter("operator", "and");
-            booleanCondition.setParameter("subConditions", 
Arrays.asList(subConditionCount, subConditionKey));
-
-            countCondition.setParameter("subCondition", booleanCondition);
-            return countCondition;
-
+            return createEventOccurredCondition(generatedPropertyKey, 
minimumEventCount, maximumEventCount);
         } else {
+            return createEventNotOccurredCondition(generatedPropertyKey);
+        }
+    }
 
-            // 1. Key not present in profile
-            Condition keyNestedCondition = new Condition();
-            
keyNestedCondition.setConditionType(definitionsService.getConditionType("nestedCondition"));
-            keyNestedCondition.setParameter("path", 
"systemProperties.pastEvents");
-
-            Condition keyEquals = new Condition(profilePropertyConditionType);
-            keyEquals.setParameter("propertyName", 
"systemProperties.pastEvents.key");
-            keyEquals.setParameter("comparisonOperator", "equals");
-            keyEquals.setParameter("propertyValue", generatedPropertyKey);
-
-            keyNestedCondition.setParameter("subCondition", keyEquals);
+    private Condition createEventOccurredCondition(String 
generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount) {
+        Condition subConditionCount = 
conditionHelper.createProfilePropertyCondition("systemProperties.pastEvents.count",
 "between", Arrays.asList(minimumEventCount, maximumEventCount), 
"propertyValuesInteger");
+        Condition subConditionKey = 
createKeyEqualsCondition(generatedPropertyKey);
 
-            Condition mustNotExist = new 
Condition(definitionsService.getConditionType("notCondition"));
-            mustNotExist.setParameter("subCondition", keyNestedCondition);
+        Condition booleanCondition = 
conditionHelper.createBooleanCondition("and", Arrays.asList(subConditionCount, 
subConditionKey));
+        return 
conditionHelper.createNestedCondition("systemProperties.pastEvents", 
booleanCondition);
+    }
 
-            // 2. Key present in profile but value equals to 0
-            Condition counterZero = new 
Condition(profilePropertyConditionType);
-            counterZero.setParameter("propertyName", 
"systemProperties.pastEvents.count");
-            counterZero.setParameter("comparisonOperator", "equals");
-            counterZero.setParameter("propertyValueInteger", 0);
+    private Condition createEventNotOccurredCondition(String 
generatedPropertyKey) {
+        Condition pastEventsNotExist = 
createPastEventMustNotExistCondition(generatedPropertyKey);
+        Condition counterZero = 
conditionHelper.createProfilePropertyCondition("systemProperties.pastEvents.count",
 "equals", 0, "propertyValueInteger");
+        Condition keyExistsAndCounterZero = 
conditionHelper.createBooleanCondition("and", 
Arrays.asList(createKeyEqualsCondition(generatedPropertyKey), counterZero));
+        Condition nestedKeyExistsAndCounterZero = 
conditionHelper.createNestedCondition("systemProperties.pastEvents", 
keyExistsAndCounterZero);
 
-            Condition keyExistsAndCounterZero = new 
Condition(definitionsService.getConditionType("booleanCondition"));
-            keyExistsAndCounterZero.setParameter("operator", "and");
-            keyExistsAndCounterZero.setParameter("subConditions", 
Arrays.asList(subConditionKey, counterZero));
+        return conditionHelper.createBooleanCondition("or", 
Arrays.asList(pastEventsNotExist, nestedKeyExistsAndCounterZero));
+    }
 
-            Condition nestedKeyExistsAndCounterZero = new Condition();
-            
nestedKeyExistsAndCounterZero.setConditionType(definitionsService.getConditionType("nestedCondition"));
-            nestedKeyExistsAndCounterZero.setParameter("path", 
"systemProperties.pastEvents");
-            nestedKeyExistsAndCounterZero.setParameter("subCondition", 
keyExistsAndCounterZero);
+    private Condition createPastEventMustNotExistCondition(String 
generatedPropertyKey) {
+        Condition keyEquals = createKeyEqualsCondition(generatedPropertyKey);
 
-            Condition counterCondition = new Condition();
-            
counterCondition.setConditionType(definitionsService.getConditionType("booleanCondition"));
-            counterCondition.setParameter("operator", "or");
-            counterCondition.setParameter("subConditions", 
Arrays.asList(mustNotExist, nestedKeyExistsAndCounterZero));
+        Condition keyNestedCondition = 
conditionHelper.createNestedCondition("systemProperties.pastEvents", keyEquals);
 
-            return counterCondition;
-        }
+        Condition mustNotExist = new 
Condition(definitionsService.getConditionType("notCondition"));
+        mustNotExist.setParameter("subCondition", keyNestedCondition);
+        return mustNotExist;
     }
 
-    private Condition getKeyEqualsCondition(String generatedPropertyKey) {
-        Condition subConditionKey = new 
Condition(definitionsService.getConditionType("profilePropertyCondition"));
-        subConditionKey.setParameter("propertyName", 
"systemProperties.pastEvents.key");
-        subConditionKey.setParameter("comparisonOperator", "equals");
-        subConditionKey.setParameter("propertyValue", generatedPropertyKey);
-        return subConditionKey;
+    private Condition createKeyEqualsCondition(String generatedPropertyKey) {
+        return 
conditionHelper.createProfilePropertyCondition("systemProperties.pastEvents.key",
 "equals", generatedPropertyKey, "propertyValue");
     }
 
     private Set<String> getProfileIdsMatchingEventCount(Condition 
eventCondition, int minimumEventCount, int maximumEventCount) {
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 58d912b42..f14f768f6 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
@@ -57,15 +57,14 @@ public class PastEventConditionEvaluator implements 
ConditionEvaluator {
         if (parameters.containsKey("generatedPropertyKey")) {
             String key = (String) parameters.get("generatedPropertyKey");
             Profile profile = (Profile) item;
-            Object rawPastEvents =  
profile.getSystemProperties().get("pastEvents");
-            if (rawPastEvents != null) {
-                List<Map<String, Object>> pastEvents = (ArrayList<Map<String, 
Object>>) rawPastEvents;
-                    Number l = (Number) pastEvents
-                            .stream()
-                            .filter(pastEvent -> 
pastEvent.get("key").equals(key))
-                            .findFirst()
-                            .map(pastEvent -> 
pastEvent.get("count")).orElse(0L);
-                    count = l.longValue();
+            List<Map<String, Object>> pastEvents =  (ArrayList<Map<String, 
Object>>) profile.getSystemProperties().get("pastEvents");
+            if (pastEvents != null) {
+                Number l = (Number) pastEvents
+                        .stream()
+                        .filter(pastEvent -> pastEvent.get("key").equals(key))
+                        .findFirst()
+                        .map(pastEvent -> pastEvent.get("count")).orElse(0L);
+                count = l.longValue();
             } else {
                 count = 0;
             }
diff --git 
a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml 
b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 9f7dc8c92..2b5f63fc4 100644
--- a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -113,7 +113,7 @@
         <service-properties>
             <entry key="queryBuilderId" 
value="pastEventConditionESQueryBuilder"/>
         </service-properties>
-        <bean 
class="org.apache.unomi.plugins.baseplugin.conditions.PastEventConditionESQueryBuilder">
+        <bean 
class="org.apache.unomi.plugins.baseplugin.conditions.PastEventConditionESQueryBuilder"
 init-method="init">
             <property name="definitionsService" ref="definitionsService"/>
             <property name="persistenceService" ref="persistenceService"/>
             <property name="segmentService" ref="segmentService"/>
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 04acfeee5..81f656bb4 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
@@ -20,11 +20,7 @@ package org.apache.unomi.services.impl.segments;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import net.jodah.failsafe.Failsafe;
 import net.jodah.failsafe.RetryPolicy;
-import org.apache.unomi.api.Event;
-import org.apache.unomi.api.Item;
-import org.apache.unomi.api.Metadata;
-import org.apache.unomi.api.PartialList;
-import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.*;
 import org.apache.unomi.api.actions.Action;
 import org.apache.unomi.api.conditions.Condition;
 import org.apache.unomi.api.conditions.ConditionType;
@@ -35,6 +31,7 @@ import org.apache.unomi.api.services.EventService;
 import org.apache.unomi.api.services.RulesService;
 import org.apache.unomi.api.services.SchedulerService;
 import org.apache.unomi.api.services.SegmentService;
+import org.apache.unomi.api.utils.ConditionHelper;
 import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.apache.unomi.persistence.spi.aggregate.TermsAggregate;
 import org.apache.unomi.services.impl.AbstractServiceImpl;
@@ -86,6 +83,9 @@ public class SegmentServiceImpl extends AbstractServiceImpl 
implements SegmentSe
     private boolean pastEventsDisablePartitions = false;
     private int dailyDateExprEvaluationHourUtc = 5;
 
+    private ConditionHelper conditionHelper;
+
+
     public SegmentServiceImpl() {
         logger.info("Initializing segment service...");
     }
@@ -158,6 +158,7 @@ public class SegmentServiceImpl extends AbstractServiceImpl 
implements SegmentSe
         }
         bundleContext.addBundleListener(this);
         initializeTimer();
+        conditionHelper = new ConditionHelper(definitionsService);
         logger.info("Segment service initialized.");
     }
 
@@ -877,40 +878,24 @@ public class SegmentServiceImpl extends 
AbstractServiceImpl implements SegmentSe
      * Return the list of profile ids, for profiles that already have an event 
count matching the generated property key
      *
      * @param generatedPropertyKey the generated property key of the generated 
rule for the given past event condition.
-     * @return the list of profile ids.
+     * @return the set of profile ids.
      */
     private Set<String> getExistingProfilesWithPastEventOccurrenceCount(String 
generatedPropertyKey) {
-        Condition countExistsCondition = new Condition();
-
-        
countExistsCondition.setConditionType(definitionsService.getConditionType("nestedCondition"));
-        countExistsCondition.setParameter("path", 
"systemProperties.pastEvents");
-
-        Condition subConditionCount = new 
Condition(definitionsService.getConditionType("profilePropertyCondition"));
-        subConditionCount.setParameter("propertyName", 
"systemProperties.pastEvents.count");
-        subConditionCount.setParameter("comparisonOperator", "greaterThan");
-        subConditionCount.setParameter("propertyValueInteger", 0);
-
-        Condition subConditionKey = new 
Condition(definitionsService.getConditionType("profilePropertyCondition"));
-        subConditionKey.setParameter("propertyName", 
"systemProperties.pastEvents.key");
-        subConditionKey.setParameter("comparisonOperator", "equals");
-        subConditionKey.setParameter("propertyValue", generatedPropertyKey);
-
-        Condition booleanCondition = new 
Condition(definitionsService.getConditionType("booleanCondition"));
-        booleanCondition.setParameter("operator", "and");
-        booleanCondition.setParameter("subConditions", 
Arrays.asList(subConditionCount, subConditionKey));
-
-        countExistsCondition.setParameter("subCondition", booleanCondition);
+        Condition subConditionCount = 
conditionHelper.createProfilePropertyCondition("systemProperties.pastEvents.count",
 "greaterThan", 0, "propertyValueInteger");
+        Condition subConditionKey = 
conditionHelper.createProfilePropertyCondition("systemProperties.pastEvents.key",
 "equals", generatedPropertyKey, "propertyValue");
+        Condition booleanCondition = 
conditionHelper.createBooleanCondition("and", Arrays.asList(subConditionCount, 
subConditionKey));
+        Condition condition = 
conditionHelper.createNestedCondition("systemProperties.pastEvents", 
booleanCondition);
 
         Set<String> profileIds = new HashSet<>();
         if (pastEventsDisablePartitions) {
-            
profileIds.addAll(persistenceService.aggregateWithOptimizedQuery(countExistsCondition,
 new TermsAggregate("itemId"),
+            
profileIds.addAll(persistenceService.aggregateWithOptimizedQuery(condition, new 
TermsAggregate("itemId"),
                     Profile.ITEM_TYPE, maximumIdsQueryCount).keySet());
         } else {
-            Map<String, Double> m = 
persistenceService.getSingleValuesMetrics(countExistsCondition, new 
String[]{"card"}, "itemId.keyword", Profile.ITEM_TYPE);
+            Map<String, Double> m = 
persistenceService.getSingleValuesMetrics(condition, new String[]{"card"}, 
"itemId.keyword", Profile.ITEM_TYPE);
             long card = m.get("_card").longValue();
             int numParts = (int) (card / aggregateQueryBucketSize) + 2;
             for (int i = 0; i < numParts; i++) {
-                
profileIds.addAll(persistenceService.aggregateWithOptimizedQuery(countExistsCondition,
 new TermsAggregate("itemId", i, numParts),
+                
profileIds.addAll(persistenceService.aggregateWithOptimizedQuery(condition, new 
TermsAggregate("itemId", i, numParts),
                         Profile.ITEM_TYPE).keySet());
             }
         }
@@ -1001,38 +986,35 @@ public class SegmentServiceImpl extends 
AbstractServiceImpl implements SegmentSe
      *
      * @param eventCountByProfile the events count per profileId map
      * @param propertyKey         the generate property key for this past 
event condition, to keep track of the count in the profile
-     * @return the list of profiles for witch the count of event occurrences 
have been updated.
+     * @return the set of profiles for witch the count of event occurrences 
have been updated.
      */
     private Set<String> updatePastEventOccurrencesOnProfiles(Map<String, Long> 
eventCountByProfile, String propertyKey) {
         Set<String> profilesUpdated = new HashSet<>();
-        Map<Item, Map> batch = new HashMap<>();
+        Map<String, Map[]> batch = new HashMap<>();
         Iterator<Map.Entry<String, Long>> entryIterator = 
eventCountByProfile.entrySet().iterator();
+
         while (entryIterator.hasNext()) {
             Map.Entry<String, Long> entry = entryIterator.next();
             String profileId = entry.getKey();
             if (!profileId.startsWith("_")) {
-                Profile storedProfile = persistenceService.load(profileId, 
Profile.class);
-                if (storedProfile != null) {
-                    List<Map<String, Object>> pastEvents = new ArrayList<>();
-                    Map<String, Object> systemProperties = 
storedProfile.getSystemProperties() != null ? 
storedProfile.getSystemProperties() : new HashMap<>();
-                    if (systemProperties.containsKey("pastEvents")) {
-                        pastEvents = (ArrayList<Map<String, Object>>) 
storedProfile.getSystemProperties().get("pastEvents");
-                        pastEvents.removeIf(map -> 
map.get("key").equals(propertyKey));
-                    }
-                    pastEvents.add(Map.of("key", propertyKey, "count", 
entry.getValue()));
-                    systemProperties.put("pastEvents", pastEvents);
-                    systemProperties.put("lastUpdated", new Date());
-
-                    Profile profile = new Profile();
-                    profile.setItemId(profileId);
-                    batch.put(profile, 
Collections.singletonMap("systemProperties", systemProperties));
-                    profilesUpdated.add(profileId);
-                }
+                Map<String, Object> scriptParams = new HashMap<>();
+                scriptParams.put("pastEventKey", propertyKey);
+                scriptParams.put("valueToAdd", entry.getValue());
+                Map<String, Object>[] params = new Map[]{scriptParams};
+                batch.put(profileId, params);
+                profilesUpdated.add(profileId);
             }
 
+
+
+
             if (batch.size() == segmentUpdateBatchSize || 
(!entryIterator.hasNext() && !batch.isEmpty())) {
                 try {
-                    persistenceService.update(batch, Profile.class);
+                    batch.forEach((id, params) -> {
+                        Condition profileIdCondition = 
conditionHelper.createProfilePropertyCondition("itemId", "equals", id, 
"propertyValue");
+                        Condition[] conditions = new 
Condition[]{profileIdCondition};
+                        
persistenceService.updateWithQueryAndStoredScript(Profile.class, new 
String[]{"updatePastEventOccurences"}, params, conditions);
+                    });
                 } catch (Exception e) {
                     logger.error("Error updating {} profiles for past event 
system properties", batch.size(), e);
                 } finally {
diff --git 
a/tools/shell-commands/src/main/resources/requestBody/2.5.0/update_pastEvents_profile.painless
 
b/tools/shell-commands/src/main/resources/requestBody/2.5.0/update_pastEvents_profile.painless
index e6981f033..9c6768084 100644
--- 
a/tools/shell-commands/src/main/resources/requestBody/2.5.0/update_pastEvents_profile.painless
+++ 
b/tools/shell-commands/src/main/resources/requestBody/2.5.0/update_pastEvents_profile.painless
@@ -16,7 +16,6 @@
  */
 
 if (ctx._source.systemProperties != null && 
ctx._source.systemProperties.pastEvents != null && 
ctx._source.systemProperties.pastEvents instanceof Map) {
-    Map updatedPastEvents = new HashMap();
     List listOfPastEvent = new ArrayList();
     for (pastEventKey in ctx._source.systemProperties.pastEvents.keySet()) {
         Map pastEvent = new HashMap();

Reply via email to