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;
041import org.nuxeo.ecm.core.api.NuxeoException;
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    public void handleRemovedActivities(ActivityStreamService activityStreamService, ActivitiesList activities) {
089        List<String> activityObjects = new ArrayList<>();
090        for (Activity activity : activities) {
091            activityObjects.add(ActivityHelper.createActivityObject(activity));
092            for (ActivityReply reply : activity.getActivityReplies()) {
093                activityObjects.add(ActivityHelper.createActivityObject(reply.getId()));
094            }
095        }
096        removeAllRatingActivitiesFor(activityStreamService, activityObjects);
097    }
098
099    @Override
100    public void handleRemovedActivityReply(ActivityStreamService activityStreamService, Activity activity,
101            ActivityReply activityReply) {
102        removeAllRatingActivitiesFor(activityStreamService,
103                Collections.singleton(ActivityHelper.createActivityObject(activityReply.getId())));
104    }
105
106    protected void removeAllRatingActivitiesFor(ActivityStreamService activityStreamService,
107            Collection<String> activityObjects) {
108        EntityManager em = ((ActivityStreamServiceImpl) activityStreamService).getEntityManager();
109        Query query = em.createQuery(
110                "delete from Activity activity where activity.verb LIKE :verb and activity.target in (:target)");
111        query.setParameter("verb", RATING_VERB_PREFIX + "%");
112        query.setParameter("target", activityObjects);
113        query.executeUpdate();
114    }
115
116    @Override
117    @SuppressWarnings("unchecked")
118    public ActivitiesList query(ActivityStreamService activityStreamService, Map<String, Serializable> parameters,
119            long offset, long limit) {
120        EntityManager em = ((ActivityStreamServiceImpl) activityStreamService).getEntityManager();
121        QueryType queryType = (QueryType) parameters.get(QUERY_TYPE_PARAMETER);
122        if (queryType == null) {
123            return new ActivitiesListImpl();
124        }
125
126        Query query = null;
127        StringBuilder sb;
128        String targetObject = (String) parameters.get(TARGET_OBJECT_PARAMETER);
129        String aspect = (String) parameters.get(ASPECT_PARAMETER);
130        String actor = (String) parameters.get(ACTOR_PARAMETER);
131        Integer rating = (Integer) parameters.get(RATING_PARAMETER);
132        String context = (String) parameters.get(CONTEXT_PARAMETER);
133        switch (queryType) {
134        case GET_ACTOR_RATINGS_FOR_OBJECT:
135            sb = new StringBuilder(
136                    "select activity from Activity activity where activity.verb = :verb and activity.actor = :actor and activity.target = :targetObject and activity.context is null");
137            if (rating != null) {
138                sb.append(" and activity.object = :rating");
139            }
140            query = em.createQuery(sb.toString());
141            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
142            query.setParameter(TARGET_OBJECT_PARAMETER, targetObject);
143            query.setParameter(ACTOR_PARAMETER, actor);
144            if (rating != null) {
145                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
146            }
147            break;
148        case GET_RATINGS_FOR_OBJECT:
149            sb = new StringBuilder(
150                    "select activity from Activity activity where activity.verb = :verb and activity.target = :targetObject and activity.context is null");
151            if (rating != null) {
152                sb.append(" and activity.object = :rating");
153            }
154            query = em.createQuery(sb.toString());
155            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
156            query.setParameter(TARGET_OBJECT_PARAMETER, targetObject);
157            if (rating != null) {
158                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
159            }
160            break;
161        case GET_RATED_CHILDREN_FOR_CONTEXT:
162            sb = new StringBuilder(
163                    "select activity from Activity activity where activity.verb = :verb and activity.context  = :context");
164            if (rating != null) {
165                sb.append(" and activity.object = :rating");
166            }
167            query = em.createQuery(sb.toString());
168            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
169            query.setParameter(CONTEXT_PARAMETER, context);
170            if (rating != null) {
171                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
172            }
173            break;
174        case GET_RATINGS_FOR_CANCEL:
175            sb = new StringBuilder("select activity from Activity activity where activity.target = :targetObject");
176            if (rating != null) {
177                sb.append(" and activity.object = :rating");
178            }
179            if (actor != null) {
180                sb.append(" and activity.actor = :actor");
181            }
182            if (aspect != null) {
183                sb.append(" and activity.verb = :verb");
184            } else {
185                sb.append(" and activity.verb LIKE :verb");
186                aspect = "%";
187            }
188            query = em.createQuery(sb.toString());
189            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
190            query.setParameter(TARGET_OBJECT_PARAMETER, targetObject);
191            if (rating != null) {
192                query.setParameter(RATING_PARAMETER, String.valueOf(rating));
193            }
194            if (actor != null) {
195                query.setParameter(ACTOR_PARAMETER, actor);
196            }
197            break;
198        case GET_LATEST_RATED_FOR_OBJECT:
199            query = em.createQuery(
200                    "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");
201            query.setParameter("verb", RATING_VERB_PREFIX + aspect);
202            query.setParameter(ACTOR_PARAMETER, actor);
203            query.setParameter(TARGET_OBJECT_PARAMETER, ActivityHelper.DOC_PREFIX + "%");
204            break;
205        default:
206            throw new NuxeoException("Unknown query type: " + queryType);
207        }
208
209        if (limit > 0) {
210            query.setMaxResults((int) limit);
211        }
212        if (offset > 0) {
213            query.setFirstResult((int) offset);
214        }
215        return new ActivitiesListImpl(query.getResultList());
216    }
217}