001/*
002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Thomas Roger <troger@nuxeo.com>
018 */
019
020package org.nuxeo.ecm.rating;
021
022import static org.nuxeo.ecm.rating.api.Constants.RATING_VERB_PREFIX;
023
024import java.io.Serializable;
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.List;
029import java.util.Map;
030
031import javax.persistence.EntityManager;
032import javax.persistence.Query;
033
034import org.nuxeo.ecm.activity.ActivitiesList;
035import org.nuxeo.ecm.activity.ActivitiesListImpl;
036import org.nuxeo.ecm.activity.Activity;
037import org.nuxeo.ecm.activity.ActivityHelper;
038import org.nuxeo.ecm.activity.ActivityReply;
039import org.nuxeo.ecm.activity.ActivityStreamFilter;
040import org.nuxeo.ecm.activity.ActivityStreamService;
041import org.nuxeo.ecm.activity.ActivityStreamServiceImpl;
042
043/**
044 * Activity Stream filter handling rating activities.
045 * <p>
046 * The different queries this filter can handle are defined in the {@link QueryType} enum.
047 *
048 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
049 * @since 5.6
050 */
051public class RatingActivityStreamFilter implements ActivityStreamFilter {
052
053    public static final String ID = "RatingActivityStreamFilter";
054
055    public enum QueryType {
056        GET_ACTOR_RATINGS_FOR_OBJECT, GET_RATINGS_FOR_OBJECT, GET_RATED_CHILDREN_FOR_CONTEXT, GET_RATINGS_FOR_CANCEL, GET_LATEST_RATED_FOR_OBJECT
057    }
058
059    public static final String QUERY_TYPE_PARAMETER = "queryTypeParameter";
060
061    public static final String TARGET_OBJECT_PARAMETER = "targetObject";
062
063    public static final String ASPECT_PARAMETER = "aspect";
064
065    public static final String ACTOR_PARAMETER = "actor";
066
067    public static final String RATING_PARAMETER = "rating";
068
069    public static final String CONTEXT_PARAMETER = "context";
070
071    @Override
072    public String getId() {
073        return ID;
074    }
075
076    @Override
077    public boolean isInterestedIn(Activity activity) {
078        String verb = activity.getVerb();
079        return verb != null && verb.startsWith(RATING_VERB_PREFIX);
080    }
081
082    @Override
083    public void handleNewActivity(ActivityStreamService activityStreamService, Activity activity) {
084        // nothing to do for now
085    }
086
087    @Override
088    @Deprecated
089    public void handleRemovedActivities(ActivityStreamService activityStreamService,
090            Collection<Serializable> activityIds) {
091        // nothing to do for now
092    }
093
094    @Override
095    public void handleRemovedActivities(ActivityStreamService activityStreamService, ActivitiesList activities) {
096        List<String> activityObjects = new ArrayList<String>();
097        for (Activity activity : activities) {
098            activityObjects.add(ActivityHelper.createActivityObject(activity));
099            for (ActivityReply reply : activity.getActivityReplies()) {
100                activityObjects.add(ActivityHelper.createActivityObject(reply.getId()));
101            }
102        }
103        removeAllRatingActivitiesFor(activityStreamService, activityObjects);
104    }
105
106    @Override
107    public void handleRemovedActivityReply(ActivityStreamService activityStreamService, Activity activity,
108            ActivityReply activityReply) {
109        removeAllRatingActivitiesFor(activityStreamService,
110                Collections.singleton(ActivityHelper.createActivityObject(activityReply.getId())));
111    }
112
113    protected void removeAllRatingActivitiesFor(ActivityStreamService activityStreamService,
114            Collection<String> activityObjects) {
115        EntityManager em = ((ActivityStreamServiceImpl) activityStreamService).getEntityManager();
116        Query query = em.createQuery("delete from Activity activity where activity.verb LIKE :verb and activity.target in (:target)");
117        query.setParameter("verb", RATING_VERB_PREFIX + "%");
118        query.setParameter("target", activityObjects);
119        query.executeUpdate();
120    }
121
122    @Override
123    @SuppressWarnings("unchecked")
124    public ActivitiesList query(ActivityStreamService activityStreamService, Map<String, Serializable> parameters,
125            long offset, long limit) {
126        EntityManager em = ((ActivityStreamServiceImpl) activityStreamService).getEntityManager();
127        QueryType queryType = (QueryType) parameters.get(QUERY_TYPE_PARAMETER);
128        if (queryType == null) {
129            return new ActivitiesListImpl();
130        }
131
132        Query query = null;
133        StringBuilder sb;
134        String targetObject = (String) parameters.get(TARGET_OBJECT_PARAMETER);
135        String aspect = (String) parameters.get(ASPECT_PARAMETER);
136        String actor = (String) parameters.get(ACTOR_PARAMETER);
137        Integer rating = (Integer) parameters.get(RATING_PARAMETER);
138        String context = (String) parameters.get(CONTEXT_PARAMETER);
139        switch (queryType) {
140        case GET_ACTOR_RATINGS_FOR_OBJECT:
141            sb = new StringBuilder(
142                    "select activity from Activity activity where activity.verb = :verb and activity.actor = :actor and activity.target = :targetObject and activity.context is null");
143            if (rating != null) {
144                sb.append(" and activity.object = :rating");
145            }
146            query = em.createQuery(sb.toString());
147            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
148            query.setParameter(TARGET_OBJECT_PARAMETER, targetObject);
149            query.setParameter(ACTOR_PARAMETER, actor);
150            if (rating != null) {
151                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
152            }
153            break;
154        case GET_RATINGS_FOR_OBJECT:
155            sb = new StringBuilder(
156                    "select activity from Activity activity where activity.verb = :verb and activity.target = :targetObject and activity.context is null");
157            if (rating != null) {
158                sb.append(" and activity.object = :rating");
159            }
160            query = em.createQuery(sb.toString());
161            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
162            query.setParameter(TARGET_OBJECT_PARAMETER, targetObject);
163            if (rating != null) {
164                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
165            }
166            break;
167        case GET_RATED_CHILDREN_FOR_CONTEXT:
168            sb = new StringBuilder(
169                    "select activity from Activity activity where activity.verb = :verb and activity.context  = :context");
170            if (rating != null) {
171                sb.append(" and activity.object = :rating");
172            }
173            query = em.createQuery(sb.toString());
174            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
175            query.setParameter(CONTEXT_PARAMETER, context);
176            if (rating != null) {
177                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
178            }
179            break;
180        case GET_RATINGS_FOR_CANCEL:
181            sb = new StringBuilder("select activity from Activity activity where activity.target = :targetObject");
182            if (rating != null) {
183                sb.append(" and activity.object = :rating");
184            }
185            if (actor != null) {
186                sb.append(" and activity.actor = :actor");
187            }
188            if (aspect != null) {
189                sb.append(" and activity.verb = :verb");
190            } else {
191                sb.append(" and activity.verb LIKE :verb");
192                aspect = "%";
193            }
194            query = em.createQuery(sb.toString());
195            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
196            query.setParameter(TARGET_OBJECT_PARAMETER, targetObject);
197            if (rating != null) {
198                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
199            }
200            if (actor != null) {
201                query.setParameter(ACTOR_PARAMETER, actor);
202            }
203            break;
204        case GET_LATEST_RATED_FOR_OBJECT:
205            query = em.createQuery("select activity from Activity activity where activity.target LIKE :targetObject and activity.context is null and activity.actor = :actor and activity.verb = :verb order by activity.publishedDate DESC, activity.id DESC");
206            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
207            query.setParameter(ACTOR_PARAMETER, actor);
208            query.setParameter(TARGET_OBJECT_PARAMETER, ActivityHelper.DOC_PREFIX + "%");
209            break;
210        }
211
212        if (limit > 0) {
213            query.setMaxResults((int) limit);
214        }
215        if (offset > 0) {
216            query.setFirstResult((int) offset);
217        }
218        return new ActivitiesListImpl(query.getResultList());
219    }
220}