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.activity.ActivityHelper.createDocumentActivityObject;
021import static org.nuxeo.ecm.activity.ActivityHelper.createUserActivityObject;
022import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.ACTOR_PARAMETER;
023import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.CONTEXT_PARAMETER;
024import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.FROMDT_PARAMETER;
025import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.OBJECT_PARAMETER;
026import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.TODT_PARAMETER;
027import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.QueryType.GET_DOCUMENTS_COUNT;
028import static org.nuxeo.ecm.rating.LikesCountActivityStreamFilter.QueryType.GET_MINI_MESSAGE_COUNT;
029import static org.nuxeo.ecm.rating.RatingActivityStreamFilter.QUERY_TYPE_PARAMETER;
030import static org.nuxeo.ecm.rating.api.Constants.LIKE_ASPECT;
031import static org.nuxeo.ecm.rating.api.LikeStatus.DISLIKED;
032import static org.nuxeo.ecm.rating.api.LikeStatus.LIKED;
033import static org.nuxeo.ecm.rating.api.LikeStatus.UNKNOWN;
034
035import java.io.Serializable;
036import java.util.Collections;
037import java.util.Comparator;
038import java.util.Date;
039import java.util.HashMap;
040import java.util.Map;
041
042import org.nuxeo.ecm.activity.ActivitiesList;
043import org.nuxeo.ecm.activity.ActivitiesListImpl;
044import org.nuxeo.ecm.activity.Activity;
045import org.nuxeo.ecm.activity.ActivityStreamService;
046import org.nuxeo.ecm.core.api.CoreSession;
047import org.nuxeo.ecm.core.api.DocumentModel;
048import org.nuxeo.ecm.rating.api.LikeService;
049import org.nuxeo.ecm.rating.api.LikeStatus;
050import org.nuxeo.ecm.rating.api.RatingService;
051import org.nuxeo.runtime.api.Framework;
052import org.nuxeo.runtime.model.DefaultComponent;
053
054/**
055 * Default implementation of {@see LikeService}.
056 *
057 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
058 * @since 5.6
059 */
060public class LikeServiceImpl extends DefaultComponent implements LikeService {
061
062    public static final int LIKE_RATING = 1;
063
064    public static final int DISLIKE_RATING = -1;
065
066    @Override
067    public void like(String username, String activityObject) {
068        RatingService ratingService = Framework.getLocalService(RatingService.class);
069        ratingService.cancelRate(username, activityObject, LIKE_ASPECT);
070        ratingService.rate(username, LIKE_RATING, activityObject, LIKE_ASPECT);
071    }
072
073    @Override
074    public void like(String username, DocumentModel doc) {
075        like(username, createDocumentActivityObject(doc));
076    }
077
078    @Override
079    public boolean hasUserLiked(String username, String activityObject) {
080        RatingService ratingService = Framework.getLocalService(RatingService.class);
081        double average = ratingService.getAverageRatingForUser(username, activityObject, LIKE_ASPECT);
082        return average > 0;
083    }
084
085    @Override
086    public boolean hasUserLiked(String username, DocumentModel doc) {
087        return hasUserLiked(username, createDocumentActivityObject(doc));
088    }
089
090    @Override
091    public long getLikesCount(String activityObject) {
092        RatingService ratingService = Framework.getLocalService(RatingService.class);
093        return ratingService.getRatesCount(activityObject, LIKE_RATING, LIKE_ASPECT);
094    }
095
096    @Override
097    public long getLikesCount(DocumentModel doc) {
098        return getLikesCount(createDocumentActivityObject(doc));
099    }
100
101    @Override
102    public void dislike(String username, String activityObject) {
103        RatingService ratingService = Framework.getLocalService(RatingService.class);
104        ratingService.cancelRate(username, activityObject, LIKE_ASPECT);
105        ratingService.rate(username, DISLIKE_RATING, activityObject, LIKE_ASPECT);
106    }
107
108    @Override
109    public void dislike(String username, DocumentModel doc) {
110        dislike(username, createDocumentActivityObject(doc));
111    }
112
113    @Override
114    public boolean hasUserDisliked(String username, String activityObject) {
115        RatingService ratingService = Framework.getLocalService(RatingService.class);
116        double average = ratingService.getAverageRatingForUser(username, activityObject, LIKE_ASPECT);
117        return average < 0;
118    }
119
120    @Override
121    public boolean hasUserDisliked(String username, DocumentModel doc) {
122        return hasUserDisliked(username, createDocumentActivityObject(doc));
123    }
124
125    @Override
126    public long getDislikesCount(String activityObject) {
127        RatingService ratingService = Framework.getLocalService(RatingService.class);
128        return ratingService.getRatesCount(activityObject, DISLIKE_RATING, LIKE_ASPECT);
129    }
130
131    @Override
132    public long getDislikesCount(DocumentModel doc) {
133        return getDislikesCount(createDocumentActivityObject(doc));
134    }
135
136    @Override
137    public void cancel(String username, String activityObject) {
138        RatingService ratingService = Framework.getLocalService(RatingService.class);
139        ratingService.cancelRate(username, activityObject, LIKE_ASPECT);
140    }
141
142    @Override
143    public void cancel(String username, DocumentModel doc) {
144        cancel(username, createDocumentActivityObject(doc));
145    }
146
147    @Override
148    public LikeStatus getLikeStatus(String activityObject) {
149        long likesCount = getLikesCount(activityObject);
150        long dislikesCount = getDislikesCount(activityObject);
151        return new LikeStatus(activityObject, likesCount, dislikesCount);
152    }
153
154    @Override
155    public LikeStatus getLikeStatus(DocumentModel doc) {
156        return getLikeStatus(createDocumentActivityObject(doc));
157    }
158
159    @Override
160    public LikeStatus getLikeStatus(String username, String activityObject) {
161        long likesCount = getLikesCount(activityObject);
162        long dislikesCount = getDislikesCount(activityObject);
163        int userLikeStatus = hasUserLiked(username, activityObject) ? LIKED
164                : hasUserDisliked(username, activityObject) ? DISLIKED : UNKNOWN;
165        return new LikeStatus(activityObject, likesCount, dislikesCount, username, userLikeStatus);
166    }
167
168    @Override
169    public LikeStatus getLikeStatus(String username, DocumentModel doc) {
170        return getLikeStatus(username, createDocumentActivityObject(doc));
171    }
172
173    @Override
174    public ActivitiesList getMostLikedActivities(CoreSession session, int limit, DocumentModel source, Date fromDt,
175            Date toDt) {
176        // Get most liked Documents
177        Map<String, Serializable> parameters = new HashMap<String, Serializable>();
178        if (fromDt != null && toDt != null) {
179            parameters.put(FROMDT_PARAMETER, fromDt);
180            parameters.put(TODT_PARAMETER, toDt);
181        }
182        parameters.put(CONTEXT_PARAMETER, createDocumentActivityObject(source));
183        parameters.put(OBJECT_PARAMETER, Integer.valueOf(LIKE_RATING));
184        parameters.put(ACTOR_PARAMETER, createUserActivityObject(session.getPrincipal().getName()));
185        parameters.put(QUERY_TYPE_PARAMETER, GET_DOCUMENTS_COUNT);
186
187        ActivityStreamService activityStreamService = Framework.getLocalService(ActivityStreamService.class);
188        ActivitiesList documentActivitiesList = activityStreamService.query(LikesCountActivityStreamFilter.ID,
189                parameters);
190        ActivitiesList mostLikedActivities = documentActivitiesList.filterActivities(session);
191
192        // Get most liked minimessages
193        parameters.put(QUERY_TYPE_PARAMETER, GET_MINI_MESSAGE_COUNT);
194        ActivitiesList miniMessageActivitiesList = activityStreamService.query(LikesCountActivityStreamFilter.ID,
195                parameters, 0, limit);
196        mostLikedActivities.addAll(miniMessageActivitiesList);
197
198        // Sort by Object
199        Collections.sort(mostLikedActivities, new Comparator<Activity>() {
200            @Override
201            public int compare(Activity o1, Activity o2) {
202                return o2.getObject().compareTo(o1.getObject());
203            }
204        });
205
206        if (mostLikedActivities.size() > limit) {
207            return new ActivitiesListImpl(mostLikedActivities.subList(0, limit));
208        }
209        return mostLikedActivities;
210    }
211
212    @Override
213    public ActivitiesList getMostLikedActivities(CoreSession session, int limit, DocumentModel source) {
214        return getMostLikedActivities(session, limit, source, null, null);
215    }
216}