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