package com.collabinate.server.resources;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.DateTime;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.data.Tag;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;
import com.collabinate.server.activitystreams.Activity;
import com.collabinate.server.activitystreams.ActivityStreamsCollection;
import com.collabinate.server.activitystreams.ActivityStreamsObject;
import com.collabinate.server.engine.CollabinateReader;
import com.collabinate.server.engine.CollabinateWriter;
import com.google.common.hash.Hashing;
/**
* Restful resource representing a series of activities for an entity.
*
* @author mafuba
*
*/
public class StreamResource extends ServerResource
{
@Get("json")
public Representation getStream()
{
// extract necessary information from the context
CollabinateReader reader = (CollabinateReader)getContext()
.getAttributes().get("collabinateReader");
String tenantId = getAttribute("tenantId");
String entityId = getAttribute("entityId");
String skipString = getQueryValue("skip");
String takeString = getQueryValue("take");
int skip = null == skipString ? 0 : Integer.parseInt(skipString);
int take = null == takeString ? DEFAULT_COUNT :
Integer.parseInt(takeString);
ActivityStreamsCollection activitiesCollection =
reader.getStream(tenantId, entityId, skip, take);
appendCollections(activitiesCollection, reader, tenantId, entityId);
String result = activitiesCollection.toString();
Representation representation = new StringRepresentation(
result, MediaType.APPLICATION_JSON);
representation.setTag(new Tag(Hashing.murmur3_128().hashUnencodedChars(
result+tenantId+entityId+skipString+takeString)
.toString(), false));
return representation;
}
/**
* Appends the comments and likes collection values to each of the items
* in the given collection of activities, according to the value of the
* comments and likes query values. Note that even zero values will cause
* empty collections (with the correct counts) to be appended.
*
* @param activitiesCollection The collection of activities that will have
* comments and likes added.
* @param reader The CollabinateReader to use for getting the collections.
* @param tenantId The tenant ID.
* @param entityId The entity ID.
*/
private void appendCollections(
ActivityStreamsCollection activitiesCollection,
CollabinateReader reader, String tenantId, String entityId)
{
String commentsString = getQueryValue("comments");
String likesString = getQueryValue("likes");
String userLikedString = getQueryValue("userLiked");
if (null != commentsString ||
null != likesString ||
null != userLikedString)
{
boolean processComments = null != commentsString;
boolean processLikes = null != likesString;
boolean processUserLiked = null != userLikedString;
int comments = processComments ?
Integer.parseInt(commentsString) : 0;
int likes = processLikes ?
Integer.parseInt(likesString) : 0;
String likingUser = processUserLiked ?
userLikedString : null;
List<ActivityStreamsObject> activities =
activitiesCollection.getItems();
List<ActivityStreamsObject> updatedActivities =
new ArrayList<ActivityStreamsObject>();
for (ActivityStreamsObject activity : activities)
{
if (processComments)
{
activity.setReplies(reader.getComments(tenantId, entityId,
activity.getId(), 0, comments));
}
if (processLikes)
{
activity.setLikes(reader.getLikes(tenantId, entityId,
activity.getId(), 0, likes));
}
if (processUserLiked)
{
DateTime likedDate = reader.userLikesActivity(
tenantId, likingUser, entityId, activity.getId());
if (null != likedDate)
{
activity.setCollabinateValue("likedByUser",
likedDate.toString());
}
}
updatedActivities.add(activity);
}
activitiesCollection.setItems(updatedActivities);
}
}
@Post
public void addActivity(String content)
{
// extract necessary information from the context
CollabinateWriter writer = (CollabinateWriter)getContext()
.getAttributes().get("collabinateWriter");
String tenantId = getAttribute("tenantId");
String entityId = getAttribute("entityId");
String ignoreCommentsString = getQueryValue("ignoreComments");
String ignoreLikesString = getQueryValue("ignoreLikes");
if (null == writer)
throw new IllegalStateException(
"Context does not contain a CollabinateWriter");
// create an activity from the given content
Activity activity = new Activity(content);
// generate an id and relocate the original if necessary
String originalId = activity.getId();
String activityId = ActivityStreamsObject.generateUuidUrn();
activity.setId(activityId);
if (null != originalId && !originalId.equals(""))
{
activity.setCollabinateValue(ORIGINAL_ID, originalId);
}
// keep track of the entityID in the activity
activity.setCollabinateValue("entityId", entityId);
writer.addActivity(tenantId, entityId, activity);
// if the activity has comments and we're not ignoring them,
// add them to the database properly
boolean ignoreComments = null != ignoreCommentsString &&
!ignoreCommentsString.equalsIgnoreCase("false");
ActivityStreamsCollection replies = activity.getReplies();
if (!ignoreComments && null != replies && replies.size() > 0)
{
for (ActivityStreamsObject comment : replies.getItems())
{
// ensure the comment has an id - set to generated id if not
String commentId = comment.getId();
if (null == commentId || commentId.equals(""))
{
commentId = ActivityStreamsObject.generateUuidUrn();
comment.setId(commentId);
}
// we leave the userId as null because determining the user
// from previously populated comments can be done in multiple
// ways, and may not work with the way we handle IDs
writer.addComment(tenantId, entityId, activityId, null,
comment);
}
}
// if the activity has likes and we're not ignoring them,
// add them to the database properly
boolean ignoreLikes = null != ignoreLikesString &&
!ignoreLikesString.equalsIgnoreCase("false");
ActivityStreamsCollection likes = activity.getLikes();
if (!ignoreLikes && null != likes && likes.size() > 0)
{
for (ActivityStreamsObject likeObject : likes.getItems())
{
Activity like = new Activity(likeObject.toString());
ActivityStreamsObject actor = like.getActor();
if (null != actor)
{
String userId = actor.getId();
if (null != userId && !userId.equals(""))
{
writer.likeActivity(tenantId, userId, entityId,
activityId);
}
}
}
}
// return the activity in the response body
getResponse().setEntity(activity.toString(),
MediaType.APPLICATION_JSON);
//TODO: return relative reference location
setLocationRef(new Reference(getReference())
.addSegment(activity.getId()));
setStatus(Status.SUCCESS_CREATED);
}
private static final int DEFAULT_COUNT = 20;
private static final String ORIGINAL_ID = "originalId";
}