http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
new file mode 100644
index 0000000..9a7c979
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
@@ -0,0 +1,200 @@
+/*
+ * 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.actions;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Persona;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.Session;
+import org.apache.unomi.api.actions.Action;
+import org.apache.unomi.api.actions.ActionExecutor;
+import org.apache.unomi.api.actions.ActionPostExecutor;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.services.DefinitionsService;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.persistence.spi.PersistenceService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.List;
+
+public class MergeProfilesOnPropertyAction implements ActionExecutor {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(MergeProfilesOnPropertyAction.class.getName());
+
+    private final int MAX_COOKIE_AGE_IN_SECONDS = 60 * 60 * 24 * 365 * 10; // 
10-years
+    private int cookieAgeInSeconds = MAX_COOKIE_AGE_IN_SECONDS;
+    private String profileIdCookieName = "context-profile-id";
+
+    private ProfileService profileService;
+
+    private PersistenceService persistenceService;
+
+    private EventService eventService;
+
+    private DefinitionsService definitionsService;
+
+    public void setCookieAgeInSeconds(int cookieAgeInSeconds) {
+        this.cookieAgeInSeconds = cookieAgeInSeconds;
+    }
+
+    public void setProfileIdCookieName(String profileIdCookieName) {
+        this.profileIdCookieName = profileIdCookieName;
+    }
+
+    public void setProfileService(ProfileService profileService) {
+        this.profileService = profileService;
+    }
+
+    public PersistenceService getPersistenceService() {
+        return persistenceService;
+    }
+
+    public void setPersistenceService(PersistenceService persistenceService) {
+        this.persistenceService = persistenceService;
+    }
+
+    public EventService getEventService() {
+        return eventService;
+    }
+
+    public void setEventService(EventService eventService) {
+        this.eventService = eventService;
+    }
+
+    public DefinitionsService getDefinitionsService() {
+        return definitionsService;
+    }
+
+    public void setDefinitionsService(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+
+    public int execute(Action action, Event event) {
+
+        final Profile profile = event.getProfile();
+
+        final String mergeProfilePropertyName = (String) 
action.getParameterValues().get("mergeProfilePropertyName");
+        final String mergeProfilePropertyValue = 
profile.getProperty(mergeProfilePropertyName) != null ? 
profile.getProperty(mergeProfilePropertyName).toString() : "";
+        final Session currentSession = event.getSession();
+
+        // store the profile id in case the merge change it to a previous one
+
+        if (profile instanceof Persona) {
+            return EventService.NO_CHANGE;
+        }
+
+        if (StringUtils.isEmpty(mergeProfilePropertyValue)) {
+            return EventService.NO_CHANGE;
+        }
+        String profileId = profile.getItemId();
+
+        Condition propertyCondition = new 
Condition(definitionsService.getConditionType("eventPropertyCondition"));
+        propertyCondition.setParameter("comparisonOperator", "equals");
+        propertyCondition.setParameter("propertyName", 
mergeProfilePropertyName);
+        propertyCondition.setParameter("propertyValue", 
mergeProfilePropertyValue);
+
+        Condition excludeMergedProfilesCondition = new 
Condition(definitionsService.getConditionType("eventPropertyCondition"));
+        excludeMergedProfilesCondition.setParameter("comparisonOperator", 
"missing");
+        excludeMergedProfilesCondition.setParameter("propertyName", 
"mergedWith");
+
+        Condition c = new 
Condition(definitionsService.getConditionType("booleanCondition"));
+        c.setParameter("operator", "and");
+        c.setParameter("subConditions", Arrays.asList(propertyCondition, 
excludeMergedProfilesCondition));
+
+        final List<Profile> profiles = persistenceService.query(c, 
"properties.firstVisit", Profile.class);
+
+        // add current Profile to profiles to be merged
+        boolean add = true;
+        for (Profile p : profiles) {
+            add = add && !StringUtils.equals(p.getItemId(), 
profile.getItemId());
+        }
+        if (add) {
+            profiles.add(profile);
+        }
+
+        if (profiles.size() == 1) {
+            return EventService.NO_CHANGE;
+        }
+
+        Profile masterProfile = profileService.mergeProfiles(profiles.get(0), 
profiles);
+
+        if (!masterProfile.getItemId().equals(profileId)) {
+            HttpServletResponse httpServletResponse = (HttpServletResponse) 
event.getAttributes().get(Event.HTTP_RESPONSE_ATTRIBUTE);
+            sendProfileCookie(event.getSession().getProfile(), 
httpServletResponse);
+            final String masterProfileId = masterProfile.getItemId();
+
+            // At the end of the merge, we must set the merged profile as 
profile event to process other Actions
+            event.setProfileId(masterProfileId);
+            event.setProfile(masterProfile);
+
+            event.getActionPostExecutors().add(new ActionPostExecutor() {
+                @Override
+                public boolean execute() {
+                    try {
+                        for (Profile profile : profiles) {
+                            String profileId = profile.getItemId();
+                            if (!StringUtils.equals(profileId, 
masterProfileId)) {
+                                List<Session> sessions = 
persistenceService.query("profileId", profileId, null, Session.class);
+                                if 
(currentSession.getProfileId().equals(profileId) && 
!sessions.contains(currentSession)) {
+                                    sessions.add(currentSession);
+                                }
+                                for (Session session : sessions) {
+                                    
persistenceService.update(session.getItemId(), session.getTimeStamp(), 
Session.class, "profileId", masterProfileId);
+                                }
+
+                                List<Event> events = 
persistenceService.query("profileId", profileId, null, Event.class);
+                                for (Event event : events) {
+                                    
persistenceService.update(event.getItemId(), event.getTimeStamp(), Event.class, 
"profileId", masterProfileId);
+                                }
+                                // we must mark all the profiles that we 
merged into the master as merged with the master, and they will
+                                // be deleted upon next load
+                                profile.setMergedWith(masterProfileId);
+                                persistenceService.update(profile.getItemId(), 
null, Profile.class, "mergedWith", masterProfileId);
+                            }
+                        }
+                    } catch (Exception e) {
+                        logger.error("unable to execute callback action, 
profile and session will not be saved", e);
+                        return false;
+                    }
+                    return true;
+                }
+            });
+            return EventService.PROFILE_UPDATED;
+        }
+
+        return EventService.NO_CHANGE;
+    }
+
+    public void sendProfileCookie(Profile profile, ServletResponse response) {
+        if (response instanceof HttpServletResponse) {
+            HttpServletResponse httpServletResponse = (HttpServletResponse) 
response;
+            Cookie profileIdCookie = new Cookie(profileIdCookieName, 
profile.getItemId());
+            profileIdCookie.setPath("/");
+            profileIdCookie.setMaxAge(cookieAgeInSeconds);
+            httpServletResponse.addCookie(profileIdCookie);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SendEventAction.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SendEventAction.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SendEventAction.java
new file mode 100644
index 0000000..f94851e
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SendEventAction.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.actions;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Item;
+import org.apache.unomi.api.actions.Action;
+import org.apache.unomi.api.actions.ActionExecutor;
+import org.apache.unomi.api.services.EventService;
+
+import java.util.Map;
+
+public class SendEventAction implements ActionExecutor {
+
+    private EventService eventService;
+
+    public void setEventService(EventService eventService) {
+        this.eventService = eventService;
+    }
+
+    @Override
+    public int execute(Action action, Event event) {
+        String eventType = (String) 
action.getParameterValues().get("eventType");
+        @SuppressWarnings("unchecked")
+        Map<String, Object> eventProperties = (Map<String, Object>) 
action.getParameterValues().get("eventProperties");
+        Item target = (Item) action.getParameterValues().get("eventTarget");
+//        String type = (String) target.get("type");
+
+//            Item targetItem = new CustomItem();
+//            BeanUtils.populate(targetItem, target);
+
+        Event subEvent = new Event(eventType, event.getSession(), 
event.getProfile(), event.getScope(), event, target, event.getTimeStamp());
+        subEvent.getAttributes().putAll(event.getAttributes());
+        subEvent.getProperties().putAll(eventProperties);
+
+        return eventService.send(subEvent);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java
new file mode 100644
index 0000000..7f5e31a
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetEventOccurenceCountAction.java
@@ -0,0 +1,87 @@
+/*
+ * 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.actions;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.actions.Action;
+import org.apache.unomi.api.actions.ActionExecutor;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.services.DefinitionsService;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.persistence.spi.PersistenceService;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class SetEventOccurenceCountAction implements ActionExecutor {
+    private DefinitionsService definitionsService;
+
+    private PersistenceService persistenceService;
+
+    public void setDefinitionsService(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+
+    public void setPersistenceService(PersistenceService persistenceService) {
+        this.persistenceService = persistenceService;
+    }
+
+    @Override
+    public int execute(Action action, Event event) {
+        final Condition pastEventCondition = (Condition) 
action.getParameterValues().get("pastEventCondition");
+
+        Condition andCondition = new 
Condition(definitionsService.getConditionType("booleanCondition"));
+        andCondition.setParameter("operator", "and");
+        ArrayList<Condition> conditions = new ArrayList<Condition>();
+
+        Condition eventCondition = (Condition) 
pastEventCondition.getParameter("eventCondition");
+        definitionsService.resolveConditionType(eventCondition);
+        conditions.add(eventCondition);
+
+        Condition c = new 
Condition(definitionsService.getConditionType("eventPropertyCondition"));
+        c.setParameter("propertyName","profileId");
+        c.setParameter("comparisonOperator", "equals");
+        c.setParameter("propertyValue",event.getProfileId());
+        conditions.add(c);
+
+        if (pastEventCondition.getParameter("numberOfDays") != null) {
+            int i = (Integer) pastEventCondition.getParameter("numberOfDays");
+
+            Condition timeCondition = new 
Condition(definitionsService.getConditionType("eventPropertyCondition"));
+            timeCondition.setParameter("propertyName","timeStamp");
+            timeCondition.setParameter("comparisonOperator","greaterThan");
+            timeCondition.setParameter("propertyValueDateExpr","now-"+i+"d");
+
+            conditions.add(timeCondition);
+        }
+
+        andCondition.setParameter("subConditions", conditions);
+
+        long count = persistenceService.queryCount(andCondition, 
Event.ITEM_TYPE);
+
+        Map<String,Object> pastEvents = (Map<String,Object>) 
event.getProfile().getSystemProperties().get("pastEvents");
+        if (pastEvents == null) {
+            pastEvents = new LinkedHashMap<>();
+            event.getProfile().getSystemProperties().put("pastEvents", 
pastEvents);
+        }
+        pastEvents.put((String) 
pastEventCondition.getParameter("generatedPropertyKey"), count + 1);
+
+        return EventService.PROFILE_UPDATED;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java
new file mode 100644
index 0000000..55c1210
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java
@@ -0,0 +1,63 @@
+/*
+ * 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.actions;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.actions.Action;
+import org.apache.unomi.api.actions.ActionExecutor;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.persistence.spi.PropertyHelper;
+
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+public class SetPropertyAction implements ActionExecutor {
+
+    public SetPropertyAction() {
+    }
+
+    public String getActionId() {
+        return "setPropertyAction";
+    }
+
+    public int execute(Action action, Event event) {
+        Object propertyValue = 
action.getParameterValues().get("setPropertyValue");
+        Object propertyValueInteger = 
action.getParameterValues().get("setPropertyValueInteger");
+
+        if(propertyValueInteger != null && propertyValue == null) {
+            propertyValue = PropertyHelper.getInteger(propertyValueInteger);
+        }
+
+        if (propertyValue != null && propertyValue.equals("now")) {
+            SimpleDateFormat format = new 
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+            format.setTimeZone(TimeZone.getTimeZone("UTC"));
+            propertyValue = format.format(event.getTimeStamp());
+        }
+        String propertyName = (String) 
action.getParameterValues().get("setPropertyName");
+
+        boolean storeInSession = 
Boolean.TRUE.equals(action.getParameterValues().get("storeInSession"));
+
+        Object target = storeInSession ? event.getSession() : 
event.getProfile();
+
+        if (PropertyHelper.setProperty(target, propertyName, propertyValue, 
(String) action.getParameterValues().get("setPropertyStrategy"))) {
+            return storeInSession ? EventService.SESSION_UPDATED : 
EventService.PROFILE_UPDATED;
+        }
+        return EventService.NO_CHANGE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java
new file mode 100644
index 0000000..919ce54
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java
@@ -0,0 +1,54 @@
+/*
+ * 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.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ES query builder for boolean conditions.
+ */
+public class BooleanConditionESQueryBuilder implements ConditionESQueryBuilder 
{
+
+    @Override
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context,
+            ConditionESQueryBuilderDispatcher dispatcher) {
+        boolean isAndOperator = "and".equalsIgnoreCase((String) 
condition.getParameter("operator"));
+        @SuppressWarnings("unchecked")
+        List<Condition> conditions = (List<Condition>) 
condition.getParameter("subConditions");
+
+        int conditionCount = conditions.size();
+
+        if (conditionCount == 1) {
+            return dispatcher.buildFilter(conditions.get(0), context);
+        }
+
+        FilterBuilder[] l = new FilterBuilder[conditionCount];
+        for (int i = 0; i < conditionCount; i++) {
+            l[i] = dispatcher.buildFilter(conditions.get(i), context);
+        }
+
+        return isAndOperator ? FilterBuilders.andFilter(l) : 
FilterBuilders.orFilter(l);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java
new file mode 100644
index 0000000..1ecfc65
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.Item;
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Evaluator for AND and OR conditions.
+ */
+public class BooleanConditionEvaluator implements ConditionEvaluator {
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context,
+            ConditionEvaluatorDispatcher dispatcher) {
+        boolean isAnd = "and".equalsIgnoreCase((String) 
condition.getParameter("operator"));
+        @SuppressWarnings("unchecked")
+        List<Condition> conditions = (List<Condition>) 
condition.getParameter("subConditions");
+        for (Condition sub : conditions) {
+            boolean eval = dispatcher.eval(sub, item, context);
+            if (!eval && isAnd) {
+                // And
+                return false;
+            } else if (eval && !isAnd) {
+                // Or
+                return true;
+            }
+        }
+        return isAnd;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java
new file mode 100644
index 0000000..804f4f4
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java
@@ -0,0 +1,60 @@
+/*
+ * 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.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.Map;
+
+public class GeoLocationByPointSessionConditionESQueryBuilder implements 
ConditionESQueryBuilder {
+    @Override
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
+        String type = (String) condition.getParameter("type");
+
+        if("circle".equals(type)) {
+            Double circleLatitude = (Double) 
condition.getParameter("circleLatitude");
+            Double circleLongitude = (Double) 
condition.getParameter("circleLongitude");
+            String distance = condition.getParameter("distance").toString();
+
+            if(circleLatitude != null && circleLongitude != null && distance 
!= null) {
+                return FilterBuilders.geoDistanceFilter("location")
+                        .lat(circleLatitude)
+                        .lon(circleLongitude)
+                        .distance(distance);
+            }
+        } else if("rectangle".equals(type)) {
+            Double rectLatitudeNE = (Double) 
condition.getParameter("rectLatitudeNE");
+            Double rectLongitudeNE = (Double) 
condition.getParameter("rectLongitudeNE");
+            Double rectLatitudeSW = (Double) 
condition.getParameter("rectLatitudeSW");
+            Double rectLongitudeSW = (Double) 
condition.getParameter("rectLongitudeSW");
+
+            if(rectLatitudeNE != null && rectLongitudeNE != null && 
rectLatitudeSW != null && rectLongitudeSW != null) {
+                return FilterBuilders.geoBoundingBoxFilter("location")
+                        .topLeft(rectLatitudeNE, rectLongitudeNE)
+                        .bottomRight(rectLatitudeSW, rectLongitudeSW);
+            }
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java
new file mode 100644
index 0000000..c0b4134
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java
@@ -0,0 +1,70 @@
+/*
+ * 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.commons.beanutils.BeanUtils;
+import org.apache.unomi.api.Item;
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+import org.elasticsearch.common.geo.GeoDistance;
+import org.elasticsearch.common.unit.DistanceUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+public class GeoLocationByPointSessionConditionEvaluator implements 
ConditionEvaluator {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(GeoLocationByPointSessionConditionEvaluator.class.getName());
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context, ConditionEvaluatorDispatcher dispatcher) {
+        try {
+            String type = (String) condition.getParameter("type");
+            Double latitudeProperty = 
Double.parseDouble(BeanUtils.getProperty(item, "properties.location.lat"));
+            Double longitudeProperty = 
Double.parseDouble(BeanUtils.getProperty(item, "properties.location.lon"));
+
+            if("circle".equals(type)) {
+                Double circleLatitude = (Double) 
condition.getParameter("circleLatitude");
+                Double circleLongitude = (Double) 
condition.getParameter("circleLongitude");
+                DistanceUnit.Distance distance = 
DistanceUnit.Distance.parseDistance(condition.getParameter("distance").toString());
+
+                double d = GeoDistance.DEFAULT.calculate(circleLatitude, 
circleLongitude, latitudeProperty, longitudeProperty, distance.unit);
+                return d < distance.value;
+            } else if("rectangle".equals(type)) {
+                Double rectLatitudeNE = (Double) 
condition.getParameter("rectLatitudeNE");
+                Double rectLongitudeNE = (Double) 
condition.getParameter("rectLongitudeNE");
+                Double rectLatitudeSW = (Double) 
condition.getParameter("rectLatitudeSW");
+                Double rectLongitudeSW = (Double) 
condition.getParameter("rectLongitudeSW");
+
+                if(rectLatitudeNE != null && rectLongitudeNE != null && 
rectLatitudeSW != null && rectLongitudeSW != null) {
+                    return latitudeProperty < Math.max(rectLatitudeNE, 
rectLatitudeSW)  &&
+                            latitudeProperty > Math.min(rectLatitudeNE, 
rectLatitudeSW) &&
+                            longitudeProperty < Math.max(rectLongitudeNE, 
rectLongitudeSW) &&
+                            longitudeProperty > Math.min(rectLongitudeNE, 
rectLongitudeSW);
+                }
+            }
+        } catch (Exception e) {
+            logger.debug("Cannot get properties", e);
+        }
+        return false;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java
new file mode 100644
index 0000000..9efd2c1
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.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;
+
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.Map;
+
+public class MatchAllConditionESQueryBuilder implements 
ConditionESQueryBuilder {
+
+    @Override
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
+        return FilterBuilders.matchAllFilter();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java
new file mode 100644
index 0000000..ee8c1e8
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.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;
+
+import org.apache.unomi.api.Item;
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+
+import java.util.Map;
+
+public class MatchAllConditionEvaluator implements ConditionEvaluator {
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context, ConditionEvaluatorDispatcher dispatcher) {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.java
new file mode 100644
index 0000000..7793aa0
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.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;
+
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.Map;
+
+/**
+ * Builder for NOT condition.
+ */
+public class NotConditionESQueryBuilder implements ConditionESQueryBuilder {
+
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
+        Condition subCondition = (Condition) 
condition.getParameter("subCondition");
+        return FilterBuilders.notFilter(dispatcher.buildFilter(subCondition, 
context));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java
new file mode 100644
index 0000000..5522f31
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.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;
+
+import org.apache.unomi.api.Item;
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+
+import java.util.Map;
+
+/**
+ * Evaluator for NOT condition.
+ */
+public class NotConditionEvaluator implements ConditionEvaluator {
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context, ConditionEvaluatorDispatcher dispatcher) {
+        Condition subCondition = (Condition) 
condition.getParameter("subCondition");
+        return !dispatcher.eval(subCondition, item, context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java
new file mode 100644
index 0000000..64fe15f
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java
@@ -0,0 +1,88 @@
+/*
+ * 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.Event;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.services.DefinitionsService;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.apache.unomi.persistence.spi.PersistenceService;
+import org.apache.unomi.persistence.spi.aggregate.TermsAggregate;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.*;
+
+public class PastEventConditionESQueryBuilder implements 
ConditionESQueryBuilder {
+    private DefinitionsService definitionsService;
+    private PersistenceService persistenceService;
+
+    public void setDefinitionsService(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+
+    public void setPersistenceService(PersistenceService persistenceService) {
+        this.persistenceService = persistenceService;
+    }
+
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
+        Condition eventCondition;
+        try {
+            eventCondition = (Condition) 
condition.getParameter("eventCondition");
+        } catch (ClassCastException e) {
+            throw new IllegalArgumentException("Empty eventCondition");
+        }
+        if (eventCondition == null) {
+            throw new IllegalArgumentException("No eventCondition");
+        }
+        List<Condition> l = new ArrayList<Condition>();
+        Condition andCondition = new Condition();
+        
andCondition.setConditionType(definitionsService.getConditionType("booleanCondition"));
+        andCondition.setParameter("operator", "and");
+        andCondition.setParameter("subConditions", l);
+
+        l.add(eventCondition);
+
+        Integer numberOfDays = (Integer) 
condition.getParameter("numberOfDays");
+        if (numberOfDays != null) {
+            Condition numberOfDaysCondition = new Condition();
+            
numberOfDaysCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition"));
+            numberOfDaysCondition.setParameter("propertyName", "timeStamp");
+            numberOfDaysCondition.setParameter("comparisonOperator", 
"greaterThan");
+            numberOfDaysCondition.setParameter("propertyValueDateExpr", "now-" 
+ numberOfDays + "d");
+            l.add(numberOfDaysCondition);
+        }
+        //todo : Check behaviour with important number of profiles
+        Set<String> ids = new HashSet<String>();
+        Integer minimumEventCount = 
condition.getParameter("minimumEventCount") == null ? 0 : (Integer) 
condition.getParameter("minimumEventCount");
+        Integer maximumEventCount = 
condition.getParameter("maximumEventCount") == null  ? Integer.MAX_VALUE : 
(Integer) condition.getParameter("maximumEventCount");
+
+        Map<String, Long> res = 
persistenceService.aggregateQuery(andCondition, new 
TermsAggregate("profileId"), Event.ITEM_TYPE);
+        for (Map.Entry<String, Long> entry : res.entrySet()) {
+            if (!entry.getKey().startsWith("_")) {
+                if (entry.getValue() >= minimumEventCount && entry.getValue() 
<= maximumEventCount) {
+                    ids.add(entry.getKey());
+                }
+            }
+        }
+
+        return 
FilterBuilders.idsFilter(Profile.ITEM_TYPE).addIds(ids.toArray(new 
String[ids.size()]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java
new file mode 100644
index 0000000..0b18df5
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java
@@ -0,0 +1,104 @@
+/*
+ * 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.Event;
+import org.apache.unomi.api.Item;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.services.DefinitionsService;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+import org.apache.unomi.persistence.spi.PersistenceService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class PastEventConditionEvaluator implements ConditionEvaluator {
+
+    private PersistenceService persistenceService;
+
+    private DefinitionsService definitionsService;
+
+    public void setPersistenceService(PersistenceService persistenceService) {
+        this.persistenceService = persistenceService;
+    }
+
+    public void setDefinitionsService(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context, ConditionEvaluatorDispatcher dispatcher) {
+
+        final Map<String, Object> parameters = condition.getParameterValues();
+
+        Condition eventCondition = (Condition) 
parameters.get("eventCondition");
+
+        long count;
+
+        if (parameters.containsKey("generatedPropertyKey")) {
+            String key = (String) parameters.get("generatedPropertyKey");
+            Profile profile = (Profile) item;
+            Map<String,Object> pastEvents = (Map<String, Object>) 
profile.getSystemProperties().get("pastEvents");
+            if (pastEvents != null) {
+                Number l = (Number) pastEvents.get(key);
+                count = l != null ? l.longValue() : 0L;
+            } else {
+                count = 0;
+            }
+
+        } else {
+            if (eventCondition == null) {
+                throw new IllegalArgumentException("No eventCondition");
+            }
+
+            List<Condition> l = new ArrayList<Condition>();
+            Condition andCondition = new Condition();
+            
andCondition.setConditionType(definitionsService.getConditionType("booleanCondition"));
+            andCondition.setParameter("operator", "and");
+            andCondition.setParameter("subConditions", l);
+
+            l.add(eventCondition);
+
+            Condition profileCondition = new Condition();
+            
profileCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition"));
+            profileCondition.setParameter("propertyName", "profileId");
+            profileCondition.setParameter("comparisonOperator", "equals");
+            profileCondition.setParameter("propertyValue", item.getItemId());
+            l.add(profileCondition);
+
+            Integer numberOfDays = (Integer) 
condition.getParameter("numberOfDays");
+            if (numberOfDays != null) {
+                Condition numberOfDaysCondition = new Condition();
+                
numberOfDaysCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition"));
+                numberOfDaysCondition.setParameter("propertyName", 
"timeStamp");
+                numberOfDaysCondition.setParameter("comparisonOperator", 
"greaterThan");
+                numberOfDaysCondition.setParameter("propertyValueDateExpr", 
"now-" + numberOfDays + "d");
+                l.add(numberOfDaysCondition);
+            }
+            count = persistenceService.queryCount(andCondition, 
Event.ITEM_TYPE);
+        }
+
+        Integer minimumEventCount = parameters.get("minimumEventCount") == 
null  ? 0 : (Integer) parameters.get("minimumEventCount");
+        Integer maximumEventCount = parameters.get("maximumEventCount") == 
null  ? Integer.MAX_VALUE : (Integer) parameters.get("maximumEventCount");
+
+        return count > 0 && (count >= minimumEventCount && count <= 
maximumEventCount);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
new file mode 100644
index 0000000..d063ff3
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java
@@ -0,0 +1,135 @@
+/*
+ * 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.commons.lang3.ObjectUtils;
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.elasticsearch.common.joda.time.DateTime;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.List;
+import java.util.Map;
+
+public class PropertyConditionESQueryBuilder implements 
ConditionESQueryBuilder {
+
+    public PropertyConditionESQueryBuilder() {
+    }
+
+    @Override
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
+        String op = (String) condition.getParameter("comparisonOperator");
+        String name = (String) condition.getParameter("propertyName");
+
+        if(op == null || name == null){
+            throw new IllegalArgumentException("Impossible to build ES filter, 
condition is not valid, comparisonOperator and propertyName properties should 
be provided");
+        }
+
+        String expectedValue = ConditionContextHelper.foldToASCII((String) 
condition.getParameter("propertyValue"));
+        Object expectedValueInteger = 
condition.getParameter("propertyValueInteger");
+        Object expectedValueDate = condition.getParameter("propertyValueDate");
+        Object expectedValueDateExpr = 
condition.getParameter("propertyValueDateExpr");
+
+        List<?> expectedValues = ConditionContextHelper.foldToASCII((List<?>) 
condition.getParameter("propertyValues"));
+        List<?> expectedValuesInteger = (List<?>) 
condition.getParameter("propertyValuesInteger");
+        List<?> expectedValuesDate = (List<?>) 
condition.getParameter("propertyValuesDate");
+        List<?> expectedValuesDateExpr = (List<?>) 
condition.getParameter("propertyValuesDateExpr");
+
+        Object value = 
ObjectUtils.firstNonNull(expectedValue,expectedValueInteger,expectedValueDate,expectedValueDateExpr);
+        @SuppressWarnings("unchecked")
+        List<?> values = 
ObjectUtils.firstNonNull(expectedValues,expectedValuesInteger,expectedValuesDate,expectedValuesDateExpr);
+
+        switch (op) {
+            case "equals":
+                checkRequiredValue(value, name, op, false);
+                return FilterBuilders.termFilter(name, value);
+            case "notEquals":
+                checkRequiredValue(value, name, op, false);
+                return 
FilterBuilders.notFilter(FilterBuilders.termFilter(name, value));
+            case "greaterThan":
+                checkRequiredValue(value, name, op, false);
+                return FilterBuilders.rangeFilter(name).gt(value);
+            case "greaterThanOrEqualTo":
+                checkRequiredValue(value, name, op, false);
+                return FilterBuilders.rangeFilter(name).gte(value);
+            case "lessThan":
+                checkRequiredValue(value, name, op, false);
+                return FilterBuilders.rangeFilter(name).lt(value);
+            case "lessThanOrEqualTo":
+                checkRequiredValue(value, name, op, false);
+                return FilterBuilders.rangeFilter(name).lte(value);
+            case "between":
+                checkRequiredValuesSize(values, name, op, 2);
+                return 
FilterBuilders.rangeFilter(name).gte(values.get(0)).lte(values.get(1));
+            case "exists":
+                return FilterBuilders.existsFilter(name);
+            case "missing":
+                return FilterBuilders.missingFilter(name);
+            case "contains":
+                checkRequiredValue(expectedValue, name, op, false);
+                return FilterBuilders.regexpFilter(name, ".*" + expectedValue 
+ ".*");
+            case "startsWith":
+                checkRequiredValue(expectedValue, name, op, false);
+                return FilterBuilders.prefixFilter(name, expectedValue);
+            case "endsWith":
+                checkRequiredValue(expectedValue, name, op, false);
+                return FilterBuilders.regexpFilter(name, ".*" + expectedValue);
+            case "matchesRegex":
+                checkRequiredValue(expectedValue, name, op, false);
+                return FilterBuilders.regexpFilter(name, expectedValue);
+            case "in":
+                checkRequiredValue(values, name, op, true);
+                return FilterBuilders.inFilter(name, values.toArray());
+            case "notIn":
+                checkRequiredValue(values, name, op, true);
+                return FilterBuilders.notFilter(FilterBuilders.inFilter(name, 
values.toArray()));
+            case "all":
+                checkRequiredValue(values, name, op, true);
+                return FilterBuilders.termsFilter(name, 
values.toArray()).execution("and");
+            case "isDay":
+                checkRequiredValue(value, name, op, false);
+                return getIsSameDayRange(value, name);
+            case "isNotDay":
+                checkRequiredValue(value, name, op, false);
+                return FilterBuilders.notFilter(getIsSameDayRange(value, 
name));
+        }
+        return null;
+    }
+
+    private void checkRequiredValuesSize(List<?> values, String name, String 
operator, int expectedSize) {
+        if(values == null || values.size() != expectedSize) {
+            throw new IllegalArgumentException("Impossible to build ES filter, 
missing " + expectedSize + " values for a condition using comparisonOperator: " 
+ operator + ", and propertyName: " + name);
+        }
+    }
+
+    private void checkRequiredValue(Object value, String name, String 
operator, boolean multiple) {
+        if(value == null) {
+            throw new IllegalArgumentException("Impossible to build ES filter, 
missing value" + (multiple ? "s" : "") + " for condition using 
comparisonOperator: " + operator + ", and propertyName: " + name);
+        }
+    }
+
+    private FilterBuilder getIsSameDayRange (Object value, String name) {
+        DateTime date = new DateTime(value);
+        DateTime dayStart = date.withTimeAtStartOfDay();
+        DateTime dayAfterStart = date.plusDays(1).withTimeAtStartOfDay();
+        return 
FilterBuilders.rangeFilter(name).gte(dayStart.toDate()).lte(dayAfterStart.toDate());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..ca3e512
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java
@@ -0,0 +1,299 @@
+/*
+ * 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 ognl.Node;
+import ognl.Ognl;
+import ognl.OgnlContext;
+import ognl.OgnlException;
+import ognl.enhance.ExpressionAccessor;
+import org.apache.commons.beanutils.BeanUtilsBean;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Item;
+import org.apache.unomi.api.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+import org.apache.unomi.persistence.spi.PropertyHelper;
+import org.elasticsearch.ElasticsearchParseException;
+import org.elasticsearch.common.joda.DateMathParser;
+import org.elasticsearch.index.mapper.core.DateFieldMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+/**
+ * Evaluator for property comparison conditions
+ */
+public class PropertyConditionEvaluator implements ConditionEvaluator {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(PropertyConditionEvaluator.class.getName());
+
+    private static final SimpleDateFormat yearMonthDayDateFormat = new 
SimpleDateFormat("yyyyMMdd");
+    
+    private BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
+    
+    private Map<String, Map<String, ExpressionAccessor>> expressionCache = new 
HashMap<>(64); 
+
+    private int compare(Object actualValue, String expectedValue, Object 
expectedValueDate, Object expectedValueInteger, Object expectedValueDateExpr) {
+        if (expectedValue == null && expectedValueDate == null && 
expectedValueInteger == null && getDate(expectedValueDateExpr) == null) {
+            return actualValue == null ? 0 : 1;
+        } else if (actualValue == null) {
+            return -1;
+        }
+
+        if (expectedValueInteger != null) {
+            return 
PropertyHelper.getInteger(actualValue).compareTo(PropertyHelper.getInteger(expectedValueInteger));
+        } else if (expectedValueDate != null) {
+            return getDate(actualValue).compareTo(getDate(expectedValueDate));
+        } else if (expectedValueDateExpr != null) {
+            return 
getDate(actualValue).compareTo(getDate(expectedValueDateExpr));
+        } else {
+            return actualValue.toString().compareTo(expectedValue);
+        }
+    }
+
+    private boolean compareMultivalue(Object actualValue, List<?> 
expectedValues, List<?> expectedValuesDate, List<?> expectedValuesNumber, 
List<?> expectedValuesDateExpr, String op) {
+        @SuppressWarnings("unchecked")
+        List<?> expected = ObjectUtils.firstNonNull(expectedValues, 
expectedValuesDate, expectedValuesNumber);
+        if (actualValue == null) {
+            return expected == null;
+        } else if (expected == null) {
+            return false;
+        }
+        
+        List<Object> actual = 
ConditionContextHelper.foldToASCII(getValueSet(actualValue));
+
+        boolean result = true;
+        
+        switch (op) {
+            case "in":
+                result = false;
+                for (Object a : actual) {
+                    if (expected.contains(a)) {
+                        result = true;
+                        break;
+                    }
+                }
+                break;
+            case "notIn":
+                for (Object a : actual) {
+                    if (expected.contains(a)) {
+                        result = false;
+                        break;
+                    }
+                }
+                break;
+            case "all":
+                for (Object e : expected) {
+                    if (!actual.contains(e)) {
+                        result = false;
+                        break;
+                    }
+                }
+                break;
+                
+            default:
+                throw new IllegalArgumentException("Unknown comparison 
operator " + op);
+        }
+        
+        return result;
+    }
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context, ConditionEvaluatorDispatcher dispatcher) {
+        String op = (String) condition.getParameter("comparisonOperator");
+        String name = (String) condition.getParameter("propertyName");
+
+        String expectedValue = ConditionContextHelper.foldToASCII((String) 
condition.getParameter("propertyValue"));
+        Object expectedValueInteger = 
condition.getParameter("propertyValueInteger");
+        Object expectedValueDate = condition.getParameter("propertyValueDate");
+        Object expectedValueDateExpr = 
condition.getParameter("propertyValueDateExpr");
+
+        Object actualValue;
+        if (item instanceof Event && "eventType".equals(name)) {
+            actualValue = ((Event)item).getEventType();
+        } else {
+            try {
+                long time = System.nanoTime();
+                //actualValue = 
beanUtilsBean.getPropertyUtils().getProperty(item, name);
+                actualValue = getPropertyValue(item, name);
+                time = System.nanoTime() - time;
+                if (time > 5000000L) {
+                    logger.info("eval took {} ms for {} {}", time / 1000000L, 
item.getClass().getName(), name);
+                }
+            } catch (NullPointerException e) {
+                // property not found
+                actualValue = null;
+            } catch (Exception e) {
+                if (!(e instanceof OgnlException)
+                        || (!StringUtils.startsWith(e.getMessage(),
+                                "source is null for getProperty(null"))) {
+                    logger.warn("Error evaluating value for " + 
item.getClass().getName() + " " + name, e);
+                }
+                actualValue = null;
+            }
+        }
+        if (actualValue instanceof String) {
+            actualValue = ConditionContextHelper.foldToASCII((String) 
actualValue);
+        }
+
+        if(op == null) {
+            return false;
+        } else if(actualValue == null){
+            return op.equals("missing");
+        } else if (op.equals("exists")) {
+            return true;
+        } else if (op.equals("equals")) {
+            if (actualValue instanceof Collection) {
+                for (Object o : ((Collection<?>)actualValue)) {
+                    if (o instanceof String) {
+                        o = ConditionContextHelper.foldToASCII((String) o);
+                    }
+                    if (compare(o, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) == 0) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            return compare(actualValue, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) == 0;
+        } else if (op.equals("notEquals")) {
+            return compare(actualValue, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) != 0;
+        } else if (op.equals("greaterThan")) {
+            return compare(actualValue, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) > 0;
+        } else if (op.equals("greaterThanOrEqualTo")) {
+            return compare(actualValue, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) >= 0;
+        } else if (op.equals("lessThan")) {
+            return compare(actualValue, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) < 0;
+        } else if (op.equals("lessThanOrEqualTo")) {
+            return compare(actualValue, expectedValue, expectedValueDate, 
expectedValueInteger, expectedValueDateExpr) <= 0;
+        } else if (op.equals("between")) {
+            List<?> expectedValuesInteger = (List<?>) 
condition.getParameter("propertyValuesInteger");
+            List<?> expectedValuesDate = (List<?>) 
condition.getParameter("propertyValuesDate");
+            List<?> expectedValuesDateExpr = (List<?>) 
condition.getParameter("propertyValuesDateExpr");
+            return compare(actualValue, null,
+                    (expectedValuesDate != null && expectedValuesDate.size() 
>= 1) ? getDate(expectedValuesDate.get(0)) : null,
+                    (expectedValuesInteger != null && 
expectedValuesInteger.size() >= 1) ? (Integer) expectedValuesInteger.get(0) : 
null,
+                    (expectedValuesDateExpr != null && 
expectedValuesDateExpr.size() >= 1) ? (String) expectedValuesDateExpr.get(0) : 
null) >= 0
+                    &&
+                    compare(actualValue, null,
+                            (expectedValuesDate != null && 
expectedValuesDate.size() >= 2) ? getDate(expectedValuesDate.get(1)) : null,
+                            (expectedValuesInteger != null && 
expectedValuesInteger.size() >= 2) ? (Integer) expectedValuesInteger.get(1) : 
null,
+                            (expectedValuesDateExpr != null && 
expectedValuesDateExpr.size() >= 2) ? (String) expectedValuesDateExpr.get(1) : 
null) <= 0;
+        } else if (op.equals("contains")) {
+            return actualValue.toString().contains(expectedValue);
+        } else if (op.equals("startsWith")) {
+            return actualValue.toString().startsWith(expectedValue);
+        } else if (op.equals("endsWith")) {
+            return actualValue.toString().endsWith(expectedValue);
+        } else if (op.equals("matchesRegex")) {
+            return expectedValue != null && 
Pattern.compile(expectedValue).matcher(actualValue.toString()).matches();
+        } else if (op.equals("in") || op.equals("notIn") || op.equals("all")) {
+            List<?> expectedValues = 
ConditionContextHelper.foldToASCII((List<?>) 
condition.getParameter("propertyValues"));
+            List<?> expectedValuesInteger = (List<?>) 
condition.getParameter("propertyValuesInteger");
+            List<?> expectedValuesDate = (List<?>) 
condition.getParameter("propertyValuesDate");
+            List<?> expectedValuesDateExpr = (List<?>) 
condition.getParameter("propertyValuesDateExpr");
+
+            return compareMultivalue(actualValue, expectedValues, 
expectedValuesDate, expectedValuesInteger, expectedValuesDateExpr, op);
+        } else if(op.equals("isDay") && expectedValueDate != null) {
+            return 
yearMonthDayDateFormat.format(getDate(actualValue)).equals(yearMonthDayDateFormat.format(getDate(expectedValueDate)));
+        } else if(op.equals("isNotDay") && expectedValueDate != null) {
+            return 
!yearMonthDayDateFormat.format(getDate(actualValue)).equals(yearMonthDayDateFormat.format(getDate(expectedValueDate)));
+        }
+        
+        return false;
+    }
+
+    private Object getPropertyValue(Item item, String expression) throws 
Exception {
+        ExpressionAccessor accessor = getPropertyAccessor(item, expression);
+        return accessor != null ? accessor.get((OgnlContext) 
Ognl.createDefaultContext(null), item) : null;
+    }
+
+    private ExpressionAccessor getPropertyAccessor(Item item, String 
expression) throws Exception {
+        ExpressionAccessor accessor = null;
+        String clazz = item.getClass().getName();
+        Map<String, ExpressionAccessor> expressions = 
expressionCache.get(clazz);
+        if (expressions == null) {
+            expressions = new HashMap<>();
+            expressionCache.put(clazz, expressions);
+        } else {
+            accessor = expressions.get(expression);
+        }
+        if (accessor == null) {
+            long time = System.nanoTime();
+            Thread current = Thread.currentThread();
+            ClassLoader contextCL = current.getContextClassLoader();
+            try {
+                
current.setContextClassLoader(PropertyConditionEvaluator.class.getClassLoader());
+                Node node = Ognl.compileExpression((OgnlContext) 
Ognl.createDefaultContext(null), item, expression);
+                accessor = node.getAccessor();
+            } finally {
+                current.setContextClassLoader(contextCL);
+            }
+            if (accessor != null) {
+                expressions.put(expression, accessor);
+            } else {
+                logger.warn("Unable to compile expression for {} and {}", 
clazz, expression);
+            }
+            time = System.nanoTime() - time;
+            logger.info("Expression compilation for {} took {}", expression, 
time / 1000000L);
+        }
+
+        return accessor;
+    }
+    
+    private Date getDate(Object value) {
+        if (value == null) {
+            return null;
+        }
+        if (value instanceof Date) {
+            return ((Date) value);
+        } else {
+            DateMathParser parser = new 
DateMathParser(DateFieldMapper.Defaults.DATE_TIME_FORMATTER, 
TimeUnit.MILLISECONDS);
+            try {
+                return new Date(parser.parse(value.toString(), new 
Callable<Long>() {
+                    @Override
+                    public Long call() throws Exception {
+                        return System.currentTimeMillis();
+                    }
+                }));
+            } catch (ElasticsearchParseException e) {
+                logger.warn("unable to parse date " + value.toString(), e);
+            }
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Object> getValueSet(Object expectedValue) {
+        if (expectedValue instanceof List) {
+            return (List<Object>) expectedValue;
+        } else if (expectedValue instanceof Collection) {
+            return new ArrayList<Object>((Collection<?>) expectedValue);
+        } else {
+            return Collections.singletonList(expectedValue);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java
new file mode 100644
index 0000000..68e5944
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java
@@ -0,0 +1,54 @@
+/*
+ * 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.conditions.Condition;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class SourceEventPropertyConditionESQueryBuilder implements 
ConditionESQueryBuilder {
+
+    public SourceEventPropertyConditionESQueryBuilder() {
+    }
+
+    private void appendFilderIfPropExist(List<FilterBuilder> filterBuilders, 
Condition condition, String prop){
+        final Object parameter = condition.getParameter(prop);
+        if (parameter != null && !"".equals(parameter)) {
+            filterBuilders.add(FilterBuilders.termFilter("source." + prop, 
(String) parameter));
+        }
+    }
+
+    public FilterBuilder buildFilter(Condition condition, Map<String, Object> 
context, ConditionESQueryBuilderDispatcher dispatcher) {
+        List<FilterBuilder> l = new ArrayList<FilterBuilder>();
+        for (String prop : new String[]{"id", "path", "scope", "type"}){
+            appendFilderIfPropExist(l, condition, prop);
+        }
+
+        if (l.size() >= 1) {
+            return l.size() == 1 ? l.get(0) : 
FilterBuilders.andFilter(l.toArray(new FilterBuilder[l.size()]));
+        } else {
+            return null;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java
 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java
new file mode 100644
index 0000000..98669dd
--- /dev/null
+++ 
b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java
@@ -0,0 +1,80 @@
+/*
+ * 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.Item;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.conditions.ConditionType;
+import org.apache.unomi.api.services.DefinitionsService;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator;
+import 
org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SourceEventPropertyConditionEvaluator implements 
ConditionEvaluator {
+    private static final Map<String,String> MAPPED_PROPERTIES;
+    static {
+        MAPPED_PROPERTIES = new HashMap<>(4);
+        MAPPED_PROPERTIES.put("id", "itemId");
+        MAPPED_PROPERTIES.put("path", "properties.pageInfo.pagePath");
+        MAPPED_PROPERTIES.put("type", "itemType");
+        MAPPED_PROPERTIES.put("scope", "scope");
+    }
+
+    private DefinitionsService definitionsService;
+
+    private void appendConditionIfPropExist(List<Condition> conditions, 
Condition condition, String prop, ConditionType propConditionType) {
+        final Object parameter = condition.getParameter(prop);
+        if (parameter != null && !"".equals(parameter)) {
+            Condition propCondition = new Condition(propConditionType);
+            propCondition.setParameter("comparisonOperator", "equals");
+            
propCondition.setParameter("propertyName",MAPPED_PROPERTIES.get(prop));
+            propCondition.setParameter("propertyValue", parameter);
+            conditions.add(propCondition);
+        }
+    }
+
+    @Override
+    public boolean eval(Condition condition, Item item, Map<String, Object> 
context, ConditionEvaluatorDispatcher dispatcher) {
+        Condition andCondition = new 
Condition(definitionsService.getConditionType("booleanCondition"));
+        andCondition.setParameter("operator", "and");
+        ArrayList<Condition> conditions = new ArrayList<Condition>();
+
+        for (String prop : MAPPED_PROPERTIES.keySet()){
+            appendConditionIfPropExist(conditions, condition, prop, 
definitionsService.getConditionType("eventPropertyCondition"));
+        }
+
+        if(conditions.size() > 0){
+            andCondition.setParameter("subConditions", conditions);
+            return dispatcher.eval(andCondition, item);
+        } else {
+            return true;
+        }
+    }
+
+    public DefinitionsService getDefinitionsService() {
+        return definitionsService;
+    }
+
+    public void setDefinitionsService(DefinitionsService definitionsService) {
+        this.definitionsService = definitionsService;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/plugins/baseplugin/src/main/java/org/oasis_open/contextserver/plugins/baseplugin/actions/AllEventToProfilePropertiesAction.java
----------------------------------------------------------------------
diff --git 
a/plugins/baseplugin/src/main/java/org/oasis_open/contextserver/plugins/baseplugin/actions/AllEventToProfilePropertiesAction.java
 
b/plugins/baseplugin/src/main/java/org/oasis_open/contextserver/plugins/baseplugin/actions/AllEventToProfilePropertiesAction.java
deleted file mode 100644
index d50c32d..0000000
--- 
a/plugins/baseplugin/src/main/java/org/oasis_open/contextserver/plugins/baseplugin/actions/AllEventToProfilePropertiesAction.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.oasis_open.contextserver.plugins.baseplugin.actions;
-
-import org.apache.commons.beanutils.BeanUtilsBean;
-import org.oasis_open.contextserver.api.Event;
-import org.oasis_open.contextserver.api.actions.Action;
-import org.oasis_open.contextserver.api.actions.ActionExecutor;
-import org.oasis_open.contextserver.api.services.EventService;
-import org.oasis_open.contextserver.api.services.ProfileService;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class AllEventToProfilePropertiesAction implements ActionExecutor {
-
-    private ProfileService profileService;
-
-    public void setProfileService(ProfileService profileService) {
-        this.profileService = profileService;
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public int execute(Action action, Event event) {
-        boolean changed = false;
-        Map<String, Object> properties = new HashMap<String,Object>();
-        if (event.getProperties() != null) {
-            properties.putAll(event.getProperties());
-        }
-
-
-        try {
-            Object targetProperties = 
BeanUtilsBean.getInstance().getPropertyUtils().getProperty(event.getTarget(), 
"properties");
-            if (targetProperties instanceof Map) {
-                properties.putAll( (Map)targetProperties );
-            }
-        } catch (Exception e) {
-            // Ignore
-        }
-        for (Map.Entry<String, Object> entry : properties.entrySet()) {
-            if (event.getProfile().getProperty(entry.getKey()) == null || 
!event.getProfile().getProperty(entry.getKey()).equals(event.getProperty(entry.getKey())))
 {
-                String propertyMapping = 
profileService.getPropertyTypeMapping(entry.getKey());
-                if (propertyMapping != null) {
-                    event.getProfile().setProperty(propertyMapping, 
entry.getValue());
-                } else {
-                    event.getProfile().setProperty(entry.getKey(), 
entry.getValue());
-                }
-                changed = true;
-            }
-        }
-        return changed ? EventService.PROFILE_UPDATED : EventService.NO_CHANGE;
-    }
-}


Reply via email to