Created
September 27, 2011 09:24
-
-
Save hoatle/1244670 to your computer and use it in GitHub Desktop.
ActivityStreamResources.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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