001package org.nuxeo.ecm.rating;
002
003import static org.nuxeo.ecm.rating.RatingActivityStreamFilter.QUERY_TYPE_PARAMETER;
004import static org.nuxeo.ecm.rating.api.Constants.LIKE_ASPECT;
005import static org.nuxeo.ecm.rating.api.Constants.RATING_VERB_PREFIX;
006
007import java.io.Serializable;
008import java.util.Collection;
009import java.util.Map;
010
011import javax.persistence.EntityManager;
012import javax.persistence.Query;
013
014import org.apache.commons.logging.Log;
015import org.apache.commons.logging.LogFactory;
016import org.nuxeo.ecm.activity.ActivitiesList;
017import org.nuxeo.ecm.activity.ActivitiesListImpl;
018import org.nuxeo.ecm.activity.Activity;
019import org.nuxeo.ecm.activity.ActivityBuilder;
020import org.nuxeo.ecm.activity.ActivityReply;
021import org.nuxeo.ecm.activity.ActivityStreamFilter;
022import org.nuxeo.ecm.activity.ActivityStreamService;
023import org.nuxeo.ecm.activity.ActivityStreamServiceImpl;
024
025/**
026 * An activity stream filter to handle likes count
027 *
028 * @author <a href="mailto:akervern@nuxeo.com">Arnaud Kervern</a>
029 * @since 5.6
030 */
031public class LikesCountActivityStreamFilter implements ActivityStreamFilter {
032
033    public enum QueryType {
034        GET_DOCUMENTS_COUNT, GET_MINI_MESSAGE_COUNT
035    }
036
037    public static final String ID = "LikesCountActivityStreamFilter";
038
039    public static final String CONTEXT_PARAMETER = "context";
040
041    public static final String ASPECT_PARAMETER = "aspect";
042
043    public static final String OBJECT_PARAMETER = "object";
044
045    public static final String ACTOR_PARAMETER = "actor";
046
047    public static final String FROMDT_PARAMETER = "fromDt";
048
049    public static final String TODT_PARAMETER = "toDt";
050
051    protected static final String VERB_PARAMETER = "verb";
052
053    protected static final String VERB_MINIMESSAGE_PARAMETER = "verbMiniMessage";
054
055    private static final Log log = LogFactory.getLog(LikesCountActivityStreamFilter.class);
056
057    @Override
058    public String getId() {
059        return ID;
060    }
061
062    @Override
063    public boolean isInterestedIn(Activity activity) {
064        return false;
065    }
066
067    @Override
068    public void handleNewActivity(ActivityStreamService activityStreamService, Activity activity) {
069        // Nothing to do for now
070    }
071
072    @Override
073    @Deprecated
074    public void handleRemovedActivities(ActivityStreamService activityStreamService,
075            Collection<Serializable> activityIds) {
076        // Nothing to do for now
077    }
078
079    @Override
080    public void handleRemovedActivities(ActivityStreamService activityStreamService, ActivitiesList activities) {
081    }
082
083    @Override
084    public void handleRemovedActivityReply(ActivityStreamService activityStreamService, Activity activity,
085            ActivityReply activityReply) {
086    }
087
088    @Override
089    public ActivitiesList query(ActivityStreamService activityStreamService, Map<String, Serializable> parameters,
090            long offset, long limit) {
091        QueryType queryType = (QueryType) parameters.get(QUERY_TYPE_PARAMETER);
092        if (queryType == null) {
093            return new ActivitiesListImpl();
094        }
095
096        Query query = null;
097        String queryStr = "";
098        String innerStr = "";
099        EntityManager em = ((ActivityStreamServiceImpl) activityStreamService).getEntityManager();
100        Serializable actor = parameters.get(ACTOR_PARAMETER);
101
102        switch (queryType) {
103        case GET_DOCUMENTS_COUNT:
104            // InnerQuery indicates if the actor has alredy liked or not
105            innerStr = "SELECT COUNT(activity2) FROM Activity activity2 WHERE activity2.verb = :verb";
106            innerStr += " AND activity2.context = :context AND activity2.object = :object";
107            innerStr += " AND activity2.actor = :actor AND activity2.target = activity.target";
108            if (parameters.containsKey(FROMDT_PARAMETER)) {
109                innerStr += " AND activity2.publishedDate BETWEEN :fromDt AND :toDt";
110            }
111            queryStr = "SELECT activity.target, count(activity), (" + innerStr + ") FROM Activity activity";
112            queryStr += " WHERE activity.verb = :verb and activity.context  = :context";
113            queryStr += " AND activity.object = :object";
114            if (parameters.containsKey(FROMDT_PARAMETER)) {
115                queryStr += " AND activity.publishedDate BETWEEN :fromDt AND :toDt";
116            }
117            queryStr += " GROUP BY activity.target ORDER BY COUNT(activity) DESC";
118
119            Serializable object = String.valueOf(parameters.get(OBJECT_PARAMETER));
120            query = em.createQuery(queryStr);
121            query.setParameter(OBJECT_PARAMETER, object);
122
123            break;
124        case GET_MINI_MESSAGE_COUNT:
125            // InnerQuery indicates if the actor has alredy liked or not
126            innerStr = "Select count(likes2) from Activity as likes2 ";
127            innerStr += " where likes.target = likes2.target and likes2.actor = :actor";
128            if (parameters.containsKey(FROMDT_PARAMETER)) {
129                innerStr += " AND likes2.publishedDate BETWEEN :fromDt AND :toDt";
130            }
131            queryStr = "Select likes.target, count(likes), (" + innerStr
132                    + ") from Activity as likes, Activity as minimessage";
133            queryStr += " where concat('activity:', cast(minimessage.id as string)) = likes.target";
134            queryStr += " and minimessage.verb = :verbMiniMessage and minimessage.context  = :context";
135            queryStr += " and likes.verb = :verb";
136            if (parameters.containsKey(FROMDT_PARAMETER)) {
137                queryStr += " AND likes.publishedDate BETWEEN :fromDt AND :toDt";
138            }
139            queryStr += " group by likes.target order by count(likes) desc";
140
141            query = em.createQuery(queryStr);
142            query.setParameter(VERB_MINIMESSAGE_PARAMETER, "minimessage");
143
144            break;
145        default:
146            log.info("Unknown query type: " + queryType);
147            return new ActivitiesListImpl();
148        }
149
150        // Default parameters
151        query.setParameter(CONTEXT_PARAMETER, parameters.get(CONTEXT_PARAMETER));
152        query.setParameter(VERB_PARAMETER, RATING_VERB_PREFIX + LIKE_ASPECT);
153        query.setParameter(ACTOR_PARAMETER, actor);
154        if (parameters.containsKey(FROMDT_PARAMETER)) {
155            query.setParameter(FROMDT_PARAMETER, parameters.get(FROMDT_PARAMETER));
156            query.setParameter(TODT_PARAMETER, parameters.get(TODT_PARAMETER));
157        }
158
159        if (limit > 0) {
160            query.setMaxResults((int) limit);
161        }
162        if (offset > 0) {
163            query.setFirstResult((int) offset);
164        }
165
166        ActivitiesList likesCount = new ActivitiesListImpl();
167        for (Object result : query.getResultList()) {
168            Object[] objects = (Object[]) result;
169            ActivityBuilder ab = new ActivityBuilder().verb(RATING_VERB_PREFIX + LIKE_ASPECT).actor((String) actor).object(
170                    String.valueOf(objects[1])).target((String) objects[0]).context(String.valueOf(objects[2]));
171            likesCount.add(ab.build());
172        }
173
174        return likesCount;
175    }
176}