UNOMI-400 Refactoring of hardcoded property accessors (#218)
* UNOMI-400 Refactoring of hardcoded property accessors
* UNOMI-400 More refactoring on property accessors & added unit test
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java
new file mode 100644
index 0000000..59a70b5
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java
@@ -0,0 +1,132 @@
+/*
+ * 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.plugins.baseplugin.conditions;
+
+import org.apache.unomi.api.*;
+import org.apache.unomi.api.campaigns.Campaign;
+import org.apache.unomi.api.goals.Goal;
+import org.apache.unomi.api.rules.Rule;
+import org.apache.unomi.plugins.baseplugin.conditions.accessors.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+/**
+ * This class contains the registry of all the hardcoded property accessors.
+ * For the moment this list of accessors is hardcoded, but in a future update it could be made dynamic.
+ */
+public class HardcodedPropertyAccessorRegistry {
+
+ private static final Logger logger = LoggerFactory.getLogger(HardcodedPropertyAccessorRegistry.class.getName());
+
+ Map<String, HardcodedPropertyAccessor> propertyAccessors = new HashMap<>();
+
+ public HardcodedPropertyAccessorRegistry() {
+ propertyAccessors.put(Item.class.getName(), new ItemAccessor(this));
+ propertyAccessors.put(MetadataItem.class.getName(), new MetadataItemAccessor(this));
+ propertyAccessors.put(Metadata.class.getName(), new MetadataAccessor(this));
+ propertyAccessors.put(TimestampedItem.class.getName(), new TimestampedItemAccessor(this));
+ propertyAccessors.put(Event.class.getName(), new EventAccessor(this));
+ propertyAccessors.put(Profile.class.getName(), new ProfileAccessor(this));
+ propertyAccessors.put(Consent.class.getName(), new ConsentAccessor(this));
+ propertyAccessors.put(Session.class.getName(), new SessionAccessor(this));
+ propertyAccessors.put(Rule.class.getName(), new RuleAccessor(this));
+ propertyAccessors.put(Goal.class.getName(), new GoalAccessor(this));
+ propertyAccessors.put(CustomItem.class.getName(), new CustomItemAccessor(this));
+ propertyAccessors.put(Campaign.class.getName(), new CampaignAccessor(this));
+ propertyAccessors.put(Map.class.getName(), new MapAccessor(this));
+ }
+
+ public static class NextTokens {
+ public String propertyName;
+ public String leftoverExpression;
+ }
+
+ protected NextTokens getNextTokens(String expression) {
+ if (expression.startsWith("[\"")) {
+ int lookupNameBeginPos = "[\"".length();
+ int lookupNameEndPos = expression.indexOf("\"]", lookupNameBeginPos);
+ return buildNextTokens(expression, lookupNameBeginPos, lookupNameEndPos, lookupNameEndPos+2);
+ } else if (expression.startsWith(".")) {
+ int lookupNameBeginPos = ".".length();
+ int lookupNameEndPos = findNextStartDelimiterPos(expression, lookupNameBeginPos);
+ return buildNextTokens(expression, lookupNameBeginPos, lookupNameEndPos, lookupNameEndPos);
+ } else {
+ int lookupNameBeginPos = 0;
+ int lookupNameEndPos = findNextStartDelimiterPos(expression, lookupNameBeginPos);
+ return buildNextTokens(expression, lookupNameBeginPos, lookupNameEndPos, lookupNameEndPos);
+ }
+ }
+
+ private NextTokens buildNextTokens(String expression, int lookupNameBeginPos, int lookupNameEndPos, int leftoverStartPos) {
+ NextTokens nextTokens = new NextTokens();
+ if (lookupNameEndPos >= lookupNameBeginPos) {
+ nextTokens.propertyName = expression.substring(lookupNameBeginPos, lookupNameEndPos);
+ nextTokens.leftoverExpression = expression.substring(leftoverStartPos);
+ if ("".equals(nextTokens.leftoverExpression)) {
+ nextTokens.leftoverExpression = null;
+ }
+ } else {
+ nextTokens.propertyName = expression.substring(lookupNameBeginPos);
+ nextTokens.leftoverExpression = null;
+ }
+ return nextTokens;
+ }
+
+ private int findNextStartDelimiterPos(String expression, int lookupNameBeginPos) {
+ int lookupNameEndPos;
+ int dotlookupNameEndPos = expression.indexOf(".", lookupNameBeginPos);
+ int squareBracketlookupNameEndPos = expression.indexOf("[\"", lookupNameBeginPos);
+ if (dotlookupNameEndPos >= lookupNameBeginPos && squareBracketlookupNameEndPos >= lookupNameBeginPos) {
+ lookupNameEndPos = Math.min(dotlookupNameEndPos, squareBracketlookupNameEndPos);
+ } else if (dotlookupNameEndPos >= lookupNameBeginPos) {
+ lookupNameEndPos = dotlookupNameEndPos;
+ } else if (squareBracketlookupNameEndPos >= lookupNameBeginPos) {
+ lookupNameEndPos = squareBracketlookupNameEndPos;
+ } else {
+ lookupNameEndPos = -1;
+ }
+ return lookupNameEndPos;
+ }
+
+
+ public Object getProperty(Object object, String expression) {
+ if (expression == null) {
+ return object;
+ }
+ if (expression.trim().equals("")) {
+ return object;
+ }
+ NextTokens nextTokens = getNextTokens(expression);
+ List<Class<?>> lookupClasses = new ArrayList<>();
+ lookupClasses.add(object.getClass());
+ lookupClasses.add(object.getClass().getSuperclass());
+ lookupClasses.addAll(Arrays.asList(object.getClass().getInterfaces()));
+ for (Class<?> lookupClass : lookupClasses) {
+ HardcodedPropertyAccessor propertyAccessor = propertyAccessors.get(lookupClass.getName());
+ if (propertyAccessor != null) {
+ Object result = propertyAccessor.getProperty(object, nextTokens.propertyName, nextTokens.leftoverExpression);
+ if (!HardcodedPropertyAccessor.PROPERTY_NOT_FOUND_MARKER.equals(result)) {
+ return result;
+ }
+ }
+ }
+ logger.warn("Couldn't find any property access for class {} and expression {}", object.getClass().getName(), expression);
+ return HardcodedPropertyAccessor.PROPERTY_NOT_FOUND_MARKER;
+ }
+}
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 00f3787..13319b6 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
@@ -23,8 +23,7 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.unomi.api.*;
import org.apache.unomi.api.conditions.Condition;
-import org.apache.unomi.api.rules.Rule;
-import org.apache.unomi.scripting.ExpressionFilter;
+import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessor;
import org.apache.unomi.scripting.ExpressionFilterFactory;
import org.apache.unomi.scripting.SecureFilteringClassLoader;
import org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper;
@@ -52,14 +51,14 @@
private static final Logger logger = LoggerFactory.getLogger(PropertyConditionEvaluator.class.getName());
private static final SimpleDateFormat yearMonthDayDateFormat = new SimpleDateFormat("yyyyMMdd");
- public static final String NOT_OPTIMIZED_MARKER = "$$$###NOT_OPTIMIZED###$$$";
- private Map<String, Map<String, ExpressionAccessor>> expressionCache = new HashMap<>(64);
+ private final Map<String, Map<String, ExpressionAccessor>> expressionCache = new HashMap<>(64);
private boolean usePropertyConditionOptimizations = true;
- private static ClassLoader secureFilteringClassLoader = new SecureFilteringClassLoader(PropertyConditionEvaluator.class.getClassLoader());
+ private static final ClassLoader secureFilteringClassLoader = new SecureFilteringClassLoader(PropertyConditionEvaluator.class.getClassLoader());
+ private static final HardcodedPropertyAccessorRegistry hardcodedPropertyAccessorRegistry = new HardcodedPropertyAccessorRegistry();
private ExpressionFilterFactory expressionFilterFactory;
- private boolean useOGNLScripting = Boolean.parseBoolean(System.getProperty("org.apache.unomi.security.properties.useOGNLScripting", "false"));
+ private final boolean useOGNLScripting = Boolean.parseBoolean(System.getProperty("org.apache.unomi.security.properties.useOGNLScripting", "false"));
public void setUsePropertyConditionOptimizations(boolean usePropertyConditionOptimizations) {
this.usePropertyConditionOptimizations = usePropertyConditionOptimizations;
@@ -293,7 +292,7 @@
protected Object getPropertyValue(Item item, String expression) throws Exception {
if (usePropertyConditionOptimizations) {
Object result = getHardcodedPropertyValue(item, expression);
- if (!NOT_OPTIMIZED_MARKER.equals(result)) {
+ if (!HardcodedPropertyAccessor.PROPERTY_NOT_FOUND_MARKER.equals(result)) {
return result;
}
}
@@ -308,7 +307,7 @@
protected Object getHardcodedPropertyValue(Item item, String expression) {
// the following are optimizations to avoid using the expressions that are slower. The main objective here is
// to avoid the most used expression that may also trigger calls to the Java Reflection API.
- return getItemProperty(item, expression);
+ return hardcodedPropertyAccessorRegistry.getProperty(item, expression);
}
protected Object getOGNLPropertyValue(Item item, String expression) throws Exception {
@@ -329,21 +328,6 @@
return null;
}
- private Object getNestedPropertyValue(String expressionPart, Map<String, Object> properties) {
- int nextDotPos = expressionPart.indexOf(".");
- if (nextDotPos > -1) {
- String mapKey = expressionPart.substring(0, nextDotPos);
- Object mapValue = properties.get(mapKey);
- if (mapValue == null) {
- return null;
- }
- String nextExpression = expressionPart.substring(nextDotPos + 1);
- return getNestedPropertyValue(nextExpression, (Map<String, Object>) mapValue);
- } else {
- return properties.get(expressionPart);
- }
- }
-
private class ClassLoaderClassResolver extends DefaultClassResolver {
private ClassLoader classLoader;
@@ -448,230 +432,4 @@
}
}
- private Object getEventProperty(Event event, String expression) {
- if (expression.startsWith("properties.")) {
- return getNestedPropertyValue(expression.substring("properties.".length()), event.getProperties());
- }
- if ("scope".equals(expression)) {
- return event.getScope();
- }
- if ("eventType".equals(expression)) {
- return event.getEventType();
- }
- if (expression.startsWith("profile")) {
- if ("profile".equals(expression)) {
- return event.getProfile();
- } else {
- return getProfileProperty(event.getProfile(), expression.substring("profile".length()+1));
- }
- }
- if ("profileId".equals(expression)) {
- return event.getProfileId();
- }
- if (expression.startsWith("session")) {
- if ("session".equals(expression)) {
- return event.getSession();
- } else {
- return getSessionProperty(event.getSession(), expression.substring("session".length()+1));
- }
- }
- if ("sessionId".equals(expression)) {
- return event.getSessionId();
- }
- if (expression.startsWith("source")) {
- if ("source".equals(expression)) {
- return event.getSource();
- } else {
- return getItemProperty(event.getSource(), expression.substring("source".length()+1));
- }
- }
- if (expression.startsWith("target")) {
- if ("target".equals(expression)) {
- return event.getTarget();
- } else {
- return getItemProperty(event.getTarget(), expression.substring("target".length()+1));
- }
- }
- if ("timeStamp".equals(expression)) {
- return event.getTimeStamp();
- }
- if ("itemId".equals(expression)) {
- return event.getItemId();
- }
- if ("itemType".equals(expression)) {
- return event.getItemType();
- }
- logger.warn("Requested unimplemented property {} on Event object", expression);
- return NOT_OPTIMIZED_MARKER;
- }
-
- private Object getSessionProperty(Session session, String expression) {
- if ("scope".equals(expression)) {
- return session.getScope();
- }
- if ("timeStamp".equals(expression)) {
- return session.getTimeStamp();
- }
- if ("duration".equals(expression)) {
- return session.getDuration();
- }
- if ("size".equals(expression)) {
- return session.getSize();
- }
- if ("lastEventDate".equals(expression)) {
- return session.getLastEventDate();
- }
- if (expression.startsWith("properties.")) {
- return getNestedPropertyValue(expression.substring("properties.".length()), session.getProperties());
- }
- if (expression.startsWith("systemProperties.")) {
- return getNestedPropertyValue(expression.substring("systemProperties.".length()), session.getSystemProperties());
- }
- if ("itemId".equals(expression)) {
- return session.getItemId();
- }
- if ("itemType".equals(expression)) {
- return session.getItemType();
- }
- if (expression.startsWith("profile")) {
- if ("profile".equals(expression)) {
- return session.getProfile();
- } else {
- return getProfileProperty((Profile) session.getProfile(), expression.substring("profile".length()+1));
- }
- }
- if ("profileId".equals(expression)) {
- return session.getProfileId();
- }
- logger.warn("Requested unimplemented property {} on Session object", expression);
- return NOT_OPTIMIZED_MARKER;
- }
-
- private Object getProfileProperty(Profile profile, String expression) {
- if ("segments".equals(expression)) {
- return profile.getSegments();
- }
- if (expression.startsWith("consents")) {
- if ("consents".equals(expression)) {
- return profile.getConsents();
- } else {
- String consentLookupName = null;
- String leftoverExpression = expression;
- if (expression.startsWith("consents[\"")) {
- int lookupNameBeginPos = "consents[\"".length();
- int lookupNameEndPos = expression.indexOf("\"].", lookupNameBeginPos);
- if (lookupNameEndPos > lookupNameBeginPos) {
- consentLookupName = expression.substring(lookupNameBeginPos, lookupNameEndPos);
- leftoverExpression = expression.substring(lookupNameEndPos+3);
- } else {
- consentLookupName = expression.substring(lookupNameBeginPos);
- leftoverExpression = null;
- }
- } else if (expression.startsWith("consents.")) {
- int lookupNameBeginPos = "consents.".length();
- int lookupNameEndPos = expression.indexOf(".", lookupNameBeginPos);
- if (lookupNameEndPos > lookupNameBeginPos) {
- consentLookupName = expression.substring(lookupNameBeginPos, lookupNameEndPos);
- leftoverExpression = expression.substring(lookupNameEndPos+1);
- } else {
- consentLookupName = expression.substring(lookupNameBeginPos);
- leftoverExpression = expression.substring(lookupNameEndPos);
- }
- }
- Consent consent = profile.getConsents().get(consentLookupName);
- if (consent == null) {
- return null;
- }
- if (leftoverExpression == null) {
- return consent;
- }
- return getConsentProperty(consent, leftoverExpression);
- }
- }
- if (expression.startsWith("scores.")) {
- return profile.getScores().get(expression.substring("scores.".length()));
- }
- if (expression.startsWith("properties.")) {
- return getNestedPropertyValue(expression.substring("properties.".length()), profile.getProperties());
- }
- if (expression.startsWith("systemProperties.")) {
- return getNestedPropertyValue(expression.substring("systemProperties.".length()), profile.getSystemProperties());
- }
- if ("itemId".equals(expression)) {
- return profile.getItemId();
- }
- if ("itemType".equals(expression)) {
- return profile.getItemType();
- }
- if ("mergedWith".equals(expression)) {
- return profile.getMergedWith();
- }
- logger.warn("Requested unimplemented property {} on Profile object", expression);
- return NOT_OPTIMIZED_MARKER;
- }
-
- private Object getCustomItemProperty(CustomItem customItem, String expression) {
- if (expression.startsWith("properties.")) {
- return getNestedPropertyValue(expression.substring("properties.".length()), customItem.getProperties());
- }
- if ("itemId".equals(expression)) {
- return customItem.getItemId();
- }
- if ("itemType".equals(expression)) {
- return customItem.getItemType();
- }
- if ("scope".equals(expression)) {
- return customItem.getScope();
- }
- logger.warn("Requested unimplemented property {} on CustomItem object", expression);
- return NOT_OPTIMIZED_MARKER;
- }
-
- private Object getRuleProperty(Rule rule, String expression) {
- if ("itemId".equals(expression)) {
- return rule.getItemId();
- }
- if ("itemType".equals(expression)) {
- return rule.getItemType();
- }
- if ("scope".equals(expression)) {
- return rule.getScope();
- }
- logger.warn("Requested unimplemented property {} on Rule object", expression);
- return NOT_OPTIMIZED_MARKER;
- }
-
- private Object getItemProperty(Item item, String expression) {
- if (item instanceof Profile) {
- return getProfileProperty((Profile) item, expression);
- } else if (item instanceof Session) {
- return getSessionProperty((Session) item, expression);
- } else if (item instanceof Rule) {
- return getRuleProperty((Rule) item, expression);
- } else if (item instanceof Event) {
- return getEventProperty((Event) item, expression);
- } else if (item instanceof CustomItem) {
- return getCustomItemProperty((CustomItem) item, expression);
- } else {
- logger.warn("Requested unrecognized property {} on {} class", expression, item.getClass().getName());
- return NOT_OPTIMIZED_MARKER;
- }
- }
-
- private Object getConsentProperty(Consent consent, String expression) {
- if ("typeIdentifier".equals(expression)) {
- return consent.getTypeIdentifier();
- } else if ("scope".equals(expression)) {
- return consent.getScope();
- } else if ("status".equals(expression)) {
- return consent.getStatus();
- } else if ("statusDate".equals(expression)) {
- return consent.getStatusDate();
- } else if ("revokeDate".equals(expression)) {
- return consent.getRevokeDate();
- } else {
- logger.warn("Requested unrecognized property {} on Consent object {}", expression, consent);
- return NOT_OPTIMIZED_MARKER;
- }
- }
}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CampaignAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CampaignAccessor.java
new file mode 100644
index 0000000..5736780
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CampaignAccessor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.campaigns.Campaign;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class CampaignAccessor extends HardcodedPropertyAccessor<Campaign> {
+ public CampaignAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Campaign object, String propertyName, String leftoverExpression) {
+ if ("startDate".equals(propertyName)) {
+ return object.getStartDate();
+ } else if ("endDate".equals(propertyName)) {
+ return object.getEndDate();
+ } else if ("cost".equals(propertyName)) {
+ return object.getCost();
+ } else if ("currency".equals(propertyName)) {
+ return object.getCurrency();
+ } else if ("primaryGoal".equals(propertyName)) {
+ return object.getPrimaryGoal();
+ } else if ("timezone".equals(propertyName)) {
+ return object.getTimezone();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ConsentAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ConsentAccessor.java
new file mode 100644
index 0000000..1b052b9
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ConsentAccessor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.Consent;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class ConsentAccessor extends HardcodedPropertyAccessor<Consent> {
+
+ public ConsentAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Consent object, String propertyName, String leftoverExpression) {
+ if ("typeIdentifier".equals(propertyName)) {
+ return object.getTypeIdentifier();
+ } else if ("scope".equals(propertyName)) {
+ return object.getScope();
+ } else if ("status".equals(propertyName)) {
+ return object.getStatus();
+ } else if ("statusDate".equals(propertyName)) {
+ return object.getStatusDate();
+ } else if ("revokeDate".equals(propertyName)) {
+ return object.getRevokeDate();
+ } else {
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CustomItemAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CustomItemAccessor.java
new file mode 100644
index 0000000..66ceab2
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CustomItemAccessor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.CustomItem;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class CustomItemAccessor extends HardcodedPropertyAccessor<CustomItem> {
+
+ public CustomItemAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(CustomItem object, String propertyName, String leftoverExpression) {
+ if ("properties".equals(propertyName)) {
+ return registry.getProperty(object.getProperties(), leftoverExpression);
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/EventAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/EventAccessor.java
new file mode 100644
index 0000000..ba10bd9
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/EventAccessor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class EventAccessor extends HardcodedPropertyAccessor<Event> {
+
+ public EventAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Event object, String propertyName, String leftoverExpression) {
+ if ("properties".equals(propertyName)) {
+ return registry.getProperty(object.getProperties(), leftoverExpression);
+ }
+ if ("eventType".equals(propertyName)) {
+ return object.getEventType();
+ }
+ if ("profile".equals(propertyName)) {
+ return registry.getProperty(object.getProfile(), leftoverExpression);
+ }
+ if ("profileId".equals(propertyName)) {
+ return object.getProfileId();
+ }
+ if ("session".equals(propertyName)) {
+ return registry.getProperty(object.getSession(), leftoverExpression);
+ }
+ if ("sessionId".equals(propertyName)) {
+ return object.getSessionId();
+ }
+ if ("source".equals(propertyName)) {
+ return registry.getProperty(object.getSource(), leftoverExpression);
+ }
+ if ("target".equals(propertyName)) {
+ return registry.getProperty(object.getTarget(), leftoverExpression);
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/GoalAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/GoalAccessor.java
new file mode 100644
index 0000000..03e0b6c
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/GoalAccessor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.goals.Goal;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class GoalAccessor extends HardcodedPropertyAccessor<Goal> {
+
+ public GoalAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Goal object, String propertyName, String leftoverExpression) {
+ if ("campaignId".equals(propertyName)) {
+ return object.getCampaignId();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessor.java
new file mode 100644
index 0000000..7a414fd
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessor.java
@@ -0,0 +1,38 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+/**
+ * Hardcoded property accessors serve two purpose:
+ * - control access to object fields, only expose the ones that are "safe" to use
+ * - prevent using Java Reflection API that is both slower and potentially unsafe as there could be potential to abuse it.
+ */
+public abstract class HardcodedPropertyAccessor<T> {
+
+ public static final String PROPERTY_NOT_FOUND_MARKER = "$$$###PROPERTY_NOT_FOUND###$$$";
+
+ protected HardcodedPropertyAccessorRegistry registry;
+
+ public HardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+ this.registry = registry;
+ }
+
+ public abstract Object getProperty(T object, String propertyName, String leftoverExpression);
+
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ItemAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ItemAccessor.java
new file mode 100644
index 0000000..7dc9913
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ItemAccessor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.Item;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class ItemAccessor extends HardcodedPropertyAccessor<Item> {
+
+ public ItemAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Item object, String propertyName, String leftoverExpression) {
+ if ("itemId".equals(propertyName)) {
+ return object.getItemId();
+ }
+ if ("itemType".equals(propertyName)) {
+ return object.getItemType();
+ }
+ if ("scope".equals(propertyName)) {
+ return object.getScope();
+ }
+ if ("version".equals(propertyName)) {
+ return object.getVersion();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MapAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MapAccessor.java
new file mode 100644
index 0000000..fb04257
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MapAccessor.java
@@ -0,0 +1,40 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+import java.util.Map;
+
+public class MapAccessor extends HardcodedPropertyAccessor<Map> {
+ public MapAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Map object, String propertyName, String leftoverExpression) {
+ Object mapValue = object.get(propertyName);
+ if (mapValue == null) {
+ return null;
+ }
+ if (leftoverExpression != null) {
+ return registry.getProperty(mapValue, leftoverExpression);
+ } else {
+ return mapValue;
+ }
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataAccessor.java
new file mode 100644
index 0000000..c4effd1
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataAccessor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.Metadata;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class MetadataAccessor extends HardcodedPropertyAccessor<Metadata> {
+
+ public MetadataAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Metadata object, String propertyName, String leftoverExpression) {
+ if ("id".equals(propertyName)) {
+ return object.getId();
+ } else if ("name".equals(propertyName)) {
+ return object.getName();
+ } else if ("description".equals(propertyName)) {
+ return object.getDescription();
+ } else if ("scope".equals(propertyName)) {
+ return object.getScope();
+ } else if ("tags".equals(propertyName)) {
+ return object.getTags();
+ } else if ("systemTags".equals(propertyName)) {
+ return object.getSystemTags();
+ } else if ("enabled".equals(propertyName)) {
+ return object.isEnabled();
+ } else if ("missingPlugins".equals(propertyName)) {
+ return object.isMissingPlugins();
+ } else if ("hidden".equals(propertyName)) {
+ return object.isHidden();
+ } else if ("readOnly".equals(propertyName)) {
+ return object.isReadOnly();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataItemAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataItemAccessor.java
new file mode 100644
index 0000000..1c787a3
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataItemAccessor.java
@@ -0,0 +1,34 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.MetadataItem;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class MetadataItemAccessor extends HardcodedPropertyAccessor<MetadataItem> {
+ public MetadataItemAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(MetadataItem object, String propertyName, String leftoverExpression) {
+ if ("metadata".equals(propertyName)) {
+ registry.getProperty(object.getMetadata(), leftoverExpression);
+ }
+ return null;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ProfileAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ProfileAccessor.java
new file mode 100644
index 0000000..d008cfd
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ProfileAccessor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class ProfileAccessor extends HardcodedPropertyAccessor<Profile> {
+
+ public ProfileAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Profile object, String propertyName, String leftoverExpression) {
+ if ("segments".equals(propertyName)) {
+ return object.getSegments();
+ }
+ if ("consents".equals(propertyName)) {
+ return registry.getProperty(object.getConsents(), leftoverExpression);
+ }
+ if ("scores".equals(propertyName)) {
+ return registry.getProperty(object.getScores(), leftoverExpression);
+ }
+ if ("properties".equals(propertyName)) {
+ return registry.getProperty(object.getProperties(), leftoverExpression);
+ }
+ if ("systemProperties".equals(propertyName)) {
+ return registry.getProperty(object.getSystemProperties(), leftoverExpression);
+ }
+ if ("mergedWith".equals(propertyName)) {
+ return object.getMergedWith();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/RuleAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/RuleAccessor.java
new file mode 100644
index 0000000..e398798
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/RuleAccessor.java
@@ -0,0 +1,38 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.rules.Rule;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class RuleAccessor extends HardcodedPropertyAccessor<Rule> {
+
+ public RuleAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Rule object, String propertyName, String leftoverExpression) {
+ if ("linkedItems".equals(propertyName)) {
+ return object.getLinkedItems();
+ } else if ("priority".equals(propertyName)) {
+ return object.getPriority();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/SessionAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/SessionAccessor.java
new file mode 100644
index 0000000..a3da510
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/SessionAccessor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.Session;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class SessionAccessor extends HardcodedPropertyAccessor<Session> {
+
+ public SessionAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(Session object, String propertyName, String leftoverExpression) {
+ if ("duration".equals(propertyName)) {
+ return object.getDuration();
+ }
+ if ("size".equals(propertyName)) {
+ return object.getSize();
+ }
+ if ("lastEventDate".equals(propertyName)) {
+ return object.getLastEventDate();
+ }
+ if ("properties".equals(propertyName)) {
+ return registry.getProperty(object.getProperties(), leftoverExpression);
+ }
+ if ("systemProperties".equals(propertyName)) {
+ return registry.getProperty(object.getSystemProperties(), leftoverExpression);
+ }
+ if ("profile".equals(propertyName)) {
+ return registry.getProperty(object.getProfile(), leftoverExpression);
+ }
+ if ("profileId".equals(propertyName)) {
+ return object.getProfileId();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/TimestampedItemAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/TimestampedItemAccessor.java
new file mode 100644
index 0000000..7916a28
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/TimestampedItemAccessor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.plugins.baseplugin.conditions.accessors;
+
+import org.apache.unomi.api.TimestampedItem;
+import org.apache.unomi.plugins.baseplugin.conditions.HardcodedPropertyAccessorRegistry;
+
+public class TimestampedItemAccessor extends HardcodedPropertyAccessor<TimestampedItem> {
+
+ public TimestampedItemAccessor(HardcodedPropertyAccessorRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Object getProperty(TimestampedItem object, String propertyName, String leftoverExpression) {
+ if ("timeStamp".equals(propertyName)) {
+ return object.getTimeStamp();
+ }
+ return PROPERTY_NOT_FOUND_MARKER;
+ }
+}
diff --git a/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistryTest.java b/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistryTest.java
new file mode 100644
index 0000000..03bdb30
--- /dev/null
+++ b/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistryTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.plugins.baseplugin.conditions;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class HardcodedPropertyAccessorRegistryTest {
+
+ HardcodedPropertyAccessorRegistry registry = new HardcodedPropertyAccessorRegistry();
+
+ @Test
+ public void testGetNextTokens() {
+ assertTokens("test", "test", null);
+ assertTokens("test.test", "test", ".test");
+ assertTokens("test..", "test", "..");
+ assertTokens("test...", "test", "...");
+ assertTokens(".test", "test", null);
+ assertTokens(".test[abc]", "test[abc]", null);
+ assertTokens("[abc]", "[abc]", null);
+ assertTokens("[\"abc\"]", "abc", null);
+ assertTokens(".test[\"abc\"]", "test", "[\"abc\"]");
+ assertTokens("..test", "", ".test");
+ assertTokens(".[test", "[test", null);
+ assertTokens("[\"test\"][\"a\"]", "test", "[\"a\"]");
+ assertTokens("test[\"a\"].c", "test", "[\"a\"].c");
+ assertTokens("[\"b\"]", "b", null);
+ assertTokens("[\"b\"].c", "b", ".c");
+ assertTokens("[\"b.c\"].c", "b.c", ".c");
+ assertTokens("[\"b\"test\"].c", "b\"test", ".c");
+ assertTokens("[\"b\"]test\"].c", "b", "test\"].c");
+ assertTokens("[\"b\\.\\\"]c\"].c", "b\\.\\", "c\"].c");
+ assertTokens("[]", "[]", null);
+ }
+
+ private void assertTokens(String expression, String expectedPropertyName, String expectedLeftoverExpression) {
+ HardcodedPropertyAccessorRegistry.NextTokens nextTokens = registry.getNextTokens(expression);
+ assertEquals("Property name value was wrong", expectedPropertyName, nextTokens.propertyName);
+ assertEquals("Leftover expression value was wrong", expectedLeftoverExpression, nextTokens.leftoverExpression);
+ }
+}
diff --git a/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java b/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java
index af039a5..1ba3c72 100644
--- a/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java
+++ b/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java
@@ -18,6 +18,7 @@
import ognl.MethodFailedException;
import org.apache.unomi.api.*;
+import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessor;
import org.apache.unomi.scripting.ExpressionFilter;
import org.apache.unomi.scripting.ExpressionFilterFactory;
import org.junit.Before;
@@ -33,7 +34,6 @@
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;
-import static org.apache.unomi.plugins.baseplugin.conditions.PropertyConditionEvaluator.NOT_OPTIMIZED_MARKER;
import static org.junit.Assert.assertFalse;
public class PropertyConditionEvaluatorTest {
@@ -94,7 +94,7 @@
assertEquals("Unexisting property should be null", null, propertyConditionEvaluator.getHardcodedPropertyValue(mockProfile, "properties.email"));
// here let's make sure our reporting of non optimized expressions works.
- assertEquals("Should have received the non-optimized marker string", NOT_OPTIMIZED_MARKER, propertyConditionEvaluator.getHardcodedPropertyValue(mockSession, "profile.non-existing-field"));
+ assertEquals("Should have received the non-optimized marker string", HardcodedPropertyAccessor.PROPERTY_NOT_FOUND_MARKER, propertyConditionEvaluator.getHardcodedPropertyValue(mockSession, "profile.non-existing-field"));
}