/* * Copyright (C) 2003-2010 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.social.core.manager; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.Validate; import org.exoplatform.commons.utils.ListAccess; import org.exoplatform.container.PortalContainer; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.social.common.RealtimeListAccess; import org.exoplatform.social.core.ActivityProcessor; import org.exoplatform.social.core.BaseActivityProcessorPlugin; import org.exoplatform.social.core.activity.ActivitiesRealtimeListAccess; import org.exoplatform.social.core.activity.ActivitiesRealtimeListAccess.ActivityType; import org.exoplatform.social.core.activity.CommentsRealtimeListAccess; import org.exoplatform.social.core.activity.model.ExoSocialActivity; import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl; import org.exoplatform.social.core.identity.model.Identity; import org.exoplatform.social.core.space.spi.SpaceService; import org.exoplatform.social.core.storage.api.ActivityStorage; import org.exoplatform.social.core.storage.ActivityStorageException; /** * Class ActivityManagerImpl implements ActivityManager without caching. * * @author <a href="mailto:vien_levan@exoplatform.com">vien_levan</a> * @author <a href="hoatle.net">hoatle (hoatlevan at gmail dot com)</a> * @since Nov 24, 2010 * @since 1.2.0-GA */ public class ActivityManagerImpl implements ActivityManager { /** Logger */ private static final Log LOG = ExoLogger.getLogger(ActivityManagerImpl.class); /** The activityStorage. */ protected ActivityStorage activityStorage; /** identityManager to get identity for saving and getting activities */ protected IdentityManager identityManager; /** spaceService */ protected SpaceService spaceService; /** * Default limit for deprecated methods to get maximum number of activities. */ private static final int DEFAULT_LIMIT = 20; /** * Instantiates a new activity manager. * * @param activityStorage * @param identityManager */ public ActivityManagerImpl(ActivityStorage activityStorage, IdentityManager identityManager) { this.activityStorage = activityStorage; this.identityManager = identityManager; } /** * {@inheritDoc} */ public void saveActivityNoReturn(Identity streamOwner, ExoSocialActivity newActivity) { long currentTime = System.currentTimeMillis(); newActivity.setUpdated(new Date(currentTime)); //new activity if (newActivity.getId() == null) { newActivity.setPostedTime(currentTime); } activityStorage.saveActivity(streamOwner, newActivity); } /** * {@inheritDoc} */ public void saveActivityNoReturn(ExoSocialActivity newActivity) { Identity owner = getStreamOwner(newActivity); saveActivityNoReturn(owner, newActivity); } /** * {@inheritDoc} */ public void saveActivity(Identity streamOwner, String activityType, String activityTitle) { ExoSocialActivity activity = new ExoSocialActivityImpl(); activity.setType(activityType); activity.setTitle(activityTitle); saveActivity(streamOwner, activity); } /** * {@inheritDoc} */ public ExoSocialActivity getActivity(String activityId) { return activityStorage.getActivity(activityId); } /** * {@inheritDoc} */ public ExoSocialActivity getParentActivity(ExoSocialActivity comment) { return activityStorage.getParentActivity(comment); } /** * {@inheritDoc} */ public void updateActivity(ExoSocialActivity existingActivity) { activityStorage.updateActivity(existingActivity); } /** * {@inheritDoc} */ public void deleteActivity(ExoSocialActivity existingActivity) { Validate.notNull(existingActivity.getId(), "existingActivity.getId() must not be null!"); deleteActivity(existingActivity.getId()); } /** * {@inheritDoc} */ public void deleteActivity(String activityId) { activityStorage.deleteActivity(activityId); } /** * {@inheritDoc} */ public void saveComment(ExoSocialActivity existingActivity, ExoSocialActivity newComment) throws ActivityStorageException { activityStorage.saveComment(existingActivity, newComment); } /** * {@inheritDoc} */ public RealtimeListAccess<ExoSocialActivity> getCommentsWithListAccess(ExoSocialActivity existingActivity) { return new CommentsRealtimeListAccess(activityStorage, existingActivity); } /** * {@inheritDoc} */ public void deleteComment(String activityId, String commentId) { activityStorage.deleteComment(activityId, commentId); } /** * {@inheritDoc} */ public void deleteComment(ExoSocialActivity existingActivity, ExoSocialActivity existingComment) { deleteComment(existingActivity.getId(), existingComment.getId()); } /** * {@inheritDoc} */ public void saveLike(ExoSocialActivity existingActivity, Identity identity) { String[] identityIds = existingActivity.getLikeIdentityIds(); if (ArrayUtils.contains(identityIds, identity.getId())) { LOG.warn("activity is already liked by identity: " + identity); return; } identityIds = (String[]) ArrayUtils.add(identityIds, identity.getId()); existingActivity.setLikeIdentityIds(identityIds); updateActivity(existingActivity); } /** * {@inheritDoc} */ public void deleteLike(ExoSocialActivity activity, Identity identity) { String[] identityIds = activity.getLikeIdentityIds(); if (ArrayUtils.contains(identityIds, identity.getId())) { identityIds = (String[]) ArrayUtils.removeElement(identityIds, identity.getId()); activity.setLikeIdentityIds(identityIds); updateActivity(activity); } else { LOG.warn("activity is not liked by identity: " + identity); } } /** * {@inheritDoc} */ public RealtimeListAccess<ExoSocialActivity> getActivitiesWithListAccess(Identity existingIdentity) { return new ActivitiesRealtimeListAccess(activityStorage, ActivityType.USER_ACTIVITIES, existingIdentity); } /** * {@inheritDoc} */ public RealtimeListAccess<ExoSocialActivity> getActivitiesOfConnectionsWithListAccess(Identity existingIdentity) { return new ActivitiesRealtimeListAccess(activityStorage, ActivityType.CONNECTIONS_ACTIVITIES, existingIdentity); } /** * {@inheritDoc} */ public RealtimeListAccess<ExoSocialActivity> getActivitiesOfUserSpacesWithListAccess(Identity existingIdentity) { return new ActivitiesRealtimeListAccess(activityStorage, ActivityType.USER_SPACE_ACTIVITIES, existingIdentity); } /** * {@inheritDoc} */ public RealtimeListAccess<ExoSocialActivity> getActivityFeedWithListAccess(Identity existingIdentity) { return new ActivitiesRealtimeListAccess(activityStorage, ActivityType.ACTIVITY_FEED, existingIdentity); } /** * {@inheritDoc} */ public void addProcessor(ActivityProcessor processor) { activityStorage.getActivityProcessors().add(processor); LOG.debug("added activity processor " + processor.getClass()); } /** * {@inheritDoc} */ public void addProcessorPlugin(BaseActivityProcessorPlugin plugin) { this.addProcessor(plugin); } /** * {@inheritDoc} */ public ExoSocialActivity saveActivity(Identity streamOwner, ExoSocialActivity newActivity) { saveActivityNoReturn(streamOwner, newActivity); return newActivity; } /** * {@inheritDoc} */ public ExoSocialActivity saveActivity(ExoSocialActivity newActivity) { saveActivityNoReturn(newActivity); return newActivity; } /** * {@inheritDoc} */ public List<ExoSocialActivity> getActivities(Identity identity) throws ActivityStorageException { List<ExoSocialActivity> activityList = Collections.emptyList(); try { ExoSocialActivity[] activities = getActivitiesWithListAccess(identity).load(0, DEFAULT_LIMIT); activityList = Arrays.asList(activities); } catch (Exception e) { LOG.warn("Failed to get activities by identity: " + identity); } return activityList; } /** * {@inheritDoc} */ public List<ExoSocialActivity> getActivities(Identity identity, long start, long limit) throws ActivityStorageException { //validateStartLimit(start, limit); return activityStorage.getUserActivities(identity, start, limit); } /** * {@inheritDoc} * The result list is returned with 30 maximum activities. */ public List<ExoSocialActivity> getActivitiesOfConnections(Identity ownerIdentity) throws ActivityStorageException { List<ExoSocialActivity> activityList = Collections.emptyList(); try { ExoSocialActivity[] activities = getActivitiesOfConnectionsWithListAccess(ownerIdentity).load(0, 30); activityList = Arrays.asList(activities); } catch (Exception e) { LOG.warn("Failed to get activities of connections!"); } return activityList; } /** * {@inheritDoc} */ public List<ExoSocialActivity> getActivitiesOfConnections(Identity ownerIdentity, int offset, int limit) throws ActivityStorageException { validateStartLimit(offset, limit); List<Identity> connectionList = null; try { ListAccess<Identity> connectionsWithListAccess = identityManager.getConnectionsWithListAccess(ownerIdentity); connectionList = Arrays.asList(connectionsWithListAccess.load(0, connectionsWithListAccess.getSize())); } catch (Exception e) { LOG.error("Failed to getActivitiesOfIdentities of: " + ownerIdentity.getRemoteId(), e); } return activityStorage.getActivitiesOfIdentities(connectionList, offset, limit); } /** * {@inheritDoc} * By default, the activity list is composed of all spaces' activities. * Each activity list of the space contains maximum 20 activities * and are returned sorted starting from the most recent. */ public List<ExoSocialActivity> getActivitiesOfUserSpaces(Identity ownerIdentity) { return getActivitiesOfUserSpacesWithListAccess(ownerIdentity).loadAsList(0, DEFAULT_LIMIT); } /** * {@inheritDoc} * Return maximum number of activities: 40 */ public List<ExoSocialActivity> getActivityFeed(Identity identity) { return getActivityFeedWithListAccess(identity).loadAsList(0, DEFAULT_LIMIT * 2); } /** * {@inheritDoc} */ public void removeLike(ExoSocialActivity existingActivity, Identity existingIdentity) { deleteLike(existingActivity, existingIdentity); } /** * {@inheritDoc} */ public List<ExoSocialActivity> getComments(ExoSocialActivity existingActivity) { return getCommentsWithListAccess(existingActivity).loadAsList(0, DEFAULT_LIMIT * 2); /* String activityId = existingActivity.getId(); List<ExoSocialActivity> returnComments = new ArrayList<ExoSocialActivity>(); // reload activity to make sure to have the most update activity existingActivity = getActivity(activityId); String rawCommentIds = existingActivity.getReplyToId(); // rawCommentIds can be: null || ,a,b,c,d if (rawCommentIds != null) { String[] commentIds = rawCommentIds.split(","); commentIds = (String[]) ArrayUtils.removeElement(commentIds, ""); for (String commentId : commentIds) { ExoSocialActivity comment = activityStorage.getActivity(commentId); processActivitiy(comment); returnComments.add(comment); } } return returnComments; */ } /** * {@inheritDoc} */ public ExoSocialActivity recordActivity(Identity owner, String type, String title) throws ActivityStorageException { ExoSocialActivity newActivity = new ExoSocialActivityImpl(owner.getId(), type, title); saveActivity(owner, newActivity); return newActivity; } /** * {@inheritDoc} */ public int getActivitiesCount(Identity owner) throws ActivityStorageException { return activityStorage.getNumberOfUserActivities(owner); } /** * {@inheritDoc} */ public void processActivitiy(ExoSocialActivity activity) { return; } /** * {@inheritDoc} */ public ExoSocialActivity recordActivity(Identity owner, ExoSocialActivity activity) throws Exception { saveActivity(owner, activity); return activity; } /** * {@inheritDoc} */ public ExoSocialActivity recordActivity(Identity owner, String type, String title, String body) throws ActivityStorageException { String userId = owner.getId(); ExoSocialActivity activity = new ExoSocialActivityImpl(userId, type, title, body); saveActivity(owner, activity); return activity; } /** * Validates the start and limit for duplicated method. * The limit must be greater than or equal to start. * The limit must be equal to or greater than start by {@link #DEFAULT_LIMIT} * * @param start * @param limit */ private void validateStartLimit(long start, long limit) { Validate.isTrue(limit >= start, "'limit' must be greater than or equal to 'start'"); Validate.isTrue(limit - start <= DEFAULT_LIMIT, "'limit - start' must be less than or equal to " + DEFAULT_LIMIT); } /** * Gets stream owner from identityId = newActivity.userId. * @param newActivity the new activity * @return the identity stream owner */ private Identity getStreamOwner(ExoSocialActivity newActivity) { Validate.notNull(newActivity.getUserId(), "activity.getUserId() must not be null!"); return identityManager.getIdentity(newActivity.getUserId(), false); } /** * Gets spaceService. * * @return spaceService */ private SpaceService getSpaceService() { if (spaceService == null) { spaceService = (SpaceService) PortalContainer.getInstance() .getComponentInstanceOfType(SpaceService.class); } return spaceService; } /** * Gets identityManager. * * @return identityManager */ private IdentityManager getIdentityManager() { return this.identityManager; } }