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 cc97d17 UNOMI-518 : allow to use custom parameters in rules with
tracked cond… (#355)
cc97d17 is described below
commit cc97d17948507c10b6ac8ff0b86a818faec936e0
Author: David Griffon <[email protected]>
AuthorDate: Thu Oct 21 18:47:38 2021 +0200
UNOMI-518 : allow to use custom parameters in rules with tracked cond…
(#355)
* UNOMI-518 : allow to use custom parameters in rules with tracked
conditions
* UNOMI-518 : fix test + clean up
---
.../test/java/org/apache/unomi/itests/BaseIT.java | 2 +
.../org/apache/unomi/itests/RuleServiceIT.java | 48 ++++++++++++++++
.../test/resources/testClickEventCondition.json | 58 +++++++++++++++++++
.../services/impl/rules/RulesServiceImpl.java | 65 +++++++++++++++-------
4 files changed, 153 insertions(+), 20 deletions(-)
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index 9f8a2d9..81d28da 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -158,6 +158,8 @@ public abstract class BaseIT {
"src/test/resources/testCopyPropertiesWithoutSystemTags.json")),
replaceConfigurationFile("data/tmp/testLoginEventCondition.json", new File(
"src/test/resources/testLoginEventCondition.json")),
+
replaceConfigurationFile("data/tmp/testClickEventCondition.json", new File(
+ "src/test/resources/testClickEventCondition.json")),
replaceConfigurationFile("data/tmp/testRuleGroovyAction.json",
new File(
"src/test/resources/testRuleGroovyAction.json")),
replaceConfigurationFile("data/tmp/groovy/UpdateAddressAction.groovy", new File(
diff --git a/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
b/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
index 7a4488b..b8519f8 100644
--- a/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
@@ -17,9 +17,13 @@
package org.apache.unomi.itests;
import org.apache.unomi.api.*;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.conditions.ConditionType;
import org.apache.unomi.api.rules.Rule;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.RulesService;
+import org.apache.unomi.persistence.spi.CustomObjectMapper;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,7 +36,9 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
+import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.util.*;
import static org.junit.Assert.*;
@@ -176,6 +182,48 @@ public class RuleServiceIT extends BaseIT {
return new Event(UUID.randomUUID().toString(), "view", session,
profile, TEST_SCOPE, sourceItem, targetItem, new Date());
}
+ @Test
+ public void testGetTrackedConditions() throws InterruptedException,
IOException {
+ // Add custom condition with parameter
+ try {
+ ConditionType conditionType =
CustomObjectMapper.getObjectMapper().readValue(
+ new
File("data/tmp/testClickEventCondition.json").toURI().toURL(),
ConditionType.class);
+ definitionsService.setConditionType(conditionType);
+ refreshPersistence();
+ rulesService.refreshRules();
+ // Test tracked parameter
+ // Add rule that has a trackParameter condition that matches
+ ConditionBuilder builder = new
ConditionBuilder(definitionsService);
+ Rule trackParameterRule = new Rule(new Metadata(TEST_SCOPE,
"tracked-parameter-rule", "Tracked parameter rule", "A rule with tracked
parameter"));
+ Condition trackedCondition =
builder.condition("clickEventCondition").build();
+
trackedCondition.setParameter("tracked_properties_pageInfo_pagePath",
"/test-page.html");
+
trackedCondition.getConditionType().getMetadata().getSystemTags().add("trackedCondition");
+ trackParameterRule.setCondition(trackedCondition);
+ rulesService.setRule(trackParameterRule);
+ // Add rule that has a trackParameter condition that does not match
+ Rule unTrackParameterRule = new Rule(new Metadata(TEST_SCOPE,
"not-tracked-parameter-rule", "Not Tracked parameter rule", "A rule that has a
parameter not tracked"));
+ Condition unTrackedCondition =
builder.condition("clickEventCondition").build();
+
unTrackedCondition.setParameter("tracked_properties_pageInfo_pagePath",
"/test-page-that-does-not-exist.html");
+
unTrackedCondition.getConditionType().getMetadata().getSystemTags().add("trackedCondition");
+ unTrackParameterRule.setCondition(unTrackedCondition);
+ rulesService.setRule(unTrackParameterRule);
+ refreshPersistence();
+ rulesService.refreshRules();
+ // Check that the given event return the tracked condition
+ Profile profile = new Profile(UUID.randomUUID().toString());
+ Session session = new Session(UUID.randomUUID().toString(),
profile, new Date(), TEST_SCOPE);
+ Event viewEvent = generateViewEvent(session, profile);
+ Set<Condition> trackedConditions =
rulesService.getTrackedConditions(viewEvent.getTarget());
+ Assert.assertTrue(trackedConditions.contains(trackedCondition));
+ Assert.assertFalse(trackedConditions.contains(unTrackedCondition));
+ } finally {
+ // Clean up test data
+ rulesService.removeRule("tracked-parameter-rule");
+ rulesService.removeRule("not-tracked-parameter-rule");
+ definitionsService.removeConditionType("clickEventCondition");
+ }
+ }
+
@Override
public void updateServices() throws InterruptedException {
super.updateServices();
diff --git a/itests/src/test/resources/testClickEventCondition.json
b/itests/src/test/resources/testClickEventCondition.json
new file mode 100644
index 0000000..4cb5646
--- /dev/null
+++ b/itests/src/test/resources/testClickEventCondition.json
@@ -0,0 +1,58 @@
+{
+ "metadata": {
+ "id": "clickEventCondition",
+ "name": "clickEventCondition",
+ "description": "",
+ "systemTags": [
+ "availableToEndUser",
+ "behavioral",
+ "profileTags",
+ "event",
+ "condition",
+ "eventCondition",
+ "usableInPastEventCondition",
+ "trackedCondition"
+ ],
+ "readOnly": true
+ },
+ "parentCondition": {
+ "type": "booleanCondition",
+ "parameterValues": {
+ "subConditions": [
+ {
+ "type": "eventTypeCondition",
+ "parameterValues": {
+ "eventTypeId": "click"
+ }
+ },
+ {
+ "type": "sourceEventPropertyCondition",
+ "parameterValues": {
+ "path": "parameter::tracked_properties_pageInfo_pagePath"
+ }
+ },
+ {
+ "type": "eventPropertyCondition",
+ "parameterValues": {
+ "propertyName": "target.itemId",
+ "propertyValue": "parameter::itemId",
+ "comparisonOperator": "equals"
+ }
+ }
+ ],
+ "operator": "and"
+ }
+ },
+ "parameters": [
+ {
+ "id": "tracked_properties_pageInfo_pagePath",
+ "type": "string",
+ "multivalued": false
+ },
+ {
+ "id": "itemId",
+ "type": "string",
+ "multivalued": false
+ }
+ ]
+}
\ No newline at end of file
diff --git
a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
index 01ae985..fbf4710 100644
---
a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
+++
b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
@@ -17,6 +17,7 @@
package org.apache.unomi.services.impl.rules;
+import org.apache.commons.lang3.StringUtils;
import org.apache.unomi.api.Event;
import org.apache.unomi.api.Item;
import org.apache.unomi.api.Metadata;
@@ -45,6 +46,7 @@ import java.util.concurrent.TimeUnit;
public class RulesServiceImpl implements RulesService, EventListenerService,
SynchronousBundleListener {
public static final String RULE_QUERY_PREFIX = "rule_";
+ public static final String TRACKED_PARAMETER_PREFIX = "tracked_";
private static final Logger logger =
LoggerFactory.getLogger(RulesServiceImpl.class.getName());
private BundleContext bundleContext;
@@ -57,14 +59,14 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
private ActionExecutorDispatcher actionExecutorDispatcher;
private List<Rule> allRules;
- private Map<String,RuleStatistics> allRuleStatistics = new
ConcurrentHashMap<>();
+ private Map<String, RuleStatistics> allRuleStatistics = new
ConcurrentHashMap<>();
private Integer rulesRefreshInterval = 1000;
private Integer rulesStatisticsRefreshInterval = 10000;
private List<RuleListenerService> ruleListeners = new
CopyOnWriteArrayList<RuleListenerService>();
- private Map<String,Set<Rule>> rulesByEventType = new HashMap<>();
+ private Map<String, Set<Rule>> rulesByEventType = new HashMap<>();
private Boolean optimizedRulesActivated = true;
public void setBundleContext(BundleContext bundleContext) {
@@ -282,8 +284,8 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
return rules;
}
- private Map<String,Set<Rule>> getRulesByEventType(List<Rule> rules) {
- Map<String,Set<Rule>> newRulesByEventType = new HashMap<>();
+ private Map<String, Set<Rule>> getRulesByEventType(List<Rule> rules) {
+ Map<String, Set<Rule>> newRulesByEventType = new HashMap<>();
for (Rule rule : rules) {
updateRulesByEventType(newRulesByEventType, rule);
}
@@ -313,7 +315,7 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
changes |= eventService.send(ruleFired);
RuleStatistics ruleStatistics = getLocalRuleStatistics(rule);
-
ruleStatistics.setLocalExecutionCount(ruleStatistics.getLocalExecutionCount()+1);
+
ruleStatistics.setLocalExecutionCount(ruleStatistics.getLocalExecutionCount() +
1);
ruleStatistics.setLocalActionsTime(ruleStatistics.getLocalActionsTime() +
totalActionsTime);
this.allRuleStatistics.put(rule.getItemId(), ruleStatistics);
}
@@ -328,14 +330,14 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
return persistenceService.load(ruleId, RuleStatistics.class);
}
- public Map<String,RuleStatistics> getAllRuleStatistics() {
+ public Map<String, RuleStatistics> getAllRuleStatistics() {
return allRuleStatistics;
}
@Override
public void resetAllRuleStatistics() {
Condition matchAllCondition = new
Condition(definitionsService.getConditionType("matchAllCondition"));
-
persistenceService.removeByQuery(matchAllCondition,RuleStatistics.class);
+ persistenceService.removeByQuery(matchAllCondition,
RuleStatistics.class);
allRuleStatistics.clear();
}
@@ -348,7 +350,7 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
}
public PartialList<Metadata> getRuleMetadatas(Query query) {
- if(query.isForceRefresh()){
+ if (query.isForceRefresh()) {
persistenceService.refresh();
}
definitionsService.resolveConditionType(query.getCondition());
@@ -394,24 +396,47 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
persistenceService.save(rule);
}
- public Set<Condition> getTrackedConditions(Item source){
+ public Set<Condition> getTrackedConditions(Item source) {
Set<Condition> trackedConditions = new HashSet<>();
for (Rule r : allRules) {
if (!r.getMetadata().isEnabled()) {
continue;
}
- Condition trackedCondition =
definitionsService.extractConditionBySystemTag(r.getCondition(),
"trackedCondition");
- if(trackedCondition != null){
- Condition sourceEventPropertyCondition =
definitionsService.extractConditionBySystemTag(r.getCondition(),
"sourceEventCondition");
- if(source != null && sourceEventPropertyCondition != null) {
- ParserHelper.resolveConditionType(definitionsService,
sourceEventPropertyCondition, "rule " + r.getItemId() + " source event
condition");
-
if(persistenceService.testMatch(sourceEventPropertyCondition, source)){
+ Condition ruleCondition = r.getCondition();
+ Condition trackedCondition =
definitionsService.extractConditionBySystemTag(ruleCondition,
"trackedCondition");
+ if (trackedCondition != null) {
+ Condition evalCondition =
definitionsService.extractConditionBySystemTag(ruleCondition,
"sourceEventCondition");
+ if (evalCondition != null) {
+ if (persistenceService.testMatch(evalCondition, source)) {
trackedConditions.add(trackedCondition);
}
} else {
- trackedConditions.add(trackedCondition);
+ // lookup for track parameters
+ Map<String, Object> trackedParameters = new HashMap<>();
+ trackedCondition.getParameterValues().forEach((key, value)
-> {
+ if (!TRACKED_PARAMETER_PREFIX.equals(key) &&
StringUtils.startsWith(key, TRACKED_PARAMETER_PREFIX)) {
+
trackedParameters.put(StringUtils.replace(StringUtils.substringAfter(key,
TRACKED_PARAMETER_PREFIX), "_", "."), value);
+ }
+ });
+ if (trackedParameters.size() > 0) {
+ evalCondition = new
Condition(definitionsService.getConditionType("booleanCondition"));
+ evalCondition.setParameter("operator", "and");
+ ArrayList<Condition> conditions = new ArrayList<>();
+ trackedParameters.forEach((key, value) -> {
+ Condition propCondition = new
Condition(definitionsService.getConditionType("eventPropertyCondition"));
+ propCondition.setParameter("comparisonOperator",
"equals");
+ propCondition.setParameter("propertyName", key);
+ propCondition.setParameter("propertyValue", value);
+ conditions.add(propCondition);
+ });
+ evalCondition.setParameter("subConditions",
conditions);
+ if (persistenceService.testMatch(evalCondition,
source)) {
+ trackedConditions.add(trackedCondition);
+ }
+ } else {
+ trackedConditions.add(trackedCondition);
+ }
}
-
}
}
return trackedConditions;
@@ -428,7 +453,7 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
refreshRules();
}
};
-
schedulerService.getScheduleExecutorService().scheduleWithFixedDelay(task,
0,rulesRefreshInterval, TimeUnit.MILLISECONDS);
+
schedulerService.getScheduleExecutorService().scheduleWithFixedDelay(task, 0,
rulesRefreshInterval, TimeUnit.MILLISECONDS);
TimerTask statisticsTask = new TimerTask() {
@Override
@@ -456,7 +481,7 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
private void syncRuleStatistics() {
List<RuleStatistics> allPersistedRuleStatisticsList =
persistenceService.getAllItems(RuleStatistics.class);
- Map<String,RuleStatistics> allPersistedRuleStatistics = new
HashMap<>();
+ Map<String, RuleStatistics> allPersistedRuleStatistics = new
HashMap<>();
for (RuleStatistics ruleStatistics : allPersistedRuleStatisticsList) {
allPersistedRuleStatistics.put(ruleStatistics.getItemId(),
ruleStatistics);
}
@@ -543,7 +568,7 @@ public class RulesServiceImpl implements RulesService,
EventListenerService, Syn
}
}
- private void updateRulesByEventType(Map<String,Set<Rule>>
rulesByEventType, Rule rule) {
+ private void updateRulesByEventType(Map<String, Set<Rule>>
rulesByEventType, Rule rule) {
Set<String> eventTypeIds =
ParserHelper.resolveConditionEventTypes(rule.getCondition());
for (String eventTypeId : eventTypeIds) {
Set<Rule> rules = rulesByEventType.get(eventTypeId);