Skip to content

Instantly share code, notes, and snippets.

@hoatle
Created September 27, 2011 09:24
Show Gist options
  • Save hoatle/1244670 to your computer and use it in GitHub Desktop.
Save hoatle/1244670 to your computer and use it in GitHub Desktop.
ActivityStreamResources.java
/*
* Copyright (C) 2003-2011 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.exoplatform.social.service.rest.api;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.rest.resource.ResourceContainer;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.social.common.RealtimeListAccess;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.manager.ActivityManager;
import org.exoplatform.social.core.storage.ActivityStorageException;
import org.exoplatform.social.service.rest.SecurityManager;
import org.exoplatform.social.service.rest.Util;
import org.exoplatform.social.service.rest.api.models.ActivityRest;
import org.exoplatform.social.service.rest.api.models.ActivityStreamRest;
import org.exoplatform.social.service.rest.api.models.IdentityRest;
/**
* This service allows accessing to:
* - activity stream (list of activities) of an owner identity.
* - activity feed (all activities of the authenticated identity, his connections and his spaces).
* - activity stream of the authenticated identity's connections.
* - activity stream of the authenticated identity's spaces.
*
* @author <a href="http://hoatle.net">hoatle (hoatlevan at gmail dot com)</a>
* @since Sep 22, 2011
* @since 1.2.3
*/
@Path("api/social/" + VersionResources.LATEST_VERSION + "/{portalContainerName}/activity_stream/")
public class ActivityStreamResources implements ResourceContainer {
private static final Log LOG = ExoLogger.getLogger(ActivityStreamResources.class.getName());
private static final String[] SUPPORTED_FORMATS = new String[] {"json"};
private static final int MAX_LIMIT = 100;
private static final int MAX_NUMBER_OF_COMMENTS = 100;
private static final int MAX_NUMBER_OF_LIKES = 100;
/**
* Gets activity stream of a specified identity, could be user identity, space identity or any type of identities.
*
* @param uriInfo The uri info
* @param portalContainerName the portal container name
* @param identityId The identity id.
* There is one special identityId: "me" standing for the authenticated user who make this request.
* @param format The response format type, for example: json, xml...
* @param limit Specifies the number of activities to retrieve. Must be less than or equal to 100.
* The value you pass as limit is a maximum number of activities to be returned.
* The actual number of activities you receive maybe less than limit.
* If no specified, 100 will be the default value.
* @param sinceId Returns the activities having the created timestamps greater than
* the specified sinceId's created timestamp
* @param maxId Returns the activities having the created timestamp less than the specified maxId's created
* timestamp. Note that sinceId and maxId must not be defined in one request,
* if they are, the sinceId query param is chosen.
* @param numberOfComments Specifies the latest number of comments to be displayed along with each activity.
* By default, numberOfComments=0. If numberOfComments is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number of
* comments is less than the provided positive number, the number of actual comments must be
* returned. If the total number of comments is more than 100,
* it's recommended to use: "activity/:activityId/comments.format" instead
* @param numberOfLikes Specifies the latest number of detailed likes to be returned along with this activity.
* By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number
* of likes is less than the provided positive number, the number of actual likes must be
* returned. If the total number of likes is more than 100, it's recommended to use:
* "activity/:activityId/likes.format" instead.
* @return the response
*/
@GET
@Path("{identityId}.{format}")
public Response getActivityStreamByIdentityId(@Context UriInfo uriInfo,
@PathParam("portalContainerName") String portalContainerName,
@PathParam("identityId") String identityId,
@PathParam("format") String format,
@QueryParam("limit") int limit,
@QueryParam("since_id") String sinceId,
@QueryParam("max_id") String maxId,
@QueryParam("number_of_comments") int numberOfComments,
@QueryParam("number_of_likes") int numberOfLikes) {
if (!isAuthenticated()) {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
PortalContainer portalContainer = Util.getPortalContainerByName(portalContainerName);
if (portalContainer == null) {
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
MediaType mediaType = Util.getMediaType(format, SUPPORTED_FORMATS);
Identity targetIdentity = Util.getIdentityManager(portalContainerName).getIdentity(identityId, false);
if (targetIdentity == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
//check permission
boolean canAccess = SecurityManager.canAccessActivityStream(portalContainer,
SecurityManager.getAuthenticatedUserIdentity(),
targetIdentity);
if (!canAccess) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
HashMap<String, Object> responseEntity = new HashMap<String, Object>();
int maxLimit = limit == 0 ? MAX_LIMIT : limit;
ExoSocialActivity baseActivity = null;
boolean getOlder = false;
//if sinceId and maxId is both passed, sinceId is chosen
ActivityManager activityManager = Util.getActivityManager(portalContainerName);
try {
if (maxId != null && sinceId == null) {
getOlder = true;
baseActivity = activityManager.getActivity(maxId);
} else if (sinceId != null) {
baseActivity = activityManager.getActivity(sinceId);
}
} catch (UndeclaredThrowableException udte) { //bad thing from cache service that we have to handle like this :(
if (udte.getCause() instanceof ActivityStorageException) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
} else {
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
RealtimeListAccess<ExoSocialActivity> rala = activityManager.getActivitiesWithListAccess(targetIdentity);
List<ExoSocialActivity> activityList;
if (getOlder) {
activityList = rala.loadOlder(baseActivity, maxLimit);
} else if (sinceId != null) {
activityList = rala.loadNewer(baseActivity, maxLimit);
} else {
activityList = rala.loadAsList(0, maxLimit);
}
List<Object> activityItems = new ArrayList<Object>();
numberOfComments = Math.min(numberOfComments, MAX_NUMBER_OF_COMMENTS);
numberOfLikes = Math.min(numberOfLikes, MAX_NUMBER_OF_LIKES);
for (ExoSocialActivity activity : activityList) {
ActivityRest activityItem = new ActivityRest(activity, portalContainerName);
activityItem.setPosterIdentity(new IdentityRest(activity.getUserId(), portalContainerName));
activityItem.setActivityStream(new ActivityStreamRest(activity.getActivityStream()));
activityItem.setNumberOfComments(numberOfComments, activity, portalContainerName);
activityItem.setNumberOfLikes(numberOfLikes, activity, portalContainerName);
try {
activityItems.add(Util.beanToMap(activityItem));
} catch (Exception e) {
//BAD here caused by Util#beanToMap
LOG.warn(e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
responseEntity.put("activities", activityItems);
return Util.getResponse(responseEntity, uriInfo, mediaType, Response.Status.OK);
}
/**
* Gets the activity stream feed of a specified user identity.
*
* @param uriInfo The uri info
* @param portalContainerName The portal container name
* @param format The response format type, for example: json, xml...
* @param limit Specifies the number of activities to retrieve. Must be less than or equal to 100.
* The value you pass as limit is a maximum number of activities to be returned.
* The actual number of activities you receive maybe less than limit.
* If no specified, 100 will be the default value.
* @param sinceId Returns the activities having the created timestamps greater than
* the specified sinceId's created timestamp
* @param maxId Returns the activities having the created timestamp less than the specified maxId's created
* timestamp. Note that sinceId and maxId must not be defined in one request,
* if they are, the sinceId query param is chosen.
* @param numberOfComments Specifies the latest number of comments to be displayed along with each activity.
* By default, numberOfComments=0. If numberOfComments is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number of
* comments is less than the provided positive number, the number of actual comments must be
* returned. If the total number of comments is more than 100,
* it's recommended to use: "activity/:activityId/comments.format" instead
* @param numberOfLikes Specifies the latest number of detailed likes to be returned along with this activity.
* By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number
* of likes is less than the provided positive number, the number of actual likes must be
* returned. If the total number of likes is more than 100, it's recommended to use:
* "activity/:activityId/likes.format" instead.
* @return the response
*/
@GET
@Path("feed.{format}")
public Response getActivityFeedOfAnIdentityId(@Context UriInfo uriInfo,
@PathParam("portalContainerName") String portalContainerName,
@PathParam("format") String format,
@QueryParam("limit") int limit,
@QueryParam("since_id") String sinceId,
@QueryParam("max_id") String maxId,
@QueryParam("number_of_comments") int numberOfComments,
@QueryParam("number_of_likes") int numberOfLikes) {
//TODO implement this (Vien)
return null;
}
/**
* Gets activities of spaces that the specified identity is the member or manager.
*
* @param uriInfo The uri info
* @param portalContainerName The portal container name
* @param format The response format type, for example: json, xml...
* @param limit Specifies the number of activities to retrieve. Must be less than or equal to 100.
* The value you pass as limit is a maximum number of activities to be returned.
* The actual number of activities you receive maybe less than limit.
* If no specified, 100 will be the default value.
* @param sinceId Returns the activities having the created timestamps greater than
* the specified sinceId's created timestamp
* @param maxId Returns the activities having the created timestamp less than the specified maxId's created
* timestamp. Note that sinceId and maxId must not be defined in one request,
* if they are, the sinceId query param is chosen.
* @param numberOfComments Specifies the latest number of comments to be displayed along with each activity.
* By default, numberOfComments=0. If numberOfComments is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number of
* comments is less than the provided positive number, the number of actual comments must be
* returned. If the total number of comments is more than 100,
* it's recommended to use: "activity/:activityId/comments.format" instead
* @param numberOfLikes Specifies the latest number of detailed likes to be returned along with this activity.
* By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number
* of likes is less than the provided positive number, the number of actual likes must be
* returned. If the total number of likes is more than 100, it's recommended to use:
* "activity/:activityId/likes.format" instead.
* @return the response
*/
@GET
@Path("spaces.{format}")
public Response getActivitySpacesOfAnIdentityId(@Context UriInfo uriInfo,
@PathParam("portalContainerName") String portalContainerName,
@PathParam("format") String format,
@QueryParam("limit") int limit,
@QueryParam("since_id") String sinceId,
@QueryParam("max_id") String maxId,
@QueryParam("number_of_comments") int numberOfComments,
@QueryParam("number_of_likes") int numberOfLikes) {
//TODO implement this (Thanh)
return null;
}
/**
* Gets activities of connections of a specified identity.
*
* @param uriInfo The uri info
* @param portalContainerName The portal container name
* @param format The response format type, for example: json, xml...
* @param limit Specifies the number of activities to retrieve. Must be less than or equal to 100.
* The value you pass as limit is a maximum number of activities to be returned.
* The actual number of activities you receive maybe less than limit.
* If no specified, 100 will be the default value.
* @param sinceId Returns the activities having the created timestamps greater than
* the specified sinceId's created timestamp
* @param maxId Returns the activities having the created timestamp less than the specified maxId's created
* timestamp. Note that sinceId and maxId must not be defined in one request,
* if they are, the sinceId query param is chosen.
* @param numberOfComments Specifies the latest number of comments to be displayed along with each activity.
* By default, numberOfComments=0. If numberOfComments is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number of
* comments is less than the provided positive number, the number of actual comments must be
* returned. If the total number of comments is more than 100,
* it's recommended to use: "activity/:activityId/comments.format" instead
* @param numberOfLikes Specifies the latest number of detailed likes to be returned along with this activity.
* By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is
* considered as a limit number that must be equal or less than 100. If the actual number
* of likes is less than the provided positive number, the number of actual likes must be
* returned. If the total number of likes is more than 100, it's recommended to use:
* "activity/:activityId/likes.format" instead.
* @return the response
*/
@GET
@Path("connections.{format}")
public Response getActivityConnectionsOfAnIdentityId(@Context UriInfo uriInfo,
@PathParam("portalContainerName") String portalContainerName,
@PathParam("format") String format,
@QueryParam("limit") int limit,
@QueryParam("since_id") String sinceId,
@QueryParam("max_id") String maxId,
@QueryParam("number_of_comments") int numberOfComments,
@QueryParam("number_of_likes") int numberOfLikes) {
//TODO implement this (Hanh)
return null;
}
private boolean isAuthenticated() {
return (ConversationState.getCurrent()!= null && ConversationState.getCurrent().getIdentity() != null &&
ConversationState.getCurrent().getIdentity().getUserId() != null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment