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