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

[unomi] branch UNOMI-400-hardcodedpropertyaccessors-refactoring updated: UNOMI-400 Refactoring of hardcoded property accessors

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

shuber pushed a commit to branch UNOMI-400-hardcodedpropertyaccessors-refactoring
in repository https://gitbox.apache.org/repos/asf/unomi.git


The following commit(s) were added to refs/heads/UNOMI-400-hardcodedpropertyaccessors-refactoring by this push:
     new e939be1  UNOMI-400 Refactoring of hardcoded property accessors
e939be1 is described below

commit e939be19cb3c0dd708f4119f4268f5517e38e3d8
Author: Serge Huber <sh...@jahia.com>
AuthorDate: Tue Nov 17 23:19:20 2020 +0100

    UNOMI-400 Refactoring of hardcoded property accessors
---
 .../conditions/PropertyConditionEvaluator.java     | 256 +--------------------
 .../CampaignHardcodedPropertyAccessor.java         |  43 ++++
 .../ConsentHardcodedPropertyAccessor.java          |  43 ++++
 .../CustomItemHardcodedPropertyAccessor.java       |  34 +++
 .../accessors/EventHardcodedPropertyAccessor.java  |  55 +++++
 .../accessors/GoalHardcodedPropertyAccessor.java   |  34 +++
 .../accessors/HardcodedPropertyAccessor.java       |  36 +++
 .../HardcodedPropertyAccessorRegistry.java         | 131 +++++++++++
 .../accessors/ItemHardcodedPropertyAccessor.java   |  43 ++++
 .../accessors/MapHardcodedPropertyAccessor.java    |  38 +++
 .../MetadataHardcodedPropertyAccessor.java         |  52 +++++
 .../MetadataItemHardcodedPropertyAccessor.java     |  33 +++
 .../ProfileHardcodedPropertyAccessor.java          |  49 ++++
 .../accessors/RuleHardcodedPropertyAccessor.java   |  37 +++
 .../SessionHardcodedPropertyAccessor.java          |  52 +++++
 .../TimestampedItemHardcodedPropertyAccessor.java  |  34 +++
 .../conditions/PropertyConditionEvaluatorTest.java |   4 +-
 17 files changed, 725 insertions(+), 249 deletions(-)

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..aa50586 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,7 +23,10 @@ import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.unomi.api.*;
 import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.goals.Goal;
 import org.apache.unomi.api.rules.Rule;
+import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessor;
+import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessorRegistry;
 import org.apache.unomi.scripting.ExpressionFilter;
 import org.apache.unomi.scripting.ExpressionFilterFactory;
 import org.apache.unomi.scripting.SecureFilteringClassLoader;
@@ -52,14 +55,14 @@ public class PropertyConditionEvaluator implements ConditionEvaluator {
     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 +296,7 @@ public class PropertyConditionEvaluator implements ConditionEvaluator {
     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 +311,7 @@ public class PropertyConditionEvaluator implements ConditionEvaluator {
     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 +332,6 @@ public class PropertyConditionEvaluator implements ConditionEvaluator {
         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 +436,4 @@ public class PropertyConditionEvaluator implements ConditionEvaluator {
         }
     }
 
-    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/CampaignHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CampaignHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..2718cfb
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CampaignHardcodedPropertyAccessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+public class CampaignHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Campaign> {
+    public CampaignHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/ConsentHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ConsentHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..5f63e3a
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ConsentHardcodedPropertyAccessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+public class ConsentHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Consent> {
+
+    public ConsentHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/CustomItemHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CustomItemHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..ed85103
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/CustomItemHardcodedPropertyAccessor.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.CustomItem;
+
+public class CustomItemHardcodedPropertyAccessor extends HardcodedPropertyAccessor<CustomItem> {
+
+    public CustomItemHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/EventHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/EventHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..81c1fb6
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/EventHardcodedPropertyAccessor.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+public class EventHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Event> {
+
+    public EventHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/GoalHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/GoalHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..c1cbbf0
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/GoalHardcodedPropertyAccessor.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.goals.Goal;
+
+public class GoalHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Goal> {
+
+    public GoalHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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..9a8385b
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessor.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * 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;
+    }
+
+    abstract Object getProperty(T object, String propertyName, String leftoverExpression);
+
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessorRegistry.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessorRegistry.java
new file mode 100644
index 0000000..6094a8f
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/HardcodedPropertyAccessorRegistry.java
@@ -0,0 +1,131 @@
+/*
+ * 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.*;
+import org.apache.unomi.api.campaigns.Campaign;
+import org.apache.unomi.api.goals.Goal;
+import org.apache.unomi.api.rules.Rule;
+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 ItemHardcodedPropertyAccessor(this));
+        propertyAccessors.put(MetadataItem.class.getName(), new MetadataItemHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Metadata.class.getName(), new MetadataHardcodedPropertyAccessor(this));
+        propertyAccessors.put(TimestampedItem.class.getName(), new TimestampedItemHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Event.class.getName(), new EventHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Profile.class.getName(), new ProfileHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Consent.class.getName(), new ConsentHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Session.class.getName(), new SessionHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Rule.class.getName(), new RuleHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Goal.class.getName(), new GoalHardcodedPropertyAccessor(this));
+        propertyAccessors.put(CustomItem.class.getName(), new CustomItemHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Campaign.class.getName(), new CampaignHardcodedPropertyAccessor(this));
+        propertyAccessors.put(Map.class.getName(), new MapHardcodedPropertyAccessor(this));
+    }
+
+    public static class NextTokens {
+        public String propertyName;
+        public String leftoverExpression;
+    }
+
+    protected NextTokens getNextTokens(String expression) {
+        NextTokens nextTokens = new NextTokens();
+        if (expression.startsWith("[\"")) {
+            int lookupNameBeginPos = "[\"".length();
+            int lookupNameEndPos = expression.indexOf("\"].", lookupNameBeginPos);
+            if (lookupNameEndPos > lookupNameBeginPos) {
+                nextTokens.propertyName = expression.substring(lookupNameBeginPos, lookupNameEndPos);
+                nextTokens.leftoverExpression = expression.substring(lookupNameEndPos+2);
+            } else {
+                nextTokens.propertyName = expression.substring(lookupNameBeginPos);
+                nextTokens.leftoverExpression = null;
+            }
+        } else if (expression.startsWith(".")) {
+            int lookupNameBeginPos = ".".length();
+            int lookupNameEndPos = lookupNameBeginPos;
+            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;
+            }
+            if (lookupNameEndPos > lookupNameBeginPos) {
+                nextTokens.propertyName = expression.substring(lookupNameBeginPos, lookupNameEndPos);
+                nextTokens.leftoverExpression = expression.substring(lookupNameEndPos);
+            } else {
+                nextTokens.propertyName = expression.substring(lookupNameBeginPos);
+                nextTokens.leftoverExpression = null;
+            }
+        } else {
+            int lookupNameBeginPos = 0;
+            int lookupNameEndPos = expression.indexOf(".", lookupNameBeginPos);
+            if (lookupNameEndPos > lookupNameBeginPos) {
+                nextTokens.propertyName = expression.substring(lookupNameBeginPos, lookupNameEndPos);
+                nextTokens.leftoverExpression = expression.substring(lookupNameEndPos);
+            } else {
+                nextTokens.propertyName = expression.substring(lookupNameBeginPos);
+                nextTokens.leftoverExpression = null;
+            }
+        }
+        return nextTokens;
+    }
+
+
+    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/accessors/ItemHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ItemHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..41ce3a4
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ItemHardcodedPropertyAccessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+public class ItemHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Item> {
+
+    public ItemHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/MapHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MapHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..92895fe
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MapHardcodedPropertyAccessor.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 java.util.Map;
+
+public class MapHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Map> {
+    public MapHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/MetadataHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..edb3310
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataHardcodedPropertyAccessor.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+public class MetadataHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Metadata> {
+
+    public MetadataHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/MetadataItemHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataItemHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..7c26c59
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/MetadataItemHardcodedPropertyAccessor.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+public class MetadataItemHardcodedPropertyAccessor extends HardcodedPropertyAccessor<MetadataItem> {
+    public MetadataItemHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/ProfileHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ProfileHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..3778c27
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/ProfileHardcodedPropertyAccessor.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+public class ProfileHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Profile> {
+
+    public ProfileHardcodedPropertyAccessor(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/RuleHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/RuleHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..28e9bb1
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/RuleHardcodedPropertyAccessor.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+public class RuleHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Rule> {
+
+    public RuleHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/SessionHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/SessionHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..a318721
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/SessionHardcodedPropertyAccessor.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+public class SessionHardcodedPropertyAccessor extends HardcodedPropertyAccessor<Session> {
+
+    public SessionHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/TimestampedItemHardcodedPropertyAccessor.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/TimestampedItemHardcodedPropertyAccessor.java
new file mode 100644
index 0000000..c408e8c
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/accessors/TimestampedItemHardcodedPropertyAccessor.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.TimestampedItem;
+
+public class TimestampedItemHardcodedPropertyAccessor extends HardcodedPropertyAccessor<TimestampedItem> {
+
+    public TimestampedItemHardcodedPropertyAccessor(HardcodedPropertyAccessorRegistry registry) {
+        super(registry);
+    }
+
+    @Override
+    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/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 @@ package org.apache.unomi.plugins.baseplugin.conditions;
 
 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 java.util.regex.Pattern;
 
 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 @@ public class PropertyConditionEvaluatorTest {
         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"));
 
     }