http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/ProfileServiceEndPoint.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/ProfileServiceEndPoint.java
 
b/rest/src/main/java/org/oasis_open/contextserver/rest/ProfileServiceEndPoint.java
deleted file mode 100644
index bad5737..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/ProfileServiceEndPoint.java
+++ /dev/null
@@ -1,507 +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.rest;
-
-import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.oasis_open.contextserver.api.*;
-import org.oasis_open.contextserver.api.conditions.Condition;
-import org.oasis_open.contextserver.api.query.Query;
-import org.oasis_open.contextserver.api.services.EventService;
-import org.oasis_open.contextserver.api.services.ProfileService;
-import org.oasis_open.contextserver.api.services.SegmentService;
-import org.oasis_open.contextserver.persistence.spi.CustomObjectMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-import javax.ws.rs.*;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-/**
- * A JAX-RS endpoint to manage {@link Profile}s and {@link Persona}s.
- */
-@WebService
-@Produces(MediaType.APPLICATION_JSON)
-@CrossOriginResourceSharing(
-        allowAllOrigins = true,
-        allowCredentials = true
-)
-public class ProfileServiceEndPoint {
-
-    private static final Logger logger = 
LoggerFactory.getLogger(ProfileServiceEndPoint.class.getName());
-
-    private ProfileService profileService;
-
-    private EventService eventService;
-
-    private SegmentService segmentService;
-
-    private LocalizationHelper localizationHelper;
-
-    public ProfileServiceEndPoint() {
-        System.out.println("Initializing profile service endpoint...");
-    }
-
-    @WebMethod(exclude = true)
-    public void setProfileService(ProfileService profileService) {
-        this.profileService = profileService;
-    }
-
-    @WebMethod(exclude = true)
-    public void setEventService(EventService eventService) {
-        this.eventService = eventService;
-    }
-
-    @WebMethod(exclude = true)
-    public void setSegmentService(SegmentService segmentService) {
-        this.segmentService = segmentService;
-    }
-
-    @WebMethod(exclude = true)
-    public void setLocalizationHelper(LocalizationHelper localizationHelper) {
-        this.localizationHelper = localizationHelper;
-    }
-
-    /**
-     * Retrieves the number of unique profiles.
-     *
-     * @return the number of unique profiles.
-     */
-    @GET
-    @Path("/count")
-    public long getAllProfilesCount() {
-        return profileService.getAllProfilesCount();
-    }
-
-    /**
-     * Retrieves profiles matching the specified query.
-     *
-     * @param query a {@link Query} specifying which elements to retrieve
-     * @return a {@link PartialList} of profiles instances matching the 
specified query
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/search")
-    public PartialList<Profile> getProfiles(Query query) {
-        return profileService.search(query, Profile.class);
-    }
-
-    /**
-     * Retrieves an export of profiles matching the specified query as a 
downloadable file using the comma-separated values (CSV) format.
-     *
-     * @param query a String JSON representation of the query the profiles to 
export should match
-     * @return a Response object configured to allow caller to download the 
CSV export file
-     */
-    @GET
-    @Path("/export")
-    @Produces("text/csv")
-    public Response getExportProfiles(@QueryParam("query") String query) {
-        try {
-            Query queryObject = 
CustomObjectMapper.getObjectMapper().readValue(query, Query.class);
-            Response.ResponseBuilder response = 
Response.ok(profileService.exportProfilesPropertiesToCsv(queryObject));
-            response.header("Content-Disposition",
-                    "attachment; filename=Profiles_export_" + new 
SimpleDateFormat("yyyy-MM-dd-HH-mm").format(new Date()) + ".csv");
-            return response.build();
-        } catch (IOException e) {
-            logger.error(e.getMessage(), e);
-            return Response.serverError().build();
-        }
-    }
-
-    /**
-     * A version of {@link #getExportProfiles(String)} suitable to be called 
from an HTML form.
-     *
-     * @param query a form-encoded representation of the query the profiles to 
export should match
-     * @return a Response object configured to allow caller to download the 
CSV export file
-     */
-    @GET
-    @Path("/export")
-    @Produces("text/csv")
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response formExportProfiles(@FormParam("query") String query) {
-        try {
-            Query queryObject = 
CustomObjectMapper.getObjectMapper().readValue(query, Query.class);
-            Response.ResponseBuilder response = 
Response.ok(profileService.exportProfilesPropertiesToCsv(queryObject));
-            response.header("Content-Disposition",
-                    "attachment; filename=Profiles_export_" + new 
SimpleDateFormat("yyyy-MM-dd-HH-mm").format(new Date()) + ".csv");
-            return response.build();
-        } catch (IOException e) {
-            logger.error(e.getMessage(), e);
-            return Response.serverError().build();
-        }
-    }
-
-    /**
-     * Update all profiles in batch according to the specified {@link 
BatchUpdate}
-     *
-     * @param update the batch update specification
-     */
-    @POST
-    @Path("/batchProfilesUpdate")
-    public void batchProfilesUpdate(BatchUpdate update) {
-        profileService.batchProfilesUpdate(update);
-    }
-
-    /**
-     * Retrieves the profile identified by the specified identifier.
-     *
-     * @param profileId the identifier of the profile to retrieve
-     * @return the profile identified by the specified identifier or {@code 
null} if no such profile exists
-     */
-    @GET
-    @Path("/{profileId}")
-    public Profile load(@PathParam("profileId") String profileId) {
-        return profileService.load(profileId);
-    }
-
-    /**
-     * Saves the specified profile in the context server, sending a {@code 
profileUpdated} event.
-     *
-     * @param profile the profile to be saved
-     * @return the newly saved profile
-     */
-    @POST
-    @Path("/")
-    public Profile save(Profile profile) {
-        // TODO: check that the profile was actually updated correctly before 
sending the event
-        Event profileUpdated = new Event("profileUpdated", null, profile, 
null, null, profile, new Date());
-        profileUpdated.setPersistent(false);
-        eventService.send(profileUpdated);
-        return profileService.save(profile);
-    }
-
-    /**
-     * Removes the profile (or persona if the {@code persona} query parameter 
is set to {@code true}) identified by the specified identifier.
-     *
-     * @param profileId the identifier of the profile or persona to delete
-     * @param persona   {@code true} if the specified identifier is supposed 
to refer to a persona, {@code false} if it is supposed to refer to a profile
-     */
-    @DELETE
-    @Path("/{profileId}")
-    public void delete(@PathParam("profileId") String profileId, 
@QueryParam("persona") @DefaultValue("false") boolean persona) {
-        profileService.delete(profileId, false);
-    }
-
-    /**
-     * Retrieves the sessions associated with the profile identified by the 
specified identifier that match the specified query (if specified), ordered 
according to the specified
-     * {@code sortBy} String and and paged: only {@code size} of them are 
retrieved, starting with the {@code offset}-th one.
-     *
-     * TODO: use a Query object instead of distinct parameter?
-     *
-     * @param profileId the identifier of the profile we want to retrieve 
sessions from
-     * @param query     a String of text used for fulltext filtering which 
sessions we are interested in or {@code null} (or an empty String) if we want 
to retrieve all sessions
-     * @param offset    zero or a positive integer specifying the position of 
the first session in the total ordered collection of matching sessions
-     * @param size      a positive integer specifying how many matching 
sessions should be retrieved or {@code -1} if all of them should be retrieved
-     * @param sortBy    an optional ({@code null} if no sorting is required) 
String of comma ({@code ,}) separated property names on which ordering should 
be performed, ordering
-     *                  elements according to the property order in the
-     *                  String, considering each in turn and moving on to the 
next one in case of equality of all preceding ones. Each property name is 
optionally followed by
-     *                  a column ({@code :}) and an order specifier: {@code 
asc} or {@code desc}.
-     * @return a {@link PartialList} of matching sessions
-     */
-    @GET
-    @Path("/{profileId}/sessions")
-    public PartialList<Session> getProfileSessions(@PathParam("profileId") 
String profileId,
-                                                   @QueryParam("q") String 
query,
-                                                   @QueryParam("offset") 
@DefaultValue("0") int offset,
-                                                   @QueryParam("size") 
@DefaultValue("50") int size,
-                                                   @QueryParam("sort") String 
sortBy) {
-        return profileService.getProfileSessions(profileId, query, offset, 
size, sortBy);
-    }
-
-    /**
-     * Retrieves the list of segment metadata for the segments the specified 
profile is a member of.
-     *
-     * @param profileId the identifier of the profile for which we want to 
retrieve the segment metadata
-     * @return the (possibly empty) list of segment metadata for the segments 
the specified profile is a member of
-     */
-    @GET
-    @Path("/{profileId}/segments")
-    public List<Metadata> getProfileSegments(@PathParam("profileId") String 
profileId) {
-        Profile profile = profileService.load(profileId);
-        return segmentService.getSegmentMetadatasForProfile(profile);
-    }
-
-    /**
-     * TODO
-     *
-     * @param fromPropertyTypeId
-     * @return
-     */
-    @GET
-    @Path("/properties/mappings/{fromPropertyTypeId}")
-    public String getPropertyTypeMapping(@PathParam("fromPropertyTypeId") 
String fromPropertyTypeId) {
-        return profileService.getPropertyTypeMapping(fromPropertyTypeId);
-    }
-
-    /**
-     * Retrieves {@link Persona} matching the specified query.
-     *
-     * @param query a {@link Query} specifying which elements to retrieve
-     * @return a {@link PartialList} of Persona instances matching the 
specified query
-     */
-    @POST
-    @Path("/personas/search")
-    public PartialList<Persona> getPersonas(Query query) {
-        return profileService.search(query, Persona.class);
-    }
-
-    /**
-     * Retrieves the {@link Persona} identified by the specified identifier.
-     *
-     * @param personaId the identifier of the persona to retrieve
-     * @return the persona identified by the specified identifier or {@code 
null} if no such persona exists
-     */
-    @GET
-    @Path("/personas/{personaId}")
-    public Persona loadPersona(@PathParam("personaId") String personaId) {
-        return profileService.loadPersona(personaId);
-    }
-
-    /**
-     * Retrieves the persona identified by the specified identifier and all 
its associated sessions
-     *
-     * @param personaId the identifier of the persona to retrieve
-     * @return a {@link PersonaWithSessions} instance with the persona 
identified by the specified identifier and all its associated sessions
-     */
-    @GET
-    @Path("/personasWithSessions/{personaId}")
-    public PersonaWithSessions loadPersonaWithSessions(@PathParam("personaId") 
String personaId) {
-        return profileService.loadPersonaWithSessions(personaId);
-    }
-
-    /**
-     * Persists the specified {@link Persona} in the context server.
-     *
-     * @param persona the persona to persist
-     * @return the newly persisted persona
-     */
-    @POST
-    @Path("/personas")
-    public Persona savePersona(Persona persona) {
-        return profileService.savePersona(persona);
-    }
-
-    /**
-     * Removes the persona identified by the specified identifier.
-     *
-     * @param personaId the identifier of the persona to delete
-     */
-    @DELETE
-    @Path("/personas/{personaId}")
-    public void deletePersona(@PathParam("personaId") String personaId) {
-        profileService.delete(personaId, true);
-    }
-
-    /**
-     * Creates a persona with the specified identifier and automatically 
creates an associated session with it.
-     *
-     * @param personaId the identifier to use for the new persona
-     * @return the newly created persona
-     */
-    @PUT
-    @Path("/personas/{personaId}")
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Persona createPersona(@PathParam("personaId") String personaId) {
-        return profileService.createPersona(personaId);
-    }
-
-    /**
-     * Retrieves the sessions associated with the persona identified by the 
specified identifier, ordered according to the specified {@code sortBy} String 
and and paged: only
-     * {@code size} of them are retrieved, starting with the {@code offset}-th 
one.
-     *
-     * @param personaId the persona id
-     * @param offset    zero or a positive integer specifying the position of 
the first session in the total ordered collection of matching sessions
-     * @param size      a positive integer specifying how many matching 
sessions should be retrieved or {@code -1} if all of them should be retrieved
-     * @param sortBy    an optional ({@code null} if no sorting is required) 
String of comma ({@code ,}) separated property names on which ordering should 
be performed, ordering
-     *                  elements according to the property order in the
-     *                  String, considering each in turn and moving on to the 
next one in case of equality of all preceding ones. Each property name is 
optionally followed by
-     *                  a column ({@code :}) and an order specifier: {@code 
asc} or {@code desc}.
-     * @return a {@link PartialList} of sessions for the persona identified by 
the specified identifier
-     */
-    @GET
-    @Path("/personas/{personaId}/sessions")
-    public PartialList<Session> getPersonaSessions(@PathParam("personaId") 
String personaId,
-                                                   @QueryParam("offset") 
@DefaultValue("0") int offset,
-                                                   @QueryParam("size") 
@DefaultValue("50") int size,
-                                                   @QueryParam("sort") String 
sortBy) {
-        return profileService.getPersonaSessions(personaId, offset, size, 
sortBy);
-    }
-
-    /**
-     * Retrieves the session identified by the specified identifier.
-     *
-     * @param sessionId the identifier of the session to be retrieved
-     * @param dateHint  a Date helping in identifying where the item is located
-     * @return the session identified by the specified identifier
-     */
-    @GET
-    @Path("/sessions/{sessionId}")
-    public Session loadSession(@PathParam("sessionId") String sessionId, 
@QueryParam("dateHint") String dateHint) throws ParseException {
-        return profileService.loadSession(sessionId, dateHint != null ? new 
SimpleDateFormat("yyyy-MM").parse(dateHint) : null);
-    }
-
-    /**
-     * Saves the specified session.
-     *
-     * @param session the session to be saved
-     * @return the newly saved session
-     */
-    @POST
-    @Path("/sessions/{sessionId}")
-    public Session saveSession(Session session) {
-        return profileService.saveSession(session);
-    }
-
-    /**
-     * Retrieves {@link Event}s for the {@link 
org.oasis_open.contextserver.api.Session} identified by the provided session 
identifier, matching any of the provided event types,
-     * ordered according to the specified {@code sortBy} String and paged: 
only {@code size} of them are retrieved, starting with the {@code offset}-th 
one.
-     * If a {@code query} is provided, a full text search is performed on the 
matching events to further filter them.
-     *
-     * @param sessionId  the identifier of the user session we're considering
-     * @param eventTypes an array of event type names; the events to retrieve 
should at least match one of these
-     * @param query      a String to perform full text filtering on events 
matching the other conditions
-     * @param offset     zero or a positive integer specifying the position of 
the first event in the total ordered collection of matching events
-     * @param size       a positive integer specifying how many matching 
events should be retrieved or {@code -1} if all of them should be retrieved
-     * @param sortBy     an optional ({@code null} if no sorting is required) 
String of comma ({@code ,}) separated property names on which ordering should 
be performed, ordering
-     *                   elements according to the property order in
-     *                   the String, considering each in turn and moving on to 
the next one in case of equality of all preceding ones. Each property name is 
optionally followed by
-     *                   a column ({@code :}) and an order specifier: {@code 
asc} or {@code desc}.
-     * @return a {@link PartialList} of matching events
-     */
-    @GET
-    @Path("/sessions/{sessionId}/events")
-    public PartialList<Event> getSessionEvents(@PathParam("sessionId") String 
sessionId,
-                                               @QueryParam("eventTypes") 
String[] eventTypes,
-                                               @QueryParam("q") String query,
-                                               @QueryParam("offset") 
@DefaultValue("0") int offset,
-                                               @QueryParam("size") 
@DefaultValue("50") int size,
-                                               @QueryParam("sort") String 
sortBy) {
-        return eventService.searchEvents(sessionId, eventTypes, query, offset, 
size, sortBy);
-    }
-
-    @WebMethod(exclude = true)
-    public PartialList<Session> findProfileSessions(String profileId) {
-        return null;
-    }
-
-    @WebMethod(exclude = true)
-    public boolean matchCondition(Condition condition, Profile profile, 
Session session) {
-        return profileService.matchCondition(condition, profile, session);
-    }
-
-    /**
-     * Retrieves the existing property types for the specified type as defined 
by the Item subclass public field {@code ITEM_TYPE} and with the specified tag.
-     *
-     * TODO: move to a different class
-     *
-     * @param tagId    the tag we're interested in
-     * @param itemType the String representation of the item type we want to 
retrieve the count of, as defined by its class' {@code ITEM_TYPE} field
-     * @return all property types defined for the specified item type and with 
the specified tag
-     */
-    @GET
-    @Path("/existingProperties")
-    public Collection<PropertyType> getExistingProperties(@QueryParam("tagId") 
String tagId, @QueryParam("itemType") String itemType, 
@HeaderParam("Accept-Language") String language) {
-        Set<PropertyType> properties = 
profileService.getExistingProperties(tagId, itemType);
-        return properties;
-    }
-
-    /**
-     * Retrieves all known property types.
-     *
-     * TODO: move to a different class
-     *
-     * @param language TODO unused
-     * @return a Map associating targets as keys to related {@link 
PropertyType}s
-     */
-    @GET
-    @Path("/properties")
-    public Map<String, Collection<PropertyType>> 
getPropertyTypes(@HeaderParam("Accept-Language") String language) {
-        return profileService.getAllPropertyTypes();
-    }
-
-    /**
-     * Retrieves all the property types associated with the specified target.
-     *
-     * TODO: move to a different class
-     *
-     * @param target   the target for which we want to retrieve the associated 
property types
-     * @param language TODO unused
-     * @return a collection of all the property types associated with the 
specified target
-     */
-    @GET
-    @Path("/properties/{target}")
-    public Collection<PropertyType> 
getPropertyTypesByTarget(@PathParam("target") String target, 
@HeaderParam("Accept-Language") String language) {
-        return profileService.getAllPropertyTypes(target);
-    }
-
-    /**
-     * Retrieves all property types with the specified tags also retrieving 
property types with sub-tags of the specified tags if so specified.
-     *
-     * TODO: move to a different class
-     * TODO: passing a list of tags via a comma-separated list is not very 
RESTful
-     *
-     * @param tags      a comma-separated list of tag identifiers
-     * @param recursive {@code true} if sub-tags of the specified tag should 
also be considered, {@code false} otherwise
-     * @return a Set of the property types with the specified tag
-     */
-    @GET
-    @Path("/properties/tags/{tagId}")
-    public Collection<PropertyType> getPropertyTypeByTag(@PathParam("tagId") 
String tags, @QueryParam("recursive") @DefaultValue("false") boolean recursive, 
@HeaderParam("Accept-Language") String language) {
-        String[] tagsArray = tags.split(",");
-        Set<PropertyType> results = new LinkedHashSet<>();
-        for (String s : tagsArray) {
-            results.addAll(profileService.getPropertyTypeByTag(s, recursive));
-        }
-        return results;
-    }
-
-    /**
-     * Persists the specified property type in the context server.
-     *
-     * TODO: move to a different class
-     *
-     * @param property the property type to persist
-     * @return {@code true} if the property type was properly created, {@code 
false} otherwise (for example, if the property type already existed
-     */
-    @POST
-    @Path("/properties")
-    public boolean createPropertyType(PropertyType property) {
-        return profileService.createPropertyType(property);
-    }
-
-    /**
-     * Deletes the property type identified by the specified identifier.
-     *
-     * TODO: move to a different class
-     *
-     * @param propertyId the identifier of the property type to delete
-     * @return {@code true} if the property type was properly deleted, {@code 
false} otherwise
-     */
-    @DELETE
-    @Path("/properties/{propertyId}")
-    public boolean deleteProperty(@PathParam("propertyId") String propertyId) {
-        return profileService.deletePropertyType(propertyId);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/QueryServiceEndPoint.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/QueryServiceEndPoint.java
 
b/rest/src/main/java/org/oasis_open/contextserver/rest/QueryServiceEndPoint.java
deleted file mode 100644
index 75bce9e..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/QueryServiceEndPoint.java
+++ /dev/null
@@ -1,143 +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.rest;
-
-import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.oasis_open.contextserver.api.Item;
-import org.oasis_open.contextserver.api.conditions.Condition;
-import org.oasis_open.contextserver.api.query.AggregateQuery;
-import org.oasis_open.contextserver.api.services.QueryService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.*;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.Map;
-
-/**
- * A JAX-RS endpoint to perform queries against context-server data.
- */
-@WebService
-@Produces(MediaType.APPLICATION_JSON)
-@CrossOriginResourceSharing(
-        allowAllOrigins = true,
-        allowCredentials = true
-)
-public class QueryServiceEndPoint {
-    private static final Logger logger = 
LoggerFactory.getLogger(QueryServiceEndPoint.class.getName());
-
-    private QueryService queryService;
-
-    private LocalizationHelper localizationHelper;
-
-    @WebMethod(exclude = true)
-    public void setQueryService(QueryService queryService) {
-        this.queryService = queryService;
-    }
-
-
-    @WebMethod(exclude = true)
-    public void setLocalizationHelper(LocalizationHelper localizationHelper) {
-        this.localizationHelper = localizationHelper;
-    }
-
-    /**
-     * Retrieves the number of items with the specified type as defined by the 
Item subclass public field {@code ITEM_TYPE} and aggregated by possible values 
of the specified
-     * property.
-     *
-     * @param type     the String representation of the item type we want to 
retrieve the count of, as defined by its class' {@code ITEM_TYPE} field
-     * @param property the property we're aggregating on, i.e. for each 
possible value of this property, we are counting how many items of the 
specified type have that value
-     * @return a Map associating a specific value of the property to the 
cardinality of items with that value
-     * @see Item Item for a discussion of {@code ITEM_TYPE}
-     */
-    @GET
-    @Path("/{type}/{property}")
-    public Map<String, Long> getAggregate(@PathParam("type") String type, 
@PathParam("property") String property) {
-        return queryService.getAggregate(type, property);
-    }
-
-    /**
-     * TODO: rework, this method is confusing since it either behaves like 
{@link #getAggregate(String, String)} if query is null but completely 
differently if it isn't
-     *
-     * Retrieves the number of items with the specified type as defined by the 
Item subclass public field {@code ITEM_TYPE} and aggregated by possible values 
of the specified
-     * property or, if the specified query is not {@code null}, perform that 
aggregate query.
-     *
-     * @param type           the String representation of the item type we 
want to retrieve the count of, as defined by its class' {@code ITEM_TYPE} field
-     * @param property       the property we're aggregating on, i.e. for each 
possible value of this property, we are counting how many items of the 
specified type have that value
-     * @param aggregateQuery the {@link AggregateQuery} specifying the 
aggregation that should be perfomed
-     * @return a Map associating a specific value of the property to the 
cardinality of items with that value
-     * @see Item Item for a discussion of {@code ITEM_TYPE}
-     */
-    @POST
-    @Path("/{type}/{property}")
-    public Map<String, Long> getAggregate(@PathParam("type") String type, 
@PathParam("property") String property, AggregateQuery aggregateQuery) {
-        return queryService.getAggregate(type, property, aggregateQuery);
-    }
-
-    /**
-     * Retrieves the specified metrics for the specified field of items of the 
specified type as defined by the Item subclass public field {@code ITEM_TYPE} 
and matching the
-     * specified {@link Condition}.
-     *
-     * @param condition   the condition the items must satisfy
-     * @param metricsType a String specifying which metrics should be 
computed, separated by a slash ({@code /}) (possible values: {@code sum} for 
the sum of the
-     *                    values, {@code avg} for the average of the values, 
{@code min} for the minimum value and {@code max} for the maximum value)
-     * @param property    the name of the field for which the metrics should 
be computed
-     * @param type        the String representation of the item type we want 
to retrieve the count of, as defined by its class' {@code ITEM_TYPE} field
-     * @return a Map associating computed metric name as key to its associated 
value
-     * @see Item Item for a discussion of {@code ITEM_TYPE}
-     */
-    @POST
-    @Path("/{type}/{property}/{metricTypes:((sum|avg|min|max)/?)*}")
-    public Map<String, Double> getMetric(@PathParam("type") String type, 
@PathParam("property") String property, @PathParam("metricTypes") String 
metricsType, Condition condition) {
-        return queryService.getMetric(type, property, metricsType, condition);
-    }
-
-    /**
-     * Retrieves the number of items of the specified type as defined by the 
Item subclass public field {@code ITEM_TYPE} and matching the specified {@link 
Condition}.
-     *
-     * @param condition the condition the items must satisfy
-     * @param validate optional parameter, in case of draft condition that 
have missing required parameters an IllegalArgumentException is throw
-     *                 and this end point will return status code 400, to 
avoid that you can set validate to false.
-     * @param type      the String representation of the item type we want to 
retrieve the count of, as defined by its class' {@code ITEM_TYPE} field
-     * @param response  the httpServletResponse
-     * @return the number of items of the specified type.
-     *         0 and status code 400 in case of IllegalArgumentException (bad 
condition) and validate null or true
-     *         0 and status code 200 in case of IllegalArgumentException (bad 
condition) and validate false
-     * @see Item Item for a discussion of {@code ITEM_TYPE}
-     */
-    @POST
-    @Path("/{type}/count")
-    public long getQueryCount(@PathParam("type") String type, 
@QueryParam("validate") Boolean validate, Condition condition,  @Context final 
HttpServletResponse response) {
-        long count = 0;
-        try {
-            count = queryService.getQueryCount(type, condition);
-        } catch (IllegalArgumentException e) {
-            if(validate == null || validate) {
-                logger.error(e.getMessage(), e);
-                
response.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
-            }
-        }
-        return count;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/RESTActionType.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTActionType.java 
b/rest/src/main/java/org/oasis_open/contextserver/rest/RESTActionType.java
deleted file mode 100644
index d0b6410..0000000
--- a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTActionType.java
+++ /dev/null
@@ -1,72 +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.rest;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * A representation of an {@link 
org.oasis_open.contextserver.api.actions.ActionType} better suited for 
definitions.
- */
-public class RESTActionType {
-    private String id;
-    private String name;
-    private String description;
-    private Collection<String> tags;
-    private List<RESTParameter> parameters;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Collection<String> getTags() {
-        return tags;
-    }
-
-    public void setTags(Collection<String> tags) {
-        this.tags = tags;
-    }
-
-    public List<RESTParameter> getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(List<RESTParameter> parameters) {
-        this.parameters = parameters;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/RESTConditionType.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTConditionType.java 
b/rest/src/main/java/org/oasis_open/contextserver/rest/RESTConditionType.java
deleted file mode 100644
index f8c9f87..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTConditionType.java
+++ /dev/null
@@ -1,77 +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.rest;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.TreeSet;
-
-/**
- * A representation of a {@link 
org.oasis_open.contextserver.api.conditions.ConditionType} better suited for 
definitions.
- */
-public class RESTConditionType {
-    private String id;
-    private String name;
-    private String description;
-    private Collection<String> tags = new TreeSet<String>();
-    private List<RESTParameter> parameters = new ArrayList<RESTParameter>();
-
-    public RESTConditionType() {
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Collection<String> getTags() {
-        return tags;
-    }
-
-    public void setTags(Collection<String> tags) {
-        this.tags = tags;
-    }
-
-    public List<RESTParameter> getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(List<RESTParameter> parameters) {
-        this.parameters = parameters;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/RESTParameter.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTParameter.java 
b/rest/src/main/java/org/oasis_open/contextserver/rest/RESTParameter.java
deleted file mode 100644
index 09be8bd..0000000
--- a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTParameter.java
+++ /dev/null
@@ -1,75 +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.rest;
-
-import 
org.oasis_open.contextserver.api.conditions.initializers.ChoiceListValue;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A representation of a {@link org.oasis_open.contextserver.api.Parameter} 
better suited for definitions.
- */
-public class RESTParameter {
-    private String id;
-    private String type;
-    private boolean multivalued = false;
-    private String defaultValue = null;
-    private List<ChoiceListValue> choiceListValues = new 
ArrayList<ChoiceListValue>();
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public boolean isMultivalued() {
-        return multivalued;
-    }
-
-    public void setMultivalued(boolean multivalued) {
-        this.multivalued = multivalued;
-    }
-
-    public String getDefaultValue() {
-        return defaultValue;
-    }
-
-    public void setDefaultValue(String defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    public List<ChoiceListValue> getChoiceListValues() {
-        return choiceListValues;
-    }
-
-    public void setChoiceListValues(List<ChoiceListValue> choiceListValues) {
-        this.choiceListValues = choiceListValues;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/RESTTag.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTTag.java 
b/rest/src/main/java/org/oasis_open/contextserver/rest/RESTTag.java
deleted file mode 100644
index c47c679..0000000
--- a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTTag.java
+++ /dev/null
@@ -1,82 +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.rest;
-
-import java.util.Collection;
-import java.util.TreeSet;
-
-/**
- * A representation of a {@link org.oasis_open.contextserver.api.Tag} better 
suited for definitions.
- */
-public class RESTTag {
-    private String id;
-    private String name;
-    private String description;
-    private String parentId;
-    private double rank = 0.0;
-    private Collection<RESTTag> subTags = new TreeSet<RESTTag>();
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getParentId() {
-        return parentId;
-    }
-
-    public void setParentId(String parentId) {
-        this.parentId = parentId;
-    }
-
-    public double getRank() {
-        return rank;
-    }
-
-    public void setRank(double rank) {
-        this.rank = rank;
-    }
-
-    public Collection<RESTTag> getSubTags() {
-        return subTags;
-    }
-
-    public void setSubTags(Collection<RESTTag> subTags) {
-        this.subTags = subTags;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/RESTValueType.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTValueType.java 
b/rest/src/main/java/org/oasis_open/contextserver/rest/RESTValueType.java
deleted file mode 100644
index c7aec52..0000000
--- a/rest/src/main/java/org/oasis_open/contextserver/rest/RESTValueType.java
+++ /dev/null
@@ -1,66 +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.rest;
-
-import java.util.Collection;
-
-/**
- * A representation of a {@link org.oasis_open.contextserver.api.ValueType} 
better suited for definitions.
- */
-public class RESTValueType {
-
-    private String id;
-    private String name;
-    private String description;
-    private Collection<RESTTag> tags;
-
-    public RESTValueType() {
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Collection<RESTTag> getTags() {
-        return tags;
-    }
-
-    public void setTags(Collection<RESTTag> tags) {
-        this.tags = tags;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/ResourceBundleHelper.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/ResourceBundleHelper.java
 
b/rest/src/main/java/org/oasis_open/contextserver/rest/ResourceBundleHelper.java
deleted file mode 100644
index 4375144..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/ResourceBundleHelper.java
+++ /dev/null
@@ -1,109 +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.rest;
-
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.regex.Pattern;
-
-import org.oasis_open.contextserver.api.PluginType;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleWiring;
-
-public class ResourceBundleHelper {
-
-    private static final Pattern COMMA = Pattern.compile(",", Pattern.LITERAL);
-
-    private static final String RESOURCE_BUNDLE = "messages";
-
-    private BundleContext bundleContext;
-
-    private ResourceBundle getBundle(String lang, Bundle bundle, ClassLoader 
loader) {
-        Locale locale = getLocale(lang);
-        try {
-            ResourceBundle resourceBundle = 
ResourceBundle.getBundle(RESOURCE_BUNDLE, locale, loader);
-            if (resourceBundle != null && 
locale.equals(resourceBundle.getLocale())) {
-                return resourceBundle;
-            }
-        } catch (MissingResourceException e) {
-            // continue with next language
-        }
-
-        if (locale.getCountry().length() > 0) {
-            // try the locale without the country
-            return getBundle(locale.getLanguage(), bundle, loader);
-        }
-
-        return null;
-    }
-
-    private Locale getLocale(String lang) {
-        int i = lang.indexOf(';');
-        if (i > -1) {
-            lang = lang.substring(0, i);
-        }
-        return Locale.forLanguageTag(lang);
-    }
-
-    public ResourceBundle getResourceBundle(PluginType object, String 
language) {
-        ResourceBundle resourceBundle = null;
-
-        Bundle bundle = bundleContext.getBundle(object.getPluginId());
-        ClassLoader loader = bundle.adapt(BundleWiring.class).getClassLoader();
-
-        if (language != null) {
-            if (language.indexOf(',') != -1) {
-                String[] langs = COMMA.split(language);
-                for (String lang : langs) {
-                    resourceBundle = getBundle(lang, bundle, loader);
-                    if (resourceBundle != null) {
-                        break;
-                    }
-                }
-            } else {
-                resourceBundle = getBundle(language, bundle, loader);
-            }
-        }
-        if (resourceBundle == null) {
-            try {
-                return ResourceBundle.getBundle(RESOURCE_BUNDLE, 
Locale.ENGLISH, loader);
-            } catch (MissingResourceException e) {
-                // ignore
-            }
-        }
-
-        return resourceBundle;
-    }
-
-    public String getResourceBundleValue(ResourceBundle bundle, String 
nameKey) {
-        try {
-            if (bundle != null) {
-                return bundle.getString(nameKey);
-            }
-        } catch (MissingResourceException e) {
-            // Continue
-        }
-        return "???" + nameKey + "???";
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/RulesServiceEndPoint.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RulesServiceEndPoint.java
 
b/rest/src/main/java/org/oasis_open/contextserver/rest/RulesServiceEndPoint.java
deleted file mode 100644
index 5f84f3d..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/RulesServiceEndPoint.java
+++ /dev/null
@@ -1,126 +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.rest;
-
-import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.oasis_open.contextserver.api.Metadata;
-import org.oasis_open.contextserver.api.PartialList;
-import org.oasis_open.contextserver.api.query.Query;
-import org.oasis_open.contextserver.api.rules.Rule;
-import org.oasis_open.contextserver.api.services.RulesService;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-import javax.ws.rs.*;
-import javax.ws.rs.core.MediaType;
-import java.util.Set;
-
-/**
- * A JAX-RS endpoint to manage {@link Rule}s.
- */
-@WebService
-@Produces(MediaType.APPLICATION_JSON)
-@CrossOriginResourceSharing(
-        allowAllOrigins = true,
-        allowCredentials = true
-)
-public class RulesServiceEndPoint {
-
-    private RulesService rulesService;
-
-    public RulesServiceEndPoint() {
-        System.out.println("Initializing rule service endpoint...");
-    }
-
-    @WebMethod(exclude=true)
-    public void setRulesService(RulesService rulesService) {
-        this.rulesService = rulesService;
-    }
-
-    /**
-     * Retrieves the metadata for all known rules.
-     *
-     * @return the Set of known metadata
-     */
-    @GET
-    @Path("/")
-    public Set<Metadata> getRuleMetadatas() {
-        return rulesService.getRuleMetadatas();
-    }
-
-    /**
-     * Persists the specified rule to the context server.
-     *
-     * @param rule the rule to be persisted
-     */
-    @POST
-    @Path("/")
-    public void setRule(Rule rule) {
-        rulesService.setRule(rule);
-    }
-
-    /**
-     * Retrieves rule metadatas for rules matching the specified {@link Query}.
-     *
-     * @param query the query the rules which metadata we want to retrieve 
must match
-     * @return a {@link PartialList} of rules metadata for the rules matching 
the specified query
-     */
-    @POST
-    @Path("/query")
-    public PartialList<Metadata> getRuleMetadatas(Query query) {
-        return rulesService.getRuleMetadatas(query);
-    }
-
-    /**
-     * Retrieves the rule identified by the specified identifier.
-     *
-     * @param ruleId the identifier of the rule we want to retrieve
-     * @return the rule identified by the specified identifier or {@code null} 
if no such rule exists.
-     */
-    @GET
-    @Path("/{ruleId}")
-    public Rule getRule( @PathParam("ruleId") String ruleId) {
-        return rulesService.getRule(ruleId);
-    }
-
-    /**
-     * Deletes the rule identified by the specified identifier.
-     *
-     * @param ruleId the identifier of the rule we want to delete
-     */
-    @DELETE
-    @Path("/{ruleId}")
-    public void removeRule(@PathParam("ruleId") String ruleId) {
-        rulesService.removeRule(ruleId);
-    }
-
-    /**
-     * TODO: remove
-     *
-     * @deprecated not needed anymore
-     */
-    @GET
-    @Path("/resetQueries")
-    public void resetQueries() {
-        for (Metadata metadata : rulesService.getRuleMetadatas()) {
-            Rule r = rulesService.getRule(metadata.getId());
-            rulesService.setRule(r);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/ScoringServiceEndPoint.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/ScoringServiceEndPoint.java
 
b/rest/src/main/java/org/oasis_open/contextserver/rest/ScoringServiceEndPoint.java
deleted file mode 100644
index 416c3a6..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/ScoringServiceEndPoint.java
+++ /dev/null
@@ -1,143 +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.rest;
-
-import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.oasis_open.contextserver.api.Item;
-import org.oasis_open.contextserver.api.Metadata;
-import org.oasis_open.contextserver.api.PartialList;
-import org.oasis_open.contextserver.api.query.Query;
-import org.oasis_open.contextserver.api.segments.Scoring;
-import org.oasis_open.contextserver.api.services.SegmentService;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-import javax.ws.rs.*;
-import javax.ws.rs.core.MediaType;
-import java.util.List;
-
-/**
- * A JAX-RS endpoint to manage {@link Scoring}s
- */
-@WebService
-@Produces(MediaType.APPLICATION_JSON)
-@CrossOriginResourceSharing(
-        allowAllOrigins = true,
-        allowCredentials = true
-)
-public class ScoringServiceEndPoint {
-
-    private SegmentService segmentService;
-
-    public ScoringServiceEndPoint() {
-        System.out.println("Initializing scoring service endpoint...");
-    }
-
-    @WebMethod(exclude = true)
-    public void setSegmentService(SegmentService segmentService) {
-        this.segmentService = segmentService;
-    }
-
-    /**
-     * Retrieves the set of all scoring metadata.
-     *
-     * @return the set of all scoring metadata
-     */
-    @GET
-    @Path("/")
-    public List<Metadata> getScoringMetadatas() {
-        return segmentService.getScoringMetadatas(0, 50, null).getList();
-    }
-
-    /**
-     * Retrieves the set of scoring metadata for scorings matching the 
specified query.
-     *
-     * @param query the query the scorings must match for their metadata to be 
retrieved
-     * @return the set of scoring metadata for scorings matching the specified 
query
-     */
-    @POST
-    @Path("/query")
-    public PartialList<Metadata> getScoringMetadatas(Query query) {
-        return segmentService.getScoringMetadatas(query);
-    }
-
-    /**
-     * Retrieves the scoring identified by the specified identifier.
-     *
-     * @param scoringId the identifier of the scoring to be retrieved
-     * @return the scoring identified by the specified identifier or {@code 
null} if no such scoring exists
-     */
-    @GET
-    @Path("/{scoringID}")
-    public Scoring getScoringDefinition(@PathParam("scoringID") String 
scoringId) {
-        return segmentService.getScoringDefinition(scoringId);
-    }
-
-    /**
-     * Persists the specified scoring in the context server.
-     *
-     * @param scoring the scoring to be persisted
-     */
-    @POST
-    @Path("/")
-    public void setScoringDefinition(Scoring scoring) {
-        segmentService.setScoringDefinition(scoring);
-    }
-
-    /**
-     * Creates a scoring with the specified scope, identifier, name and 
description from form-encoded data.
-     *
-     * @param scope              the scope for the new scoring
-     * @param scoringId          the identifier for the new scoring
-     * @param scoringName        the name of the new scoring
-     * @param scoringDescription the description of the new scoring
-     * @see Item Item's description for a discussion of scope
-     */
-    @PUT
-    @Path("/{scope}/{scoringID}")
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public void createScoringDefinition(@PathParam("scope") String scope, 
@PathParam("scoringID") String scoringId, @FormParam("scoringName") String 
scoringName, @FormParam("scoringDescription") String scoringDescription) {
-        segmentService.createScoringDefinition(scope, scoringId, scoringName, 
scoringDescription);
-    }
-
-    /**
-     * Deletes the scoring identified by the specified identifier from the 
context server.
-     *
-     * @param scoringId the identifier of the scoring to be deleted
-     */
-    @DELETE
-    @Path("/{scoringID}")
-    public void removeScoringDefinition(@PathParam("scoringID") String 
scoringId) {
-        segmentService.removeScoringDefinition(scoringId);
-    }
-
-    /**
-     * TODO: remove
-     *
-     * @deprecated not needed anymore
-     */
-    @GET
-    @Path("/resetQueries")
-    public void resetQueries() {
-        for (Metadata metadata : segmentService.getScoringMetadatas(0, 50, 
null).getList()) {
-            Scoring s = segmentService.getScoringDefinition(metadata.getId());
-            segmentService.setScoringDefinition(s);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/java/org/oasis_open/contextserver/rest/SegmentServiceEndPoint.java
----------------------------------------------------------------------
diff --git 
a/rest/src/main/java/org/oasis_open/contextserver/rest/SegmentServiceEndPoint.java
 
b/rest/src/main/java/org/oasis_open/contextserver/rest/SegmentServiceEndPoint.java
deleted file mode 100644
index 36f4216..0000000
--- 
a/rest/src/main/java/org/oasis_open/contextserver/rest/SegmentServiceEndPoint.java
+++ /dev/null
@@ -1,191 +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.rest;
-
-import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.oasis_open.contextserver.api.Metadata;
-import org.oasis_open.contextserver.api.PartialList;
-import org.oasis_open.contextserver.api.Profile;
-import org.oasis_open.contextserver.api.query.Query;
-import org.oasis_open.contextserver.api.segments.Segment;
-import org.oasis_open.contextserver.api.services.SegmentService;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-import javax.ws.rs.*;
-import javax.ws.rs.core.MediaType;
-import java.util.List;
-
-/**
- * A JAX-RS endpoint to manage {@link Segment}s.
- */
-@WebService
-@Produces(MediaType.APPLICATION_JSON)
-@CrossOriginResourceSharing(
-        allowAllOrigins = true,
-        allowCredentials = true
-)
-public class SegmentServiceEndPoint {
-
-    private SegmentService segmentService;
-
-    public SegmentServiceEndPoint() {
-        System.out.println("Initializing segment service endpoint...");
-    }
-
-    @WebMethod(exclude=true)
-    public void setSegmentService(SegmentService segmentService) {
-        this.segmentService = segmentService;
-    }
-
-    /**
-     * Retrieves a list of profiles matching the conditions defined by the 
segment identified by the specified identifier, ordered according to the 
specified {@code sortBy}
-     * String and and paged: only {@code size} of them are retrieved, starting 
with the {@code offset}-th one.
-     *
-     * @param segmentId the identifier of the segment for which we want to 
retrieve matching profiles
-     * @param offset    zero or a positive integer specifying the position of 
the first element in the total ordered collection of matching elements
-     * @param size      a positive integer specifying how many matching 
elements should be retrieved or {@code -1} if all of them should be retrieved
-     * @param sortBy    an optional ({@code null} if no sorting is required) 
String of comma ({@code ,}) separated property names on which ordering should 
be performed, ordering
-     *                  elements according to the property order in the
-     *                  String, considering each in turn and moving on to the 
next one in case of equality of all preceding ones. Each property name is 
optionally followed by
-     *                  a column ({@code :}) and an order specifier: {@code 
asc} or {@code desc}.
-     * @return a {@link PartialList} of profiles matching the specified segment
-     */
-    @GET
-    @Path("/{segmentID}/match")
-    public PartialList<Profile> getMatchingIndividuals(@PathParam("segmentID") 
String segmentId, @QueryParam("offset") @DefaultValue("0") int offset, 
@QueryParam("size") @DefaultValue("50") int size, @QueryParam("sort") String 
sortBy) {
-        return segmentService.getMatchingIndividuals(segmentId, offset, size, 
sortBy);
-    }
-
-    /**
-     * Retrieves the number of profiles matching the conditions defined by the 
segment identified by the specified identifier.
-     *
-     * @param segmentId the identifier of the segment for which we want to 
retrieve matching profiles
-     * @return the number of profiles matching the conditions defined by the 
segment identified by the specified identifier
-     */
-    @GET
-    @Path("/{segmentID}/count")
-    public long getMatchingIndividualsCount(@PathParam("segmentID") String 
segmentId) {
-        return segmentService.getMatchingIndividualsCount(segmentId);
-    }
-
-    /**
-     * Determines whether the specified profile is part of the segment 
identified by the specified identifier.
-     *
-     * @param profile   the profile we want to check
-     * @param segmentId the identifier of the segment against which we want to 
check the profile
-     * @return {@code true} if the specified profile is in the specified 
segment, {@code false} otherwise
-     */
-    @GET
-    @Path("/{segmentID}/match/{profile}")
-    public Boolean isProfileInSegment(@PathParam("profile") Profile profile, 
@PathParam("segmentID") String segmentId) {
-        return segmentService.isProfileInSegment(profile, segmentId);
-    }
-
-    /**
-     * Retrieves the 50 first segment metadatas.
-     *
-     * @return a List of the 50 first segment metadata
-     */
-    @GET
-    @Path("/")
-    public List<Metadata> getSegmentMetadatas() {
-        return segmentService.getSegmentMetadatas(0, 50, null).getList();
-    }
-
-    /**
-     * Retrieves the list of segment metadata of segments depending on the 
segment identified by the specified identifier. A segment is depending on 
another one if it includes
-     * that segment as part of its condition for profile matching.
-     *
-     * TODO: rename?
-     *
-     * @param segmentId the identifier of the segment which impact we want to 
evaluate
-     * @return a list of metadata of segments depending on the specified 
segment
-     */
-    @GET
-    @Path("/{segmentID}/impacted")
-    public List<Metadata> getSegmentImpacted(@PathParam("segmentID") String 
segmentId) {
-        return segmentService.getImpactedSegmentMetadata(segmentId);
-    }
-
-    /**
-     * Persists the specified segment in the context server.
-     *
-     * @param segment the segment to be persisted
-     */
-    @POST
-    @Path("/")
-    public void setSegmentDefinition(Segment segment) {
-        segmentService.setSegmentDefinition(segment);
-    }
-
-    /**
-     * Retrieves the metadata for segments matching the specified {@link 
Query}.
-     *
-     * @param query the query that the segments must match for their metadata 
to be retrieved
-     * @return a {@link PartialList} of segment metadata
-     */
-    @POST
-    @Path("/query")
-    public PartialList<Metadata> getListMetadatas(Query query) {
-        return segmentService.getSegmentMetadatas(query);
-    }
-
-    /**
-     * Retrieves the segment identified by the specified identifier.
-     *
-     * @param segmentId the identifier of the segment to be retrieved
-     * @return the segment identified by the specified identifier or {@code 
null} if no such segment exists
-     */
-    @GET
-    @Path("/{segmentID}")
-    public Segment getSegmentDefinition(@PathParam("segmentID") String 
segmentId) {
-        return segmentService.getSegmentDefinition(segmentId);
-    }
-
-    /**
-     * Removes the segment definition identified by the specified identifier. 
We can specify that we want the operation to be validated beforehand so that we 
can
-     * know if any other segment that might use the segment we're trying to 
delete as a condition might be impacted. If {@code validate} is set to {@code 
false}, no
-     * validation is performed. If set to {@code true}, we will first check if 
any segment depends on the one we're trying to delete and if so we will not 
delete the
-     * segment but rather return the list of the metadata of the impacted 
segments. If no dependents are found, then we properly delete the segment.
-     *
-     * @param segmentId the identifier of the segment we want to delete
-     * @param validate  whether or not to perform validation
-     * @return a list of impacted segment metadata if any or an empty list if 
no such impacted segments are found or validation was skipped
-     */
-    @DELETE
-    @Path("/{segmentID}")
-    public List<Metadata> removeSegmentDefinition(@PathParam("segmentID") 
String segmentId, @QueryParam("validate") boolean validate) {
-        return segmentService.removeSegmentDefinition(segmentId, validate);
-    }
-
-    /**
-     * TODO: remove
-     *
-     * @deprecated not needed anymore
-     */
-    @GET
-    @Path("/resetQueries")
-    public void resetQueries() {
-        for (Metadata metadata : segmentService.getSegmentMetadatas(0, 50, 
null).getList()) {
-            Segment s = segmentService.getSegmentDefinition(metadata.getId());
-            segmentService.setSegmentDefinition(s);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/rest/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/rest/src/main/resources/OSGI-INF/blueprint/blueprint.xml 
b/rest/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index d04d7b1..0c81d6e 100644
--- a/rest/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/rest/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -24,7 +24,7 @@
   http://cxf.apache.org/blueprint/jaxrs 
http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
   http://cxf.apache.org/blueprint/core 
http://cxf.apache.org/schemas/blueprint/core.xsd
   http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 
http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd";>
-    <cm:property-placeholder 
persistent-id="org.oasis_open.contextserver.rest.segmentserviceendpoint"
+    <cm:property-placeholder 
persistent-id="org.apache.unomi.rest.segmentserviceendpoint"
                              update-strategy="reload">
     </cm:property-placeholder>
 
@@ -35,7 +35,7 @@
     </cxf:bus>
 
     <bean id="cors-filter" 
class="org.apache.cxf.rs.security.cors.CrossOriginResourceSharingFilter"/>
-    <bean id="jacksonMapper" 
class="org.oasis_open.contextserver.persistence.spi.CustomObjectMapper"/>
+    <bean id="jacksonMapper" 
class="org.apache.unomi.persistence.spi.CustomObjectMapper"/>
     <bean id="jaxb-provider" 
class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
         <argument index="0" ref="jacksonMapper" 
type="com.fasterxml.jackson.databind.ObjectMapper "/>
         <argument index="1" 
type="com.fasterxml.jackson.jaxrs.cfg.Annotations[]">
@@ -166,61 +166,61 @@
         </jaxrs:serviceBeans>
     </jaxrs:server>
 
-    <reference id="segmentService" 
interface="org.oasis_open.contextserver.api.services.SegmentService"/>
-    <reference id="definitionsService" 
interface="org.oasis_open.contextserver.api.services.DefinitionsService"/>
-    <reference id="goalsService" 
interface="org.oasis_open.contextserver.api.services.GoalsService"/>
-    <reference id="rulesService" 
interface="org.oasis_open.contextserver.api.services.RulesService"/>
-    <reference id="profileService" 
interface="org.oasis_open.contextserver.api.services.ProfileService"/>
-    <reference id="clusterService" 
interface="org.oasis_open.contextserver.api.services.ClusterService"/>
-    <reference id="queryService" 
interface="org.oasis_open.contextserver.api.services.QueryService"/>
-    <reference id="eventService" 
interface="org.oasis_open.contextserver.api.services.EventService"/>
+    <reference id="segmentService" 
interface="org.apache.unomi.api.services.SegmentService"/>
+    <reference id="definitionsService" 
interface="org.apache.unomi.api.services.DefinitionsService"/>
+    <reference id="goalsService" 
interface="org.apache.unomi.api.services.GoalsService"/>
+    <reference id="rulesService" 
interface="org.apache.unomi.api.services.RulesService"/>
+    <reference id="profileService" 
interface="org.apache.unomi.api.services.ProfileService"/>
+    <reference id="clusterService" 
interface="org.apache.unomi.api.services.ClusterService"/>
+    <reference id="queryService" 
interface="org.apache.unomi.api.services.QueryService"/>
+    <reference id="eventService" 
interface="org.apache.unomi.api.services.EventService"/>
 
-    <bean id="segmentServiceEndPoint" 
class="org.oasis_open.contextserver.rest.SegmentServiceEndPoint">
+    <bean id="segmentServiceEndPoint" 
class="org.apache.unomi.rest.SegmentServiceEndPoint">
         <property name="segmentService" ref="segmentService"/>
     </bean>
 
-    <bean id="scoringServiceEndPoint" 
class="org.oasis_open.contextserver.rest.ScoringServiceEndPoint">
+    <bean id="scoringServiceEndPoint" 
class="org.apache.unomi.rest.ScoringServiceEndPoint">
         <property name="segmentService" ref="segmentService"/>
     </bean>
 
-    <bean id="definitionsServiceEndPoint" 
class="org.oasis_open.contextserver.rest.DefinitionsServiceEndPoint">
+    <bean id="definitionsServiceEndPoint" 
class="org.apache.unomi.rest.DefinitionsServiceEndPoint">
         <property name="definitionsService" ref="definitionsService"/>
         <property name="localizationHelper" ref="localizationHelper"/>
     </bean>
 
-    <bean id="goalsServiceEndPoint" 
class="org.oasis_open.contextserver.rest.GoalsServiceEndPoint">
+    <bean id="goalsServiceEndPoint" 
class="org.apache.unomi.rest.GoalsServiceEndPoint">
         <property name="goalsService" ref="goalsService"/>
     </bean>
 
-    <bean id="campaignServiceEndPoint" 
class="org.oasis_open.contextserver.rest.CampaignsServiceEndPoint">
+    <bean id="campaignServiceEndPoint" 
class="org.apache.unomi.rest.CampaignsServiceEndPoint">
         <property name="goalsService" ref="goalsService"/>
     </bean>
 
-    <bean id="rulesServiceEndPoint" 
class="org.oasis_open.contextserver.rest.RulesServiceEndPoint">
+    <bean id="rulesServiceEndPoint" 
class="org.apache.unomi.rest.RulesServiceEndPoint">
         <property name="rulesService" ref="rulesService"/>
     </bean>
 
-    <bean id="profileServiceEndPoint" 
class="org.oasis_open.contextserver.rest.ProfileServiceEndPoint">
+    <bean id="profileServiceEndPoint" 
class="org.apache.unomi.rest.ProfileServiceEndPoint">
         <property name="profileService" ref="profileService"/>
         <property name="eventService" ref="eventService"/>
         <property name="segmentService" ref="segmentService"/>
         <property name="localizationHelper" ref="localizationHelper"/>
     </bean>
 
-    <bean id="clusterServiceEndPoint" 
class="org.oasis_open.contextserver.rest.ClusterServiceEndPoint">
+    <bean id="clusterServiceEndPoint" 
class="org.apache.unomi.rest.ClusterServiceEndPoint">
         <property name="clusterService" ref="clusterService"/>
     </bean>
 
-    <bean id="queryServiceEndPoint" 
class="org.oasis_open.contextserver.rest.QueryServiceEndPoint">
+    <bean id="queryServiceEndPoint" 
class="org.apache.unomi.rest.QueryServiceEndPoint">
         <property name="queryService" ref="queryService"/>
         <property name="localizationHelper" ref="localizationHelper"/>
     </bean>
 
-    <bean id="resourceBundleHelper" 
class="org.oasis_open.contextserver.rest.ResourceBundleHelper">
+    <bean id="resourceBundleHelper" 
class="org.apache.unomi.rest.ResourceBundleHelper">
         <property name="bundleContext" ref="blueprintBundleContext"/>
     </bean>
 
-  <bean id="localizationHelper" 
class="org.oasis_open.contextserver.rest.LocalizationHelper">
+    <bean id="localizationHelper" 
class="org.apache.unomi.rest.LocalizationHelper">
     <property name="bundleContext" ref="blueprintBundleContext"/>
     <property name="resourceBundleHelper" ref="resourceBundleHelper"/>
   </bean>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/dc1d1520/services/src/main/java/org/apache/unomi/services/actions/ActionExecutorDispatcher.java
----------------------------------------------------------------------
diff --git 
a/services/src/main/java/org/apache/unomi/services/actions/ActionExecutorDispatcher.java
 
b/services/src/main/java/org/apache/unomi/services/actions/ActionExecutorDispatcher.java
new file mode 100644
index 0000000..bcd49e7
--- /dev/null
+++ 
b/services/src/main/java/org/apache/unomi/services/actions/ActionExecutorDispatcher.java
@@ -0,0 +1,201 @@
+/*
+ * 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.services.actions;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang3.StringUtils;
+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.mvel2.MVEL;
+import org.mvel2.ParserConfiguration;
+import org.mvel2.ParserContext;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ActionExecutorDispatcher {
+    private static final Logger logger = 
LoggerFactory.getLogger(ActionExecutorDispatcher.class.getName());
+    private static final String VALUE_NAME_SEPARATOR = "::";
+    private final Map<String, Serializable> mvelExpressions = new 
ConcurrentHashMap<>();
+    private final Map<String, ValueExtractor> valueExtractors = new 
HashMap<>(11);
+    private BundleContext bundleContext;
+    private Map<String, ActionExecutor> executors = new ConcurrentHashMap<>();
+    private Map<Long, List<String>> executorsByBundle = new 
ConcurrentHashMap<>();
+
+    public ActionExecutorDispatcher() {
+        valueExtractors.put("profileProperty", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                return PropertyUtils.getProperty(event.getProfile(), 
"properties." + valueAsString);
+            }
+        });
+        valueExtractors.put("simpleProfileProperty", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                return event.getProfile().getProperty(valueAsString);
+            }
+        });
+        valueExtractors.put("sessionProperty", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                return PropertyUtils.getProperty(event.getSession(), 
"properties." + valueAsString);
+            }
+        });
+        valueExtractors.put("simpleSessionProperty", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                return event.getSession().getProperty(valueAsString);
+            }
+        });
+        valueExtractors.put("eventProperty", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                return PropertyUtils.getProperty(event, valueAsString);
+            }
+        });
+        valueExtractors.put("simpleEventProperty", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                return event.getProperty(valueAsString);
+            }
+        });
+        valueExtractors.put("script", new ValueExtractor() {
+            @Override
+            public Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+                if (!mvelExpressions.containsKey(valueAsString)) {
+                    ParserConfiguration parserConfiguration = new 
ParserConfiguration();
+                    
parserConfiguration.setClassLoader(getClass().getClassLoader());
+                    mvelExpressions.put(valueAsString, 
MVEL.compileExpression(valueAsString, new ParserContext(parserConfiguration)));
+                }
+                Map<String, Object> ctx = new HashMap<>();
+                ctx.put("event", event);
+                ctx.put("session", event.getSession());
+                ctx.put("profile", event.getProfile());
+                return 
MVEL.executeExpression(mvelExpressions.get(valueAsString), ctx);
+            }
+        });
+    }
+
+    public void addExecutor(String name, long bundleId, ActionExecutor 
evaluator) {
+        executors.put(name, evaluator);
+        if (!executorsByBundle.containsKey(bundleId)) {
+            executorsByBundle.put(bundleId, new ArrayList<String>());
+        }
+        executorsByBundle.get(bundleId).add(name);
+    }
+
+    public void removeExecutors(long bundleId) {
+        if (executorsByBundle.containsKey(bundleId)) {
+            for (String s : executorsByBundle.get(bundleId)) {
+                executors.remove(s);
+            }
+            executorsByBundle.remove(bundleId);
+        }
+    }
+
+    public Action getContextualAction(Action action, Event event) {
+        if (!hasContextualParameter(action.getParameterValues())) {
+            return action;
+        }
+
+        Map<String, Object> values = parseMap(event, 
action.getParameterValues());
+        Action n = new Action(action.getActionType());
+        n.setParameterValues(values);
+        return n;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<String, Object> parseMap(Event event, Map<String, Object> map) 
{
+        Map<String, Object> values = new HashMap<>();
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            Object value = entry.getValue();
+            if (value instanceof String) {
+                String s = (String) value;
+                try {
+                    // check if we have special values
+                    if (s.contains(VALUE_NAME_SEPARATOR)) {
+                        final String valueType = 
StringUtils.substringBefore(s, VALUE_NAME_SEPARATOR);
+                        final String valueAsString = 
StringUtils.substringAfter(s, VALUE_NAME_SEPARATOR);
+                        final ValueExtractor extractor = 
valueExtractors.get(valueType);
+                        if (extractor != null) {
+                            value = extractor.extract(valueAsString, event);
+                        }
+                    }
+                } catch (UnsupportedOperationException e) {
+                    throw e;
+                } catch (Exception e) {
+                    throw new UnsupportedOperationException(e);
+                }
+            } else if (value instanceof Map) {
+                value = parseMap(event, (Map<String, Object>) value);
+            }
+            values.put(entry.getKey(), value);
+        }
+        return values;
+    }
+
+    @SuppressWarnings("unchecked")
+    private boolean hasContextualParameter(Map<String, Object> values) {
+        for (Map.Entry<String, Object> entry : values.entrySet()) {
+            Object value = entry.getValue();
+            if (value instanceof String) {
+                String s = (String) value;
+                if (s.contains(VALUE_NAME_SEPARATOR) && 
valueExtractors.containsKey(StringUtils.substringBefore(s, 
VALUE_NAME_SEPARATOR))) {
+                    return true;
+                }
+            } else if (value instanceof Map) {
+                if (hasContextualParameter((Map<String, Object>) value)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public int execute(Action action, Event event) {
+        String actionKey = action.getActionType().getActionExecutor();
+        if (actionKey == null) {
+            throw new UnsupportedOperationException("No service defined for : 
" + action.getActionType());
+        }
+
+        if (executors.containsKey(actionKey)) {
+            ActionExecutor actionExecutor = executors.get(actionKey);
+            return actionExecutor.execute(getContextualAction(action, event), 
event);
+        }
+        return EventService.NO_CHANGE;
+    }
+
+    private interface ValueExtractor {
+        Object extract(String valueAsString, Event event) throws 
IllegalAccessException, NoSuchMethodException, InvocationTargetException;
+    }
+
+}

Reply via email to