mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)
125605 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2) 125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125783 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,157 +1,157 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.domain.activities.ActivityFeedEntity;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.rest.api.Activities;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.impl.activities.ActivitySummaryParser;
|
||||
import org.alfresco.rest.api.model.Activity;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
* Centralises access to activities services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ActivitiesImpl implements Activities
|
||||
{
|
||||
private static final String ACTIVITIES_FORMAT = "json";
|
||||
|
||||
private People people;
|
||||
private ActivityService activityService;
|
||||
private ActivitySummaryParser activitySummaryParser;
|
||||
private TenantService tenantService;
|
||||
private Sites sites;
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setTenantService(TenantService tenantService)
|
||||
{
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
public void setActivitySummaryParser(ActivitySummaryParser activitySummaryParser)
|
||||
{
|
||||
this.activitySummaryParser = activitySummaryParser;
|
||||
}
|
||||
|
||||
public Map<String, Object> getActivitySummary(ActivityFeedEntity entity) throws JSONException
|
||||
{
|
||||
Map<String, Object> activitySummary = activitySummaryParser.parse(entity.getActivityType(), entity.getActivitySummary());
|
||||
return activitySummary;
|
||||
}
|
||||
|
||||
private String getSiteId(String siteNetwork)
|
||||
{
|
||||
String siteId = siteNetwork;
|
||||
|
||||
int idx = siteNetwork.lastIndexOf(TenantService.SEPARATOR);
|
||||
if(idx != -1)
|
||||
{
|
||||
siteId = siteNetwork.substring(idx + 1);
|
||||
}
|
||||
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Activity> getUserActivities(String personId, final Parameters parameters)
|
||||
{
|
||||
personId = people.validatePerson(personId);
|
||||
|
||||
Paging paging = parameters.getPaging();
|
||||
String siteId = parameters.getParameter("siteId");
|
||||
String who = parameters.getParameter("who");
|
||||
ActivityWho activityWho = null;
|
||||
if(who != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
activityWho = ActivityWho.valueOf(who);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException("Parameter who should be one of " + Arrays.toString(ActivityWho.values()));
|
||||
}
|
||||
}
|
||||
|
||||
if(siteId != null && !siteId.equals(""))
|
||||
{
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new EntityNotFoundException(siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PagingResults<ActivityFeedEntity> activities = null;
|
||||
|
||||
if(activityWho == null)
|
||||
{
|
||||
activities = activityService.getPagedUserFeedEntries(personId, siteId, false, false, -1, Util.getPagingRequest(paging));
|
||||
}
|
||||
else if(activityWho.equals(ActivityWho.me))
|
||||
{
|
||||
activities = activityService.getPagedUserFeedEntries(personId, siteId, false, true, -1, Util.getPagingRequest(paging));
|
||||
}
|
||||
else if(activityWho.equals(ActivityWho.others))
|
||||
{
|
||||
activities = activityService.getPagedUserFeedEntries(personId, siteId, true, false, -1, Util.getPagingRequest(paging));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Who argument is invalid.");
|
||||
}
|
||||
|
||||
List<ActivityFeedEntity> feedEntities = activities.getPage();
|
||||
List<Activity> ret = new ArrayList<Activity>(feedEntities.size());
|
||||
for(ActivityFeedEntity entity : feedEntities)
|
||||
{
|
||||
String feedSiteId = getSiteId(entity.getSiteNetwork());
|
||||
String networkId = tenantService.getDomain(entity.getSiteNetwork());
|
||||
Activity activity = new Activity(entity.getId(), networkId, feedSiteId, entity.getFeedUserId(), entity.getPostUserId(),
|
||||
entity.getPostDate(), entity.getActivityType(), getActivitySummary(entity));
|
||||
ret.add(activity);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, ret, activities.hasMoreItems(), activities.getTotalResultCount().getFirst());
|
||||
}
|
||||
catch(JSONException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.domain.activities.ActivityFeedEntity;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.rest.api.Activities;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.impl.activities.ActivitySummaryParser;
|
||||
import org.alfresco.rest.api.model.Activity;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
* Centralises access to activities services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ActivitiesImpl implements Activities
|
||||
{
|
||||
private static final String ACTIVITIES_FORMAT = "json";
|
||||
|
||||
private People people;
|
||||
private ActivityService activityService;
|
||||
private ActivitySummaryParser activitySummaryParser;
|
||||
private TenantService tenantService;
|
||||
private Sites sites;
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setTenantService(TenantService tenantService)
|
||||
{
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
public void setActivitySummaryParser(ActivitySummaryParser activitySummaryParser)
|
||||
{
|
||||
this.activitySummaryParser = activitySummaryParser;
|
||||
}
|
||||
|
||||
public Map<String, Object> getActivitySummary(ActivityFeedEntity entity) throws JSONException
|
||||
{
|
||||
Map<String, Object> activitySummary = activitySummaryParser.parse(entity.getActivityType(), entity.getActivitySummary());
|
||||
return activitySummary;
|
||||
}
|
||||
|
||||
private String getSiteId(String siteNetwork)
|
||||
{
|
||||
String siteId = siteNetwork;
|
||||
|
||||
int idx = siteNetwork.lastIndexOf(TenantService.SEPARATOR);
|
||||
if(idx != -1)
|
||||
{
|
||||
siteId = siteNetwork.substring(idx + 1);
|
||||
}
|
||||
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Activity> getUserActivities(String personId, final Parameters parameters)
|
||||
{
|
||||
personId = people.validatePerson(personId);
|
||||
|
||||
Paging paging = parameters.getPaging();
|
||||
String siteId = parameters.getParameter("siteId");
|
||||
String who = parameters.getParameter("who");
|
||||
ActivityWho activityWho = null;
|
||||
if(who != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
activityWho = ActivityWho.valueOf(who);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException("Parameter who should be one of " + Arrays.toString(ActivityWho.values()));
|
||||
}
|
||||
}
|
||||
|
||||
if(siteId != null && !siteId.equals(""))
|
||||
{
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new EntityNotFoundException(siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PagingResults<ActivityFeedEntity> activities = null;
|
||||
|
||||
if(activityWho == null)
|
||||
{
|
||||
activities = activityService.getPagedUserFeedEntries(personId, siteId, false, false, -1, Util.getPagingRequest(paging));
|
||||
}
|
||||
else if(activityWho.equals(ActivityWho.me))
|
||||
{
|
||||
activities = activityService.getPagedUserFeedEntries(personId, siteId, false, true, -1, Util.getPagingRequest(paging));
|
||||
}
|
||||
else if(activityWho.equals(ActivityWho.others))
|
||||
{
|
||||
activities = activityService.getPagedUserFeedEntries(personId, siteId, true, false, -1, Util.getPagingRequest(paging));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Who argument is invalid.");
|
||||
}
|
||||
|
||||
List<ActivityFeedEntity> feedEntities = activities.getPage();
|
||||
List<Activity> ret = new ArrayList<Activity>(feedEntities.size());
|
||||
for(ActivityFeedEntity entity : feedEntities)
|
||||
{
|
||||
String feedSiteId = getSiteId(entity.getSiteNetwork());
|
||||
String networkId = tenantService.getDomain(entity.getSiteNetwork());
|
||||
Activity activity = new Activity(entity.getId(), networkId, feedSiteId, entity.getFeedUserId(), entity.getPostUserId(),
|
||||
entity.getPostDate(), entity.getActivityType(), getActivitySummary(entity));
|
||||
ret.add(activity);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, ret, activities.hasMoreItems(), activities.getTotalResultCount().getFirst());
|
||||
}
|
||||
catch(JSONException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,230 +1,230 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.forum.CommentService;
|
||||
import org.alfresco.rest.api.Comments;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Comment;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.lock.LockStatus;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
|
||||
/**
|
||||
* Centralises access to comment services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class CommentsImpl implements Comments
|
||||
{
|
||||
private Nodes nodes;
|
||||
private NodeService nodeService;
|
||||
private CommentService commentService;
|
||||
private ContentService contentService;
|
||||
private LockService lockService;
|
||||
private PermissionService permissionService;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setLockService(LockService lockService)
|
||||
{
|
||||
this.lockService = lockService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setCommentService(CommentService commentService)
|
||||
{
|
||||
this.commentService = commentService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
private Comment toComment(NodeRef nodeRef, NodeRef commentNodeRef)
|
||||
{
|
||||
Map<QName, Serializable> nodeProps = nodeService.getProperties(commentNodeRef);
|
||||
|
||||
ContentReader reader = contentService.getReader(commentNodeRef, ContentModel.PROP_CONTENT);
|
||||
if(reader != null)
|
||||
{
|
||||
String content = reader.getContentString();
|
||||
nodeProps.put(Comment.PROP_COMMENT_CONTENT, content);
|
||||
nodeProps.remove(ContentModel.PROP_CONTENT);
|
||||
}
|
||||
|
||||
boolean canEdit = true;
|
||||
boolean canDelete = true;
|
||||
|
||||
boolean isNodeLocked = false;
|
||||
boolean isWorkingCopy = false;
|
||||
|
||||
if(nodeRef != null)
|
||||
{
|
||||
Set<QName> aspects = nodeService.getAspects(nodeRef);
|
||||
|
||||
isWorkingCopy = aspects.contains(ContentModel.ASPECT_WORKING_COPY);
|
||||
if(!isWorkingCopy)
|
||||
{
|
||||
if(aspects.contains(ContentModel.ASPECT_LOCKABLE))
|
||||
{
|
||||
LockStatus lockStatus = lockService.getLockStatus(nodeRef);
|
||||
if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER)
|
||||
{
|
||||
isNodeLocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isNodeLocked || isWorkingCopy)
|
||||
{
|
||||
canEdit = false;
|
||||
canDelete = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
canEdit = permissionService.hasPermission(commentNodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED;
|
||||
canDelete = permissionService.hasPermission(commentNodeRef, PermissionService.DELETE) == AccessStatus.ALLOWED;
|
||||
}
|
||||
|
||||
Comment comment = new Comment(commentNodeRef.getId(), nodeProps, canEdit, canDelete);
|
||||
return comment;
|
||||
}
|
||||
|
||||
public Comment createComment(String nodeId, Comment comment)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot comment on this node");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef commentNode = commentService.createComment(nodeRef, comment.getTitle(), comment.getContent(), false);
|
||||
return toComment(nodeRef, commentNode);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Comment updateComment(String nodeId, Comment comment)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
String commentNodeId = comment.getId();
|
||||
NodeRef commentNodeRef = nodes.validateNode(commentNodeId);
|
||||
|
||||
String title = comment.getTitle();
|
||||
String content = comment.getContent();
|
||||
|
||||
if(content == null)
|
||||
{
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
commentService.updateComment(commentNodeRef, title, content);
|
||||
return toComment(nodeRef, commentNodeRef);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Comment> getComments(String nodeId, Paging paging)
|
||||
{
|
||||
final NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
|
||||
/* MNT-10536 : fix */
|
||||
final Set<QName> contentAndFolders =
|
||||
new HashSet<QName>(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT));
|
||||
if (!nodes.nodeMatches(nodeRef, contentAndFolders, null))
|
||||
{
|
||||
throw new InvalidArgumentException("NodeId of folder or content is expected");
|
||||
}
|
||||
|
||||
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
||||
final PagingResults<NodeRef> pagingResults = commentService.listComments(nodeRef, pagingRequest);
|
||||
|
||||
final List<NodeRef> page = pagingResults.getPage();
|
||||
List<Comment> comments = new AbstractList<Comment>()
|
||||
{
|
||||
@Override
|
||||
public Comment get(int index)
|
||||
{
|
||||
return toComment(nodeRef, page.get(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return page.size();
|
||||
}
|
||||
};
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, comments, pagingResults.hasMoreItems(), pagingResults.getTotalResultCount().getFirst());
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO validate that it is a comment of the node
|
||||
public void deleteComment(String nodeId, String commentNodeId)
|
||||
{
|
||||
try
|
||||
{
|
||||
nodes.validateNode(nodeId);
|
||||
NodeRef commentNodeRef = nodes.validateNode(commentNodeId);
|
||||
commentService.deleteComment(commentNodeRef);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.forum.CommentService;
|
||||
import org.alfresco.rest.api.Comments;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Comment;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.lock.LockStatus;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
|
||||
/**
|
||||
* Centralises access to comment services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class CommentsImpl implements Comments
|
||||
{
|
||||
private Nodes nodes;
|
||||
private NodeService nodeService;
|
||||
private CommentService commentService;
|
||||
private ContentService contentService;
|
||||
private LockService lockService;
|
||||
private PermissionService permissionService;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setLockService(LockService lockService)
|
||||
{
|
||||
this.lockService = lockService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setCommentService(CommentService commentService)
|
||||
{
|
||||
this.commentService = commentService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
private Comment toComment(NodeRef nodeRef, NodeRef commentNodeRef)
|
||||
{
|
||||
Map<QName, Serializable> nodeProps = nodeService.getProperties(commentNodeRef);
|
||||
|
||||
ContentReader reader = contentService.getReader(commentNodeRef, ContentModel.PROP_CONTENT);
|
||||
if(reader != null)
|
||||
{
|
||||
String content = reader.getContentString();
|
||||
nodeProps.put(Comment.PROP_COMMENT_CONTENT, content);
|
||||
nodeProps.remove(ContentModel.PROP_CONTENT);
|
||||
}
|
||||
|
||||
boolean canEdit = true;
|
||||
boolean canDelete = true;
|
||||
|
||||
boolean isNodeLocked = false;
|
||||
boolean isWorkingCopy = false;
|
||||
|
||||
if(nodeRef != null)
|
||||
{
|
||||
Set<QName> aspects = nodeService.getAspects(nodeRef);
|
||||
|
||||
isWorkingCopy = aspects.contains(ContentModel.ASPECT_WORKING_COPY);
|
||||
if(!isWorkingCopy)
|
||||
{
|
||||
if(aspects.contains(ContentModel.ASPECT_LOCKABLE))
|
||||
{
|
||||
LockStatus lockStatus = lockService.getLockStatus(nodeRef);
|
||||
if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER)
|
||||
{
|
||||
isNodeLocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isNodeLocked || isWorkingCopy)
|
||||
{
|
||||
canEdit = false;
|
||||
canDelete = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
canEdit = permissionService.hasPermission(commentNodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED;
|
||||
canDelete = permissionService.hasPermission(commentNodeRef, PermissionService.DELETE) == AccessStatus.ALLOWED;
|
||||
}
|
||||
|
||||
Comment comment = new Comment(commentNodeRef.getId(), nodeProps, canEdit, canDelete);
|
||||
return comment;
|
||||
}
|
||||
|
||||
public Comment createComment(String nodeId, Comment comment)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot comment on this node");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef commentNode = commentService.createComment(nodeRef, comment.getTitle(), comment.getContent(), false);
|
||||
return toComment(nodeRef, commentNode);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Comment updateComment(String nodeId, Comment comment)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
String commentNodeId = comment.getId();
|
||||
NodeRef commentNodeRef = nodes.validateNode(commentNodeId);
|
||||
|
||||
String title = comment.getTitle();
|
||||
String content = comment.getContent();
|
||||
|
||||
if(content == null)
|
||||
{
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
commentService.updateComment(commentNodeRef, title, content);
|
||||
return toComment(nodeRef, commentNodeRef);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Comment> getComments(String nodeId, Paging paging)
|
||||
{
|
||||
final NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
|
||||
/* MNT-10536 : fix */
|
||||
final Set<QName> contentAndFolders =
|
||||
new HashSet<QName>(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT));
|
||||
if (!nodes.nodeMatches(nodeRef, contentAndFolders, null))
|
||||
{
|
||||
throw new InvalidArgumentException("NodeId of folder or content is expected");
|
||||
}
|
||||
|
||||
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
||||
final PagingResults<NodeRef> pagingResults = commentService.listComments(nodeRef, pagingRequest);
|
||||
|
||||
final List<NodeRef> page = pagingResults.getPage();
|
||||
List<Comment> comments = new AbstractList<Comment>()
|
||||
{
|
||||
@Override
|
||||
public Comment get(int index)
|
||||
{
|
||||
return toComment(nodeRef, page.get(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return page.size();
|
||||
}
|
||||
};
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, comments, pagingResults.hasMoreItems(), pagingResults.getTotalResultCount().getFirst());
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO validate that it is a comment of the node
|
||||
public void deleteComment(String nodeId, String commentNodeId)
|
||||
{
|
||||
try
|
||||
{
|
||||
nodes.validateNode(nodeId);
|
||||
NodeRef commentNodeRef = nodes.validateNode(commentNodeId);
|
||||
commentService.deleteComment(commentNodeRef);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,30 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
|
||||
/**
|
||||
* Translates access denied exceptions from the service layer to API not found exception.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class DefaultExceptionHandler implements ExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Throwable t)
|
||||
{
|
||||
if(t instanceof AccessDeniedException)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new NotFoundException();
|
||||
}
|
||||
else if(t instanceof PermissionDeniedException)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
|
||||
/**
|
||||
* Translates access denied exceptions from the service layer to API not found exception.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class DefaultExceptionHandler implements ExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Throwable t)
|
||||
{
|
||||
if(t instanceof AccessDeniedException)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new NotFoundException();
|
||||
}
|
||||
else if(t instanceof PermissionDeniedException)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
public interface ExceptionHandler
|
||||
{
|
||||
boolean handle(Throwable t);
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
public interface ExceptionHandler
|
||||
{
|
||||
boolean handle(Throwable t);
|
||||
}
|
||||
|
@@ -1,46 +1,46 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
/**
|
||||
* An interceptor that catches exceptions and handlers them in some way, possibly by re-throwing as a different exception.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ExceptionInterceptor implements MethodInterceptor
|
||||
{
|
||||
private List<ExceptionHandler> exceptionHandlers;
|
||||
|
||||
public void setExceptionHandlers(List<ExceptionHandler> exceptionHandlers)
|
||||
{
|
||||
this.exceptionHandlers = exceptionHandlers;
|
||||
}
|
||||
|
||||
public ExceptionInterceptor()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable
|
||||
{
|
||||
try
|
||||
{
|
||||
return mi.proceed();
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
for(ExceptionHandler handler : exceptionHandlers)
|
||||
{
|
||||
if(handler.handle(t))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
/**
|
||||
* An interceptor that catches exceptions and handlers them in some way, possibly by re-throwing as a different exception.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ExceptionInterceptor implements MethodInterceptor
|
||||
{
|
||||
private List<ExceptionHandler> exceptionHandlers;
|
||||
|
||||
public void setExceptionHandlers(List<ExceptionHandler> exceptionHandlers)
|
||||
{
|
||||
this.exceptionHandlers = exceptionHandlers;
|
||||
}
|
||||
|
||||
public ExceptionInterceptor()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable
|
||||
{
|
||||
try
|
||||
{
|
||||
return mi.proceed();
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
for(ExceptionHandler handler : exceptionHandlers)
|
||||
{
|
||||
if(handler.handle(t))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,91 +1,91 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.opencmis.dictionary.QNameFilter;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Stores a set of excluded types, by full type name. The localName can be a wildcard (*) to indicate that the
|
||||
* whole namespace should be excluded.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ExcludedTypes
|
||||
{
|
||||
private List<QName> expectedTypes;
|
||||
private QNameFilter excludedTypes;
|
||||
private NodeService nodeService;
|
||||
|
||||
public void setExpectedTypes(List<String> expectedTypes)
|
||||
{
|
||||
if(expectedTypes != null && expectedTypes.size() > 0)
|
||||
{
|
||||
this.expectedTypes = new ArrayList<QName>(expectedTypes.size());
|
||||
|
||||
for(String type : expectedTypes)
|
||||
{
|
||||
final QName typeDef = QName.createQName(type);
|
||||
this.expectedTypes.add(typeDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setExcludedTypes(QNameFilter excludedTypes)
|
||||
{
|
||||
this.excludedTypes = excludedTypes;
|
||||
}
|
||||
|
||||
public boolean isExcluded(final NodeRef nodeRef)
|
||||
{
|
||||
boolean excluded = false;
|
||||
|
||||
QName nodeType = nodeService.getType(nodeRef);
|
||||
if(expectedTypes != null && !expectedTypes.contains(nodeType))
|
||||
{
|
||||
excluded = true;
|
||||
}
|
||||
|
||||
if(!excluded)
|
||||
{
|
||||
// need to run as system - caller may not be able to read the node's aspects
|
||||
// but we need to know what they are in order to determine exclusion.
|
||||
excluded = TenantUtil.runAsSystemTenant(new TenantRunAsWork<Boolean>()
|
||||
{
|
||||
@Override
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
boolean excluded = false;
|
||||
|
||||
// the node is a content node. Make sure it doesn't have an aspect in the excluded list.
|
||||
Set<QName> aspects = new HashSet<QName>(nodeService.getAspects(nodeRef));
|
||||
for(QName aspect : aspects)
|
||||
{
|
||||
if(excludedTypes.isExcluded(aspect))
|
||||
{
|
||||
excluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
}, TenantUtil.getCurrentDomain());
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.opencmis.dictionary.QNameFilter;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Stores a set of excluded types, by full type name. The localName can be a wildcard (*) to indicate that the
|
||||
* whole namespace should be excluded.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ExcludedTypes
|
||||
{
|
||||
private List<QName> expectedTypes;
|
||||
private QNameFilter excludedTypes;
|
||||
private NodeService nodeService;
|
||||
|
||||
public void setExpectedTypes(List<String> expectedTypes)
|
||||
{
|
||||
if(expectedTypes != null && expectedTypes.size() > 0)
|
||||
{
|
||||
this.expectedTypes = new ArrayList<QName>(expectedTypes.size());
|
||||
|
||||
for(String type : expectedTypes)
|
||||
{
|
||||
final QName typeDef = QName.createQName(type);
|
||||
this.expectedTypes.add(typeDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setExcludedTypes(QNameFilter excludedTypes)
|
||||
{
|
||||
this.excludedTypes = excludedTypes;
|
||||
}
|
||||
|
||||
public boolean isExcluded(final NodeRef nodeRef)
|
||||
{
|
||||
boolean excluded = false;
|
||||
|
||||
QName nodeType = nodeService.getType(nodeRef);
|
||||
if(expectedTypes != null && !expectedTypes.contains(nodeType))
|
||||
{
|
||||
excluded = true;
|
||||
}
|
||||
|
||||
if(!excluded)
|
||||
{
|
||||
// need to run as system - caller may not be able to read the node's aspects
|
||||
// but we need to know what they are in order to determine exclusion.
|
||||
excluded = TenantUtil.runAsSystemTenant(new TenantRunAsWork<Boolean>()
|
||||
{
|
||||
@Override
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
boolean excluded = false;
|
||||
|
||||
// the node is a content node. Make sure it doesn't have an aspect in the excluded list.
|
||||
Set<QName> aspects = new HashSet<QName>(nodeService.getAspects(nodeRef));
|
||||
for(QName aspect : aspects)
|
||||
{
|
||||
if(excludedTypes.isExcluded(aspect))
|
||||
{
|
||||
excluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
}, TenantUtil.getCurrentDomain());
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
}
|
||||
|
@@ -1,307 +1,307 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.favourites.PersonFavourite;
|
||||
import org.alfresco.repo.site.SiteDoesNotExistException;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.rest.api.Favourites;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.model.Document;
|
||||
import org.alfresco.rest.api.model.DocumentTarget;
|
||||
import org.alfresco.rest.api.model.Favourite;
|
||||
import org.alfresco.rest.api.model.Folder;
|
||||
import org.alfresco.rest.api.model.FolderTarget;
|
||||
import org.alfresco.rest.api.model.Site;
|
||||
import org.alfresco.rest.api.model.SiteImpl;
|
||||
import org.alfresco.rest.api.model.SiteTarget;
|
||||
import org.alfresco.rest.api.model.Target;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper.WalkerCallbackAdapter;
|
||||
import org.alfresco.service.cmr.favourites.FavouritesService;
|
||||
import org.alfresco.service.cmr.favourites.FavouritesService.Type;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Public REST API: Centralises access to favourites functionality and maps between representations repository and api representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class FavouritesImpl implements Favourites
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(FavouritesImpl.class);
|
||||
|
||||
private People people;
|
||||
private Sites sites;
|
||||
private Nodes nodes;
|
||||
private FavouritesService favouritesService;
|
||||
private SiteService siteService;
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setFavouritesService(FavouritesService favouritesService)
|
||||
{
|
||||
this.favouritesService = favouritesService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
private Target getTarget(PersonFavourite personFavourite)
|
||||
{
|
||||
Target target = null;
|
||||
NodeRef nodeRef = personFavourite.getNodeRef();
|
||||
Type type = personFavourite.getType();
|
||||
if(type.equals(Type.FILE))
|
||||
{
|
||||
Document document = nodes.getDocument(nodeRef);
|
||||
target = new DocumentTarget(document);
|
||||
}
|
||||
else if(type.equals(Type.FOLDER))
|
||||
{
|
||||
Folder folder = nodes.getFolder(nodeRef);
|
||||
target = new FolderTarget(folder);
|
||||
}
|
||||
else if(type.equals(Type.SITE))
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
String role = sites.getSiteRole(siteInfo.getShortName());
|
||||
Site site = new SiteImpl(siteInfo, role);
|
||||
target = new SiteTarget(site);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected favourite target type: " + type);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
private Favourite getFavourite(PersonFavourite personFavourite)
|
||||
{
|
||||
Favourite fav = new Favourite();
|
||||
fav.setTargetGuid(personFavourite.getNodeRef().getId());
|
||||
fav.setCreatedAt(personFavourite.getCreatedAt());
|
||||
Target target = getTarget(personFavourite);
|
||||
fav.setTarget(target);
|
||||
return fav;
|
||||
}
|
||||
|
||||
private CollectionWithPagingInfo<Favourite> wrap(Paging paging, PagingResults<PersonFavourite> personFavourites)
|
||||
{
|
||||
final List<PersonFavourite> page = personFavourites.getPage();
|
||||
final List<Favourite> list = new AbstractList<Favourite>()
|
||||
{
|
||||
@Override
|
||||
public Favourite get(int index)
|
||||
{
|
||||
PersonFavourite personFavourite = page.get(index);
|
||||
Favourite fav = getFavourite(personFavourite);
|
||||
return fav;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return page.size();
|
||||
}
|
||||
};
|
||||
Pair<Integer, Integer> pair = personFavourites.getTotalResultCount();
|
||||
Integer total = null;
|
||||
if(pair.getFirst().equals(pair.getSecond()))
|
||||
{
|
||||
total = pair.getFirst();
|
||||
}
|
||||
return CollectionWithPagingInfo.asPaged(paging, list, personFavourites.hasMoreItems(), total);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favourite addFavourite(String personId, Favourite favourite)
|
||||
{
|
||||
Favourite ret = null;
|
||||
|
||||
personId = people.validatePerson(personId, true);
|
||||
Target target = favourite.getTarget();
|
||||
if(target == null)
|
||||
{
|
||||
throw new InvalidArgumentException("target is missing");
|
||||
}
|
||||
else if(target instanceof SiteTarget)
|
||||
{
|
||||
SiteTarget siteTarget = (SiteTarget)target;
|
||||
NodeRef guid = siteTarget.getSite().getGuid();
|
||||
SiteInfo siteInfo = sites.validateSite(guid);
|
||||
NodeRef siteNodeRef = siteInfo.getNodeRef();
|
||||
String siteId = siteInfo.getShortName();
|
||||
|
||||
try
|
||||
{
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, siteNodeRef);
|
||||
ret = getFavourite(personFavourite);
|
||||
}
|
||||
catch(SiteDoesNotExistException e)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, siteId);
|
||||
}
|
||||
}
|
||||
else if(target instanceof DocumentTarget)
|
||||
{
|
||||
DocumentTarget documentTarget = (DocumentTarget)target;
|
||||
NodeRef nodeRef = documentTarget.getFile().getGuid();
|
||||
if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null))
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, nodeRef.getId());
|
||||
}
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef);
|
||||
ret = getFavourite(personFavourite);
|
||||
}
|
||||
else if(target instanceof FolderTarget)
|
||||
{
|
||||
FolderTarget folderTarget = (FolderTarget)target;
|
||||
NodeRef nodeRef = folderTarget.getFolder().getGuid();
|
||||
if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), Collections.singleton(SiteModel.TYPE_SITE)))
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, nodeRef.getId());
|
||||
}
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef);
|
||||
ret = getFavourite(personFavourite);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFavourite(String personId, String id)
|
||||
{
|
||||
personId = people.validatePerson(personId, true);
|
||||
NodeRef nodeRef = nodes.validateNode(id);
|
||||
boolean exists = false;
|
||||
|
||||
Type type = favouritesService.getType(nodeRef);
|
||||
if(type.equals(Type.SITE))
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// shouldn't happen because the type implies it's a site
|
||||
throw new AlfrescoRuntimeException("Unable to find site with nodeRef " + nodeRef);
|
||||
}
|
||||
exists = favouritesService.removeFavourite(personId, siteInfo.getNodeRef());
|
||||
}
|
||||
else if(type.equals(Type.FILE))
|
||||
{
|
||||
exists = favouritesService.removeFavourite(personId, nodeRef);
|
||||
}
|
||||
else if(type.equals(Type.FOLDER))
|
||||
{
|
||||
exists = favouritesService.removeFavourite(personId, nodeRef);
|
||||
}
|
||||
if(!exists)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, id);
|
||||
}
|
||||
}
|
||||
|
||||
public Favourite getFavourite(String personId, String favouriteId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(favouriteId);
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.getFavourite(personId, nodeRef);
|
||||
if(personFavourite != null)
|
||||
{
|
||||
Favourite favourite = getFavourite(personFavourite);
|
||||
return favourite;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, favouriteId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Favourite> getFavourites(String personId, final Parameters parameters)
|
||||
{
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
Paging paging = parameters.getPaging();
|
||||
|
||||
final Set<Type> filteredByClientQuery = new HashSet<Type>();
|
||||
Set<Type> filterTypes = FavouritesService.Type.ALL_FILTER_TYPES; //Default all
|
||||
|
||||
// filterType is of the form 'target.<site|file|folder>'
|
||||
QueryHelper.walk(parameters.getQuery(), new WalkerCallbackAdapter()
|
||||
{
|
||||
@Override
|
||||
public void or() {
|
||||
//OR is supported but exists() will be called for each EXISTS so we don't
|
||||
//need to do anything here. If we don't override it then it will be assumed
|
||||
//that OR in the grammar is not supported.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exists(String filteredByClient, boolean negated) {
|
||||
if(filteredByClient != null)
|
||||
{
|
||||
int idx = filteredByClient.lastIndexOf("/");
|
||||
if(idx == -1 || idx == filteredByClient.length())
|
||||
{
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
else
|
||||
{
|
||||
String filtertype = filteredByClient.substring(idx + 1).toUpperCase();
|
||||
filteredByClientQuery.add(Type.valueOf(filtertype));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
if (filteredByClientQuery.size() > 0)
|
||||
{
|
||||
filterTypes = filteredByClientQuery;
|
||||
}
|
||||
|
||||
final PagingResults<PersonFavourite> favourites = favouritesService.getPagedFavourites(personId, filterTypes, FavouritesService.DEFAULT_SORT_PROPS,
|
||||
Util.getPagingRequest(paging));
|
||||
return wrap(paging, favourites);
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.favourites.PersonFavourite;
|
||||
import org.alfresco.repo.site.SiteDoesNotExistException;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.rest.api.Favourites;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.model.Document;
|
||||
import org.alfresco.rest.api.model.DocumentTarget;
|
||||
import org.alfresco.rest.api.model.Favourite;
|
||||
import org.alfresco.rest.api.model.Folder;
|
||||
import org.alfresco.rest.api.model.FolderTarget;
|
||||
import org.alfresco.rest.api.model.Site;
|
||||
import org.alfresco.rest.api.model.SiteImpl;
|
||||
import org.alfresco.rest.api.model.SiteTarget;
|
||||
import org.alfresco.rest.api.model.Target;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper.WalkerCallbackAdapter;
|
||||
import org.alfresco.service.cmr.favourites.FavouritesService;
|
||||
import org.alfresco.service.cmr.favourites.FavouritesService.Type;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Public REST API: Centralises access to favourites functionality and maps between representations repository and api representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class FavouritesImpl implements Favourites
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(FavouritesImpl.class);
|
||||
|
||||
private People people;
|
||||
private Sites sites;
|
||||
private Nodes nodes;
|
||||
private FavouritesService favouritesService;
|
||||
private SiteService siteService;
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setFavouritesService(FavouritesService favouritesService)
|
||||
{
|
||||
this.favouritesService = favouritesService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
private Target getTarget(PersonFavourite personFavourite)
|
||||
{
|
||||
Target target = null;
|
||||
NodeRef nodeRef = personFavourite.getNodeRef();
|
||||
Type type = personFavourite.getType();
|
||||
if(type.equals(Type.FILE))
|
||||
{
|
||||
Document document = nodes.getDocument(nodeRef);
|
||||
target = new DocumentTarget(document);
|
||||
}
|
||||
else if(type.equals(Type.FOLDER))
|
||||
{
|
||||
Folder folder = nodes.getFolder(nodeRef);
|
||||
target = new FolderTarget(folder);
|
||||
}
|
||||
else if(type.equals(Type.SITE))
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
String role = sites.getSiteRole(siteInfo.getShortName());
|
||||
Site site = new SiteImpl(siteInfo, role);
|
||||
target = new SiteTarget(site);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected favourite target type: " + type);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
private Favourite getFavourite(PersonFavourite personFavourite)
|
||||
{
|
||||
Favourite fav = new Favourite();
|
||||
fav.setTargetGuid(personFavourite.getNodeRef().getId());
|
||||
fav.setCreatedAt(personFavourite.getCreatedAt());
|
||||
Target target = getTarget(personFavourite);
|
||||
fav.setTarget(target);
|
||||
return fav;
|
||||
}
|
||||
|
||||
private CollectionWithPagingInfo<Favourite> wrap(Paging paging, PagingResults<PersonFavourite> personFavourites)
|
||||
{
|
||||
final List<PersonFavourite> page = personFavourites.getPage();
|
||||
final List<Favourite> list = new AbstractList<Favourite>()
|
||||
{
|
||||
@Override
|
||||
public Favourite get(int index)
|
||||
{
|
||||
PersonFavourite personFavourite = page.get(index);
|
||||
Favourite fav = getFavourite(personFavourite);
|
||||
return fav;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return page.size();
|
||||
}
|
||||
};
|
||||
Pair<Integer, Integer> pair = personFavourites.getTotalResultCount();
|
||||
Integer total = null;
|
||||
if(pair.getFirst().equals(pair.getSecond()))
|
||||
{
|
||||
total = pair.getFirst();
|
||||
}
|
||||
return CollectionWithPagingInfo.asPaged(paging, list, personFavourites.hasMoreItems(), total);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favourite addFavourite(String personId, Favourite favourite)
|
||||
{
|
||||
Favourite ret = null;
|
||||
|
||||
personId = people.validatePerson(personId, true);
|
||||
Target target = favourite.getTarget();
|
||||
if(target == null)
|
||||
{
|
||||
throw new InvalidArgumentException("target is missing");
|
||||
}
|
||||
else if(target instanceof SiteTarget)
|
||||
{
|
||||
SiteTarget siteTarget = (SiteTarget)target;
|
||||
NodeRef guid = siteTarget.getSite().getGuid();
|
||||
SiteInfo siteInfo = sites.validateSite(guid);
|
||||
NodeRef siteNodeRef = siteInfo.getNodeRef();
|
||||
String siteId = siteInfo.getShortName();
|
||||
|
||||
try
|
||||
{
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, siteNodeRef);
|
||||
ret = getFavourite(personFavourite);
|
||||
}
|
||||
catch(SiteDoesNotExistException e)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, siteId);
|
||||
}
|
||||
}
|
||||
else if(target instanceof DocumentTarget)
|
||||
{
|
||||
DocumentTarget documentTarget = (DocumentTarget)target;
|
||||
NodeRef nodeRef = documentTarget.getFile().getGuid();
|
||||
if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null))
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, nodeRef.getId());
|
||||
}
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef);
|
||||
ret = getFavourite(personFavourite);
|
||||
}
|
||||
else if(target instanceof FolderTarget)
|
||||
{
|
||||
FolderTarget folderTarget = (FolderTarget)target;
|
||||
NodeRef nodeRef = folderTarget.getFolder().getGuid();
|
||||
if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), Collections.singleton(SiteModel.TYPE_SITE)))
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, nodeRef.getId());
|
||||
}
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef);
|
||||
ret = getFavourite(personFavourite);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFavourite(String personId, String id)
|
||||
{
|
||||
personId = people.validatePerson(personId, true);
|
||||
NodeRef nodeRef = nodes.validateNode(id);
|
||||
boolean exists = false;
|
||||
|
||||
Type type = favouritesService.getType(nodeRef);
|
||||
if(type.equals(Type.SITE))
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// shouldn't happen because the type implies it's a site
|
||||
throw new AlfrescoRuntimeException("Unable to find site with nodeRef " + nodeRef);
|
||||
}
|
||||
exists = favouritesService.removeFavourite(personId, siteInfo.getNodeRef());
|
||||
}
|
||||
else if(type.equals(Type.FILE))
|
||||
{
|
||||
exists = favouritesService.removeFavourite(personId, nodeRef);
|
||||
}
|
||||
else if(type.equals(Type.FOLDER))
|
||||
{
|
||||
exists = favouritesService.removeFavourite(personId, nodeRef);
|
||||
}
|
||||
if(!exists)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, id);
|
||||
}
|
||||
}
|
||||
|
||||
public Favourite getFavourite(String personId, String favouriteId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(favouriteId);
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.getFavourite(personId, nodeRef);
|
||||
if(personFavourite != null)
|
||||
{
|
||||
Favourite favourite = getFavourite(personFavourite);
|
||||
return favourite;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, favouriteId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Favourite> getFavourites(String personId, final Parameters parameters)
|
||||
{
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
Paging paging = parameters.getPaging();
|
||||
|
||||
final Set<Type> filteredByClientQuery = new HashSet<Type>();
|
||||
Set<Type> filterTypes = FavouritesService.Type.ALL_FILTER_TYPES; //Default all
|
||||
|
||||
// filterType is of the form 'target.<site|file|folder>'
|
||||
QueryHelper.walk(parameters.getQuery(), new WalkerCallbackAdapter()
|
||||
{
|
||||
@Override
|
||||
public void or() {
|
||||
//OR is supported but exists() will be called for each EXISTS so we don't
|
||||
//need to do anything here. If we don't override it then it will be assumed
|
||||
//that OR in the grammar is not supported.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exists(String filteredByClient, boolean negated) {
|
||||
if(filteredByClient != null)
|
||||
{
|
||||
int idx = filteredByClient.lastIndexOf("/");
|
||||
if(idx == -1 || idx == filteredByClient.length())
|
||||
{
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
else
|
||||
{
|
||||
String filtertype = filteredByClient.substring(idx + 1).toUpperCase();
|
||||
filteredByClientQuery.add(Type.valueOf(filtertype));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
if (filteredByClientQuery.size() > 0)
|
||||
{
|
||||
filterTypes = filteredByClientQuery;
|
||||
}
|
||||
|
||||
final PagingResults<PersonFavourite> favourites = favouritesService.getPagedFavourites(personId, filterTypes, FavouritesService.DEFAULT_SORT_PROPS,
|
||||
Util.getPagingRequest(paging));
|
||||
return wrap(paging, favourites);
|
||||
}
|
||||
}
|
||||
|
@@ -1,24 +1,24 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
|
||||
/**
|
||||
* Translates access denied exceptions from the service layer to API permission denied exception.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class LegacyExceptionHandler implements ExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Throwable t)
|
||||
{
|
||||
if(t instanceof AccessDeniedException)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new PermissionDeniedException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
|
||||
/**
|
||||
* Translates access denied exceptions from the service layer to API permission denied exception.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class LegacyExceptionHandler implements ExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Throwable t)
|
||||
{
|
||||
if(t instanceof AccessDeniedException)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new PermissionDeniedException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,87 +1,87 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tenant.NetworksService;
|
||||
import org.alfresco.rest.api.Networks;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.model.Network;
|
||||
import org.alfresco.rest.api.model.NetworkImpl;
|
||||
import org.alfresco.rest.api.model.PersonNetwork;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
|
||||
/**
|
||||
* Centralises access to network services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class NetworksImpl implements Networks
|
||||
{
|
||||
private People people;
|
||||
private NetworksService networksService;
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setNetworksService(NetworksService networksService)
|
||||
{
|
||||
this.networksService = networksService;
|
||||
}
|
||||
|
||||
public Network validateNetwork(String networkId)
|
||||
{
|
||||
org.alfresco.repo.tenant.Network network = networksService.getNetwork(networkId);
|
||||
if(network == null)
|
||||
{
|
||||
throw new EntityNotFoundException(networkId);
|
||||
}
|
||||
Network restNetwork = new NetworkImpl(network);
|
||||
return restNetwork;
|
||||
}
|
||||
|
||||
private PersonNetwork getPersonNetwork(org.alfresco.repo.tenant.Network network)
|
||||
{
|
||||
Network restNetwork = new NetworkImpl(network);
|
||||
PersonNetwork personNetwork = new PersonNetwork(network.getIsHomeNetwork(), restNetwork);
|
||||
return personNetwork;
|
||||
}
|
||||
|
||||
public Network getNetwork(String networkId)
|
||||
{
|
||||
Network network = validateNetwork(networkId);
|
||||
return network;
|
||||
}
|
||||
|
||||
public PersonNetwork getNetwork(String personId, String networkId)
|
||||
{
|
||||
// check that personId is the current user
|
||||
personId = people.validatePerson(personId, true);
|
||||
Network network = validateNetwork(networkId);
|
||||
|
||||
org.alfresco.repo.tenant.Network tenantNetwork = networksService.getNetwork(network.getId());
|
||||
PersonNetwork personNetwork = getPersonNetwork(tenantNetwork);
|
||||
return personNetwork;
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<PersonNetwork> getNetworks(String personId, Paging paging)
|
||||
{
|
||||
// check that personId is the current user
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
PagingResults<org.alfresco.repo.tenant.Network> networks = networksService.getNetworks(Util.getPagingRequest(paging));
|
||||
List<PersonNetwork> ret = new ArrayList<PersonNetwork>(networks.getPage().size());
|
||||
for(org.alfresco.repo.tenant.Network network : networks.getPage())
|
||||
{
|
||||
PersonNetwork personNetwork = getPersonNetwork(network);
|
||||
ret.add(personNetwork);
|
||||
}
|
||||
return CollectionWithPagingInfo.asPaged(paging, ret, networks.hasMoreItems(), networks.getTotalResultCount().getFirst());
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tenant.NetworksService;
|
||||
import org.alfresco.rest.api.Networks;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.model.Network;
|
||||
import org.alfresco.rest.api.model.NetworkImpl;
|
||||
import org.alfresco.rest.api.model.PersonNetwork;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
|
||||
/**
|
||||
* Centralises access to network services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class NetworksImpl implements Networks
|
||||
{
|
||||
private People people;
|
||||
private NetworksService networksService;
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setNetworksService(NetworksService networksService)
|
||||
{
|
||||
this.networksService = networksService;
|
||||
}
|
||||
|
||||
public Network validateNetwork(String networkId)
|
||||
{
|
||||
org.alfresco.repo.tenant.Network network = networksService.getNetwork(networkId);
|
||||
if(network == null)
|
||||
{
|
||||
throw new EntityNotFoundException(networkId);
|
||||
}
|
||||
Network restNetwork = new NetworkImpl(network);
|
||||
return restNetwork;
|
||||
}
|
||||
|
||||
private PersonNetwork getPersonNetwork(org.alfresco.repo.tenant.Network network)
|
||||
{
|
||||
Network restNetwork = new NetworkImpl(network);
|
||||
PersonNetwork personNetwork = new PersonNetwork(network.getIsHomeNetwork(), restNetwork);
|
||||
return personNetwork;
|
||||
}
|
||||
|
||||
public Network getNetwork(String networkId)
|
||||
{
|
||||
Network network = validateNetwork(networkId);
|
||||
return network;
|
||||
}
|
||||
|
||||
public PersonNetwork getNetwork(String personId, String networkId)
|
||||
{
|
||||
// check that personId is the current user
|
||||
personId = people.validatePerson(personId, true);
|
||||
Network network = validateNetwork(networkId);
|
||||
|
||||
org.alfresco.repo.tenant.Network tenantNetwork = networksService.getNetwork(network.getId());
|
||||
PersonNetwork personNetwork = getPersonNetwork(tenantNetwork);
|
||||
return personNetwork;
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<PersonNetwork> getNetworks(String personId, Paging paging)
|
||||
{
|
||||
// check that personId is the current user
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
PagingResults<org.alfresco.repo.tenant.Network> networks = networksService.getNetworks(Util.getPagingRequest(paging));
|
||||
List<PersonNetwork> ret = new ArrayList<PersonNetwork>(networks.getPage().size());
|
||||
for(org.alfresco.repo.tenant.Network network : networks.getPage())
|
||||
{
|
||||
PersonNetwork personNetwork = getPersonNetwork(network);
|
||||
ret.add(personNetwork);
|
||||
}
|
||||
return CollectionWithPagingInfo.asPaged(paging, ret, networks.hasMoreItems(), networks.getTotalResultCount().getFirst());
|
||||
}
|
||||
}
|
||||
|
@@ -1,134 +1,134 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.alfresco.rest.api.NodeRatings;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.impl.node.ratings.RatingScheme;
|
||||
import org.alfresco.rest.api.model.NodeRating;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.rating.RatingService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Centralises access to node ratings services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class NodeRatingsImpl implements NodeRatings
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(NodeRatingsImpl.class);
|
||||
|
||||
private Nodes nodes;
|
||||
private RatingService ratingService;
|
||||
private NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setRatingService(RatingService ratingService)
|
||||
{
|
||||
this.ratingService = ratingService;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setNodeRatingSchemeRegistry(NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry)
|
||||
{
|
||||
this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry;
|
||||
}
|
||||
|
||||
public RatingScheme validateRatingScheme(String ratingSchemeId)
|
||||
{
|
||||
RatingScheme ratingScheme = nodeRatingSchemeRegistry.getNamedObject(ratingSchemeId);
|
||||
if(ratingScheme == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid ratingSchemeId " + ratingSchemeId);
|
||||
}
|
||||
|
||||
return ratingScheme;
|
||||
}
|
||||
|
||||
// TODO deal with fractional ratings - InvalidArgumentException
|
||||
public NodeRating getNodeRating(String nodeId, String ratingSchemeId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId);
|
||||
return ratingScheme.getNodeRating(nodeRef);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<NodeRating> getNodeRatings(String nodeId, Paging paging)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
Set<String> schemes = new TreeSet<String>(ratingService.getRatingSchemes().keySet());
|
||||
Iterator<String> it = schemes.iterator();
|
||||
|
||||
int skipCount = paging.getSkipCount();
|
||||
int maxItems = paging.getMaxItems();
|
||||
int end = skipCount + maxItems;
|
||||
if(end < 0)
|
||||
{
|
||||
// overflow
|
||||
end = Integer.MAX_VALUE;
|
||||
}
|
||||
int count = Math.min(maxItems, schemes.size() - skipCount);
|
||||
List<NodeRating> ratings = new ArrayList<NodeRating>(count);
|
||||
|
||||
for(int i = 0; i < end && it.hasNext(); i++)
|
||||
{
|
||||
String schemeName = it.next();
|
||||
if(i < skipCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RatingScheme ratingScheme = validateRatingScheme(schemeName);
|
||||
NodeRating nodeRating = ratingScheme.getNodeRating(nodeRef);
|
||||
ratings.add(nodeRating);
|
||||
}
|
||||
|
||||
int totalSize = schemes.size();
|
||||
boolean hasMoreItems = (skipCount + count < totalSize);
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, ratings, hasMoreItems, totalSize);
|
||||
}
|
||||
|
||||
public void addRating(String nodeId, String ratingSchemeId, Object rating)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
|
||||
RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId);
|
||||
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot rate this node");
|
||||
}
|
||||
|
||||
ratingScheme.applyRating(nodeRef, rating);
|
||||
}
|
||||
|
||||
public void removeRating(String nodeId, String ratingSchemeId)
|
||||
{
|
||||
RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId);
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
ratingScheme.removeRating(nodeRef);
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.alfresco.rest.api.NodeRatings;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.impl.node.ratings.RatingScheme;
|
||||
import org.alfresco.rest.api.model.NodeRating;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.rating.RatingService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Centralises access to node ratings services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class NodeRatingsImpl implements NodeRatings
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(NodeRatingsImpl.class);
|
||||
|
||||
private Nodes nodes;
|
||||
private RatingService ratingService;
|
||||
private NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setRatingService(RatingService ratingService)
|
||||
{
|
||||
this.ratingService = ratingService;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setNodeRatingSchemeRegistry(NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry)
|
||||
{
|
||||
this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry;
|
||||
}
|
||||
|
||||
public RatingScheme validateRatingScheme(String ratingSchemeId)
|
||||
{
|
||||
RatingScheme ratingScheme = nodeRatingSchemeRegistry.getNamedObject(ratingSchemeId);
|
||||
if(ratingScheme == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid ratingSchemeId " + ratingSchemeId);
|
||||
}
|
||||
|
||||
return ratingScheme;
|
||||
}
|
||||
|
||||
// TODO deal with fractional ratings - InvalidArgumentException
|
||||
public NodeRating getNodeRating(String nodeId, String ratingSchemeId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId);
|
||||
return ratingScheme.getNodeRating(nodeRef);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<NodeRating> getNodeRatings(String nodeId, Paging paging)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
Set<String> schemes = new TreeSet<String>(ratingService.getRatingSchemes().keySet());
|
||||
Iterator<String> it = schemes.iterator();
|
||||
|
||||
int skipCount = paging.getSkipCount();
|
||||
int maxItems = paging.getMaxItems();
|
||||
int end = skipCount + maxItems;
|
||||
if(end < 0)
|
||||
{
|
||||
// overflow
|
||||
end = Integer.MAX_VALUE;
|
||||
}
|
||||
int count = Math.min(maxItems, schemes.size() - skipCount);
|
||||
List<NodeRating> ratings = new ArrayList<NodeRating>(count);
|
||||
|
||||
for(int i = 0; i < end && it.hasNext(); i++)
|
||||
{
|
||||
String schemeName = it.next();
|
||||
if(i < skipCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RatingScheme ratingScheme = validateRatingScheme(schemeName);
|
||||
NodeRating nodeRating = ratingScheme.getNodeRating(nodeRef);
|
||||
ratings.add(nodeRating);
|
||||
}
|
||||
|
||||
int totalSize = schemes.size();
|
||||
boolean hasMoreItems = (skipCount + count < totalSize);
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, ratings, hasMoreItems, totalSize);
|
||||
}
|
||||
|
||||
public void addRating(String nodeId, String ratingSchemeId, Object rating)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
|
||||
RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId);
|
||||
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot rate this node");
|
||||
}
|
||||
|
||||
ratingScheme.applyRating(nodeRef, rating);
|
||||
}
|
||||
|
||||
public void removeRating(String nodeId, String ratingSchemeId)
|
||||
{
|
||||
RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId);
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
ratingScheme.removeRating(nodeRef);
|
||||
}
|
||||
}
|
||||
|
@@ -1,235 +1,235 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.opencmis.CMISConnector;
|
||||
import org.alfresco.opencmis.CMISNodeInfoImpl;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Document;
|
||||
import org.alfresco.rest.api.model.Folder;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
|
||||
import org.apache.chemistry.opencmis.commons.data.Properties;
|
||||
import org.apache.chemistry.opencmis.commons.data.PropertyData;
|
||||
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
|
||||
|
||||
/**
|
||||
* Centralises access to node services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class NodesImpl implements Nodes
|
||||
{
|
||||
private static enum Type
|
||||
{
|
||||
// Note: ordered
|
||||
DOCUMENT, FOLDER;
|
||||
};
|
||||
|
||||
private NodeService nodeService;
|
||||
private DictionaryService dictionaryService;
|
||||
private CMISConnector cmisConnector;
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setCmisConnector(CMISConnector cmisConnector)
|
||||
{
|
||||
this.cmisConnector = cmisConnector;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Note: assumes workspace://SpacesStore
|
||||
*/
|
||||
public NodeRef validateNode(String nodeId)
|
||||
{
|
||||
return validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
|
||||
}
|
||||
|
||||
public NodeRef validateNode(StoreRef storeRef, String nodeId)
|
||||
{
|
||||
String versionLabel = null;
|
||||
|
||||
int idx = nodeId.indexOf(";");
|
||||
if(idx != -1)
|
||||
{
|
||||
versionLabel = nodeId.substring(idx + 1);
|
||||
nodeId = nodeId.substring(0, idx);
|
||||
if(versionLabel.equals("pwc"))
|
||||
{
|
||||
// TODO correct exception?
|
||||
throw new EntityNotFoundException(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
NodeRef nodeRef = new NodeRef(storeRef, nodeId);
|
||||
return validateNode(nodeRef);
|
||||
}
|
||||
|
||||
public NodeRef validateNode(NodeRef nodeRef)
|
||||
{
|
||||
if(!nodeService.exists(nodeRef))
|
||||
{
|
||||
throw new EntityNotFoundException(nodeRef.getId());
|
||||
}
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
public boolean nodeMatches(NodeRef nodeRef, Set<QName> expectedTypes, Set<QName> excludedTypes)
|
||||
{
|
||||
if(!nodeService.exists(nodeRef))
|
||||
{
|
||||
throw new EntityNotFoundException(nodeRef.getId());
|
||||
}
|
||||
|
||||
QName type = nodeService.getType(nodeRef);
|
||||
|
||||
Set<QName> allExpectedTypes = new HashSet<QName>();
|
||||
if(expectedTypes != null)
|
||||
{
|
||||
for(QName expectedType : expectedTypes)
|
||||
{
|
||||
allExpectedTypes.addAll(dictionaryService.getSubTypes(expectedType, true));
|
||||
}
|
||||
}
|
||||
|
||||
Set<QName> allExcludedTypes = new HashSet<QName>();
|
||||
if(excludedTypes != null)
|
||||
{
|
||||
for(QName excludedType : excludedTypes)
|
||||
{
|
||||
allExcludedTypes.addAll(dictionaryService.getSubTypes(excludedType, true));
|
||||
}
|
||||
}
|
||||
|
||||
boolean inExpected = allExpectedTypes.contains(type);
|
||||
boolean excluded = allExcludedTypes.contains(type);
|
||||
return(inExpected && !excluded);
|
||||
}
|
||||
|
||||
public Node getNode(String nodeId)
|
||||
{
|
||||
NodeRef nodeRef = validateNode(nodeId);
|
||||
|
||||
return new Node(nodeRef, nodeService.getProperties(nodeRef));
|
||||
}
|
||||
|
||||
public Node getNode(NodeRef nodeRef)
|
||||
{
|
||||
return new Node(nodeRef, nodeService.getProperties(nodeRef));
|
||||
}
|
||||
|
||||
private Type getType(NodeRef nodeRef)
|
||||
{
|
||||
QName type = nodeService.getType(nodeRef);
|
||||
boolean isContainer = Boolean.valueOf((dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) == true &&
|
||||
!dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER)));
|
||||
return isContainer ? Type.FOLDER : Type.DOCUMENT;
|
||||
}
|
||||
|
||||
// TODO filter CMIS properties
|
||||
private Properties getCMISProperties(NodeRef nodeRef)
|
||||
{
|
||||
CMISNodeInfoImpl nodeInfo = cmisConnector.createNodeInfo(nodeRef);
|
||||
final Properties properties = cmisConnector.getNodeProperties(nodeInfo, null);
|
||||
|
||||
// fake the title property, which CMIS doesn't give us
|
||||
String title = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
|
||||
final PropertyStringImpl titleProp = new PropertyStringImpl(ContentModel.PROP_TITLE.toString(), title);
|
||||
Properties wrapProperties = new Properties()
|
||||
{
|
||||
@Override
|
||||
public List<CmisExtensionElement> getExtensions()
|
||||
{
|
||||
return properties.getExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtensions(List<CmisExtensionElement> extensions)
|
||||
{
|
||||
properties.setExtensions(extensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, PropertyData<?>> getProperties()
|
||||
{
|
||||
Map<String, PropertyData<?>> updatedProperties = new HashMap<String, PropertyData<?>>(properties.getProperties());
|
||||
updatedProperties.put(titleProp.getId(), titleProp);
|
||||
return updatedProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyData<?>> getPropertyList()
|
||||
{
|
||||
List<PropertyData<?>> propertyList = new ArrayList<PropertyData<?>>(properties.getPropertyList());
|
||||
propertyList.add(titleProp);
|
||||
return propertyList;
|
||||
}
|
||||
};
|
||||
|
||||
return wrapProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public api representation of a document.
|
||||
*
|
||||
* Note: properties are modelled after the OpenCMIS node properties
|
||||
*/
|
||||
public Document getDocument(NodeRef nodeRef)
|
||||
{
|
||||
Type type = getType(nodeRef);
|
||||
if(type.equals(Type.DOCUMENT))
|
||||
{
|
||||
Properties properties = getCMISProperties(nodeRef);
|
||||
Document doc = new Document(nodeRef, properties);
|
||||
return doc;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Node is not a file");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public api representation of a folder.
|
||||
*
|
||||
* Note: properties are modelled after the OpenCMIS node properties
|
||||
*/
|
||||
public Folder getFolder(NodeRef nodeRef)
|
||||
{
|
||||
Type type = getType(nodeRef);
|
||||
if(type.equals(Type.FOLDER))
|
||||
{
|
||||
Properties properties = getCMISProperties(nodeRef);
|
||||
Folder folder = new Folder(nodeRef, properties);
|
||||
return folder;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Node is not a folder");
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.opencmis.CMISConnector;
|
||||
import org.alfresco.opencmis.CMISNodeInfoImpl;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Document;
|
||||
import org.alfresco.rest.api.model.Folder;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
|
||||
import org.apache.chemistry.opencmis.commons.data.Properties;
|
||||
import org.apache.chemistry.opencmis.commons.data.PropertyData;
|
||||
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
|
||||
|
||||
/**
|
||||
* Centralises access to node services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class NodesImpl implements Nodes
|
||||
{
|
||||
private static enum Type
|
||||
{
|
||||
// Note: ordered
|
||||
DOCUMENT, FOLDER;
|
||||
};
|
||||
|
||||
private NodeService nodeService;
|
||||
private DictionaryService dictionaryService;
|
||||
private CMISConnector cmisConnector;
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setCmisConnector(CMISConnector cmisConnector)
|
||||
{
|
||||
this.cmisConnector = cmisConnector;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Note: assumes workspace://SpacesStore
|
||||
*/
|
||||
public NodeRef validateNode(String nodeId)
|
||||
{
|
||||
return validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
|
||||
}
|
||||
|
||||
public NodeRef validateNode(StoreRef storeRef, String nodeId)
|
||||
{
|
||||
String versionLabel = null;
|
||||
|
||||
int idx = nodeId.indexOf(";");
|
||||
if(idx != -1)
|
||||
{
|
||||
versionLabel = nodeId.substring(idx + 1);
|
||||
nodeId = nodeId.substring(0, idx);
|
||||
if(versionLabel.equals("pwc"))
|
||||
{
|
||||
// TODO correct exception?
|
||||
throw new EntityNotFoundException(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
NodeRef nodeRef = new NodeRef(storeRef, nodeId);
|
||||
return validateNode(nodeRef);
|
||||
}
|
||||
|
||||
public NodeRef validateNode(NodeRef nodeRef)
|
||||
{
|
||||
if(!nodeService.exists(nodeRef))
|
||||
{
|
||||
throw new EntityNotFoundException(nodeRef.getId());
|
||||
}
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
public boolean nodeMatches(NodeRef nodeRef, Set<QName> expectedTypes, Set<QName> excludedTypes)
|
||||
{
|
||||
if(!nodeService.exists(nodeRef))
|
||||
{
|
||||
throw new EntityNotFoundException(nodeRef.getId());
|
||||
}
|
||||
|
||||
QName type = nodeService.getType(nodeRef);
|
||||
|
||||
Set<QName> allExpectedTypes = new HashSet<QName>();
|
||||
if(expectedTypes != null)
|
||||
{
|
||||
for(QName expectedType : expectedTypes)
|
||||
{
|
||||
allExpectedTypes.addAll(dictionaryService.getSubTypes(expectedType, true));
|
||||
}
|
||||
}
|
||||
|
||||
Set<QName> allExcludedTypes = new HashSet<QName>();
|
||||
if(excludedTypes != null)
|
||||
{
|
||||
for(QName excludedType : excludedTypes)
|
||||
{
|
||||
allExcludedTypes.addAll(dictionaryService.getSubTypes(excludedType, true));
|
||||
}
|
||||
}
|
||||
|
||||
boolean inExpected = allExpectedTypes.contains(type);
|
||||
boolean excluded = allExcludedTypes.contains(type);
|
||||
return(inExpected && !excluded);
|
||||
}
|
||||
|
||||
public Node getNode(String nodeId)
|
||||
{
|
||||
NodeRef nodeRef = validateNode(nodeId);
|
||||
|
||||
return new Node(nodeRef, nodeService.getProperties(nodeRef));
|
||||
}
|
||||
|
||||
public Node getNode(NodeRef nodeRef)
|
||||
{
|
||||
return new Node(nodeRef, nodeService.getProperties(nodeRef));
|
||||
}
|
||||
|
||||
private Type getType(NodeRef nodeRef)
|
||||
{
|
||||
QName type = nodeService.getType(nodeRef);
|
||||
boolean isContainer = Boolean.valueOf((dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) == true &&
|
||||
!dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER)));
|
||||
return isContainer ? Type.FOLDER : Type.DOCUMENT;
|
||||
}
|
||||
|
||||
// TODO filter CMIS properties
|
||||
private Properties getCMISProperties(NodeRef nodeRef)
|
||||
{
|
||||
CMISNodeInfoImpl nodeInfo = cmisConnector.createNodeInfo(nodeRef);
|
||||
final Properties properties = cmisConnector.getNodeProperties(nodeInfo, null);
|
||||
|
||||
// fake the title property, which CMIS doesn't give us
|
||||
String title = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
|
||||
final PropertyStringImpl titleProp = new PropertyStringImpl(ContentModel.PROP_TITLE.toString(), title);
|
||||
Properties wrapProperties = new Properties()
|
||||
{
|
||||
@Override
|
||||
public List<CmisExtensionElement> getExtensions()
|
||||
{
|
||||
return properties.getExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtensions(List<CmisExtensionElement> extensions)
|
||||
{
|
||||
properties.setExtensions(extensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, PropertyData<?>> getProperties()
|
||||
{
|
||||
Map<String, PropertyData<?>> updatedProperties = new HashMap<String, PropertyData<?>>(properties.getProperties());
|
||||
updatedProperties.put(titleProp.getId(), titleProp);
|
||||
return updatedProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyData<?>> getPropertyList()
|
||||
{
|
||||
List<PropertyData<?>> propertyList = new ArrayList<PropertyData<?>>(properties.getPropertyList());
|
||||
propertyList.add(titleProp);
|
||||
return propertyList;
|
||||
}
|
||||
};
|
||||
|
||||
return wrapProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public api representation of a document.
|
||||
*
|
||||
* Note: properties are modelled after the OpenCMIS node properties
|
||||
*/
|
||||
public Document getDocument(NodeRef nodeRef)
|
||||
{
|
||||
Type type = getType(nodeRef);
|
||||
if(type.equals(Type.DOCUMENT))
|
||||
{
|
||||
Properties properties = getCMISProperties(nodeRef);
|
||||
Document doc = new Document(nodeRef, properties);
|
||||
return doc;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Node is not a file");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public api representation of a folder.
|
||||
*
|
||||
* Note: properties are modelled after the OpenCMIS node properties
|
||||
*/
|
||||
public Folder getFolder(NodeRef nodeRef)
|
||||
{
|
||||
Type type = getType(nodeRef);
|
||||
if(type.equals(Type.FOLDER))
|
||||
{
|
||||
Properties properties = getCMISProperties(nodeRef);
|
||||
Folder folder = new Folder(nodeRef, properties);
|
||||
return folder;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Node is not a folder");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,323 +1,323 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.model.Company;
|
||||
import org.alfresco.rest.api.model.Person;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
|
||||
import org.alfresco.service.cmr.usage.ContentUsageService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Centralises access to people services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class PeopleImpl implements People
|
||||
{
|
||||
protected Nodes nodes;
|
||||
protected Sites sites;
|
||||
|
||||
protected SiteService siteService;
|
||||
protected NodeService nodeService;
|
||||
protected PersonService personService;
|
||||
protected AuthenticationService authenticationService;
|
||||
protected ContentUsageService contentUsageService;
|
||||
protected ContentService contentService;
|
||||
protected ThumbnailService thumbnailService;
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
public void setContentUsageService(ContentUsageService contentUsageService)
|
||||
{
|
||||
this.contentUsageService = contentUsageService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
public void setThumbnailService(ThumbnailService thumbnailService)
|
||||
{
|
||||
this.thumbnailService = thumbnailService;
|
||||
}
|
||||
|
||||
public String validatePerson(String personId)
|
||||
{
|
||||
return validatePerson(personId, false);
|
||||
}
|
||||
|
||||
public String validatePerson(String personId, boolean validateIsCurrentUser)
|
||||
{
|
||||
if(personId.equalsIgnoreCase(DEFAULT_USER))
|
||||
{
|
||||
personId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
personId = personService.getUserIdentifier(personId);
|
||||
if(personId == null)
|
||||
{
|
||||
// "User " + personId + " does not exist"
|
||||
throw new EntityNotFoundException("personId is null.");
|
||||
}
|
||||
|
||||
if(validateIsCurrentUser)
|
||||
{
|
||||
String currentUserId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if(!currentUserId.equalsIgnoreCase(personId))
|
||||
{
|
||||
throw new EntityNotFoundException(personId);
|
||||
}
|
||||
}
|
||||
|
||||
return personId;
|
||||
}
|
||||
|
||||
protected void processPersonProperties(String userName, final Map<QName, Serializable> nodeProps)
|
||||
{
|
||||
if(!contentUsageService.getEnabled())
|
||||
{
|
||||
// quota used will always be 0 in this case so remove from the person properties
|
||||
nodeProps.remove(ContentModel.PROP_SIZE_QUOTA);
|
||||
nodeProps.remove(ContentModel.PROP_SIZE_CURRENT);
|
||||
}
|
||||
|
||||
final ContentData personDescription = (ContentData)nodeProps.get(ContentModel.PROP_PERSONDESC);
|
||||
if(personDescription != null)
|
||||
{
|
||||
nodeProps.remove(ContentModel.PROP_PERSONDESC);
|
||||
|
||||
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
ContentReader reader = contentService.getRawReader(personDescription.getContentUrl());
|
||||
if(reader != null && reader.exists())
|
||||
{
|
||||
String description = reader.getContentString();
|
||||
nodeProps.put(Person.PROP_PERSON_DESCRIPTION, description);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasAvatar(NodeRef personNodeRef)
|
||||
{
|
||||
if(personNodeRef != null)
|
||||
{
|
||||
List<AssociationRef> avatorAssocs = nodeService.getTargetAssocs(personNodeRef, ContentModel.ASSOC_AVATAR);
|
||||
return(avatorAssocs.size() > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public NodeRef getAvatar(String personId)
|
||||
{
|
||||
NodeRef avatar = null;
|
||||
|
||||
personId = validatePerson(personId);
|
||||
NodeRef personNode = personService.getPerson(personId);
|
||||
if(personNode != null)
|
||||
{
|
||||
List<AssociationRef> avatorAssocs = nodeService.getTargetAssocs(personNode, ContentModel.ASSOC_AVATAR);
|
||||
if(avatorAssocs.size() > 0)
|
||||
{
|
||||
AssociationRef ref = avatorAssocs.get(0);
|
||||
NodeRef thumbnailNodeRef = thumbnailService.getThumbnailByName(ref.getTargetRef(), ContentModel.PROP_CONTENT, "avatar");
|
||||
if(thumbnailNodeRef != null)
|
||||
{
|
||||
avatar = thumbnailNodeRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException("avatar");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException("avatar");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException(personId);
|
||||
}
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws NoSuchPersonException if personId does not exist
|
||||
*/
|
||||
public Person getPerson(String personId)
|
||||
{
|
||||
Person person = null;
|
||||
|
||||
personId = validatePerson(personId);
|
||||
NodeRef personNode = personService.getPerson(personId, false);
|
||||
if (personNode != null)
|
||||
{
|
||||
Map<QName, Serializable> nodeProps = nodeService.getProperties(personNode);
|
||||
processPersonProperties(personId, nodeProps);
|
||||
// TODO this needs to be run as admin but should we do this here?
|
||||
final String pId = personId;
|
||||
Boolean enabled = AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
|
||||
{
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return authenticationService.getAuthenticationEnabled(pId);
|
||||
}
|
||||
});
|
||||
person = new Person(personNode, nodeProps, enabled);
|
||||
|
||||
// get avatar information
|
||||
if(hasAvatar(personNode))
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef avatar = getAvatar(personId);
|
||||
person.setAvatarId(avatar);
|
||||
}
|
||||
catch(EntityNotFoundException e)
|
||||
{
|
||||
// shouldn't happen, but ok
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException(personId);
|
||||
}
|
||||
|
||||
return person;
|
||||
}
|
||||
/**
|
||||
private void addToMap(Map<QName, Serializable> properties, QName name, Serializable value)
|
||||
{
|
||||
// if(name != null && value != null)
|
||||
// {
|
||||
properties.put(name, value);
|
||||
// }
|
||||
}
|
||||
|
||||
public Person updatePerson(String personId, final Person person)
|
||||
{
|
||||
personId = validatePerson(personId);
|
||||
|
||||
final Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
// addToMap(properties, ContentModel.PROP_USERNAME, person.getUserName());
|
||||
addToMap(properties, ContentModel.PROP_FIRSTNAME, person.getFirstName());
|
||||
addToMap(properties, ContentModel.PROP_LASTNAME, person.getLastName());
|
||||
addToMap(properties, ContentModel.PROP_JOBTITLE, person.getJobTitle());
|
||||
addToMap(properties, ContentModel.PROP_LOCATION, person.getLocation());
|
||||
addToMap(properties, ContentModel.PROP_TELEPHONE, person.getTelephone());
|
||||
addToMap(properties, ContentModel.PROP_MOBILE, person.getMobile());
|
||||
addToMap(properties, ContentModel.PROP_EMAIL, person.getEmail());
|
||||
|
||||
Company company = person.getCompany();
|
||||
if(company != null)
|
||||
{
|
||||
addToMap(properties, ContentModel.PROP_ORGANIZATION, company.getOrganization());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, company.getAddress1());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, company.getAddress2());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, company.getAddress3());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, company.getPostcode());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, company.getTelephone());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYFAX, company.getFax());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYEMAIL, company.getEmail());
|
||||
}
|
||||
else
|
||||
{
|
||||
addToMap(properties, ContentModel.PROP_ORGANIZATION, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYFAX, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYEMAIL, null);
|
||||
}
|
||||
|
||||
addToMap(properties, ContentModel.PROP_SKYPE, person.getSkypeId());
|
||||
addToMap(properties, ContentModel.PROP_INSTANTMSG, person.getInstantMessageId());
|
||||
addToMap(properties, ContentModel.PROP_USER_STATUS, person.getUserStatus());
|
||||
addToMap(properties, ContentModel.PROP_USER_STATUS_TIME, person.getStatusUpdatedAt());
|
||||
addToMap(properties, ContentModel.PROP_GOOGLEUSERNAME, person.getGoogleId());
|
||||
addToMap(properties, ContentModel.PROP_SIZE_QUOTA, person.getQuota());
|
||||
addToMap(properties, ContentModel.PROP_SIZE_CURRENT, person.getQuotaUsed());
|
||||
addToMap(properties, ContentModel.PROP_DESCRIPTION, person.getDescription());
|
||||
|
||||
final String pId = personId;
|
||||
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
personService.setPersonProperties(pId, properties, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return getPerson(personId);
|
||||
}
|
||||
*/
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.model.Company;
|
||||
import org.alfresco.rest.api.model.Person;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
|
||||
import org.alfresco.service.cmr.usage.ContentUsageService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Centralises access to people services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class PeopleImpl implements People
|
||||
{
|
||||
protected Nodes nodes;
|
||||
protected Sites sites;
|
||||
|
||||
protected SiteService siteService;
|
||||
protected NodeService nodeService;
|
||||
protected PersonService personService;
|
||||
protected AuthenticationService authenticationService;
|
||||
protected ContentUsageService contentUsageService;
|
||||
protected ContentService contentService;
|
||||
protected ThumbnailService thumbnailService;
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
public void setContentUsageService(ContentUsageService contentUsageService)
|
||||
{
|
||||
this.contentUsageService = contentUsageService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
public void setThumbnailService(ThumbnailService thumbnailService)
|
||||
{
|
||||
this.thumbnailService = thumbnailService;
|
||||
}
|
||||
|
||||
public String validatePerson(String personId)
|
||||
{
|
||||
return validatePerson(personId, false);
|
||||
}
|
||||
|
||||
public String validatePerson(String personId, boolean validateIsCurrentUser)
|
||||
{
|
||||
if(personId.equalsIgnoreCase(DEFAULT_USER))
|
||||
{
|
||||
personId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
personId = personService.getUserIdentifier(personId);
|
||||
if(personId == null)
|
||||
{
|
||||
// "User " + personId + " does not exist"
|
||||
throw new EntityNotFoundException("personId is null.");
|
||||
}
|
||||
|
||||
if(validateIsCurrentUser)
|
||||
{
|
||||
String currentUserId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if(!currentUserId.equalsIgnoreCase(personId))
|
||||
{
|
||||
throw new EntityNotFoundException(personId);
|
||||
}
|
||||
}
|
||||
|
||||
return personId;
|
||||
}
|
||||
|
||||
protected void processPersonProperties(String userName, final Map<QName, Serializable> nodeProps)
|
||||
{
|
||||
if(!contentUsageService.getEnabled())
|
||||
{
|
||||
// quota used will always be 0 in this case so remove from the person properties
|
||||
nodeProps.remove(ContentModel.PROP_SIZE_QUOTA);
|
||||
nodeProps.remove(ContentModel.PROP_SIZE_CURRENT);
|
||||
}
|
||||
|
||||
final ContentData personDescription = (ContentData)nodeProps.get(ContentModel.PROP_PERSONDESC);
|
||||
if(personDescription != null)
|
||||
{
|
||||
nodeProps.remove(ContentModel.PROP_PERSONDESC);
|
||||
|
||||
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
ContentReader reader = contentService.getRawReader(personDescription.getContentUrl());
|
||||
if(reader != null && reader.exists())
|
||||
{
|
||||
String description = reader.getContentString();
|
||||
nodeProps.put(Person.PROP_PERSON_DESCRIPTION, description);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasAvatar(NodeRef personNodeRef)
|
||||
{
|
||||
if(personNodeRef != null)
|
||||
{
|
||||
List<AssociationRef> avatorAssocs = nodeService.getTargetAssocs(personNodeRef, ContentModel.ASSOC_AVATAR);
|
||||
return(avatorAssocs.size() > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public NodeRef getAvatar(String personId)
|
||||
{
|
||||
NodeRef avatar = null;
|
||||
|
||||
personId = validatePerson(personId);
|
||||
NodeRef personNode = personService.getPerson(personId);
|
||||
if(personNode != null)
|
||||
{
|
||||
List<AssociationRef> avatorAssocs = nodeService.getTargetAssocs(personNode, ContentModel.ASSOC_AVATAR);
|
||||
if(avatorAssocs.size() > 0)
|
||||
{
|
||||
AssociationRef ref = avatorAssocs.get(0);
|
||||
NodeRef thumbnailNodeRef = thumbnailService.getThumbnailByName(ref.getTargetRef(), ContentModel.PROP_CONTENT, "avatar");
|
||||
if(thumbnailNodeRef != null)
|
||||
{
|
||||
avatar = thumbnailNodeRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException("avatar");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException("avatar");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException(personId);
|
||||
}
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws NoSuchPersonException if personId does not exist
|
||||
*/
|
||||
public Person getPerson(String personId)
|
||||
{
|
||||
Person person = null;
|
||||
|
||||
personId = validatePerson(personId);
|
||||
NodeRef personNode = personService.getPerson(personId, false);
|
||||
if (personNode != null)
|
||||
{
|
||||
Map<QName, Serializable> nodeProps = nodeService.getProperties(personNode);
|
||||
processPersonProperties(personId, nodeProps);
|
||||
// TODO this needs to be run as admin but should we do this here?
|
||||
final String pId = personId;
|
||||
Boolean enabled = AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
|
||||
{
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return authenticationService.getAuthenticationEnabled(pId);
|
||||
}
|
||||
});
|
||||
person = new Person(personNode, nodeProps, enabled);
|
||||
|
||||
// get avatar information
|
||||
if(hasAvatar(personNode))
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef avatar = getAvatar(personId);
|
||||
person.setAvatarId(avatar);
|
||||
}
|
||||
catch(EntityNotFoundException e)
|
||||
{
|
||||
// shouldn't happen, but ok
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EntityNotFoundException(personId);
|
||||
}
|
||||
|
||||
return person;
|
||||
}
|
||||
/**
|
||||
private void addToMap(Map<QName, Serializable> properties, QName name, Serializable value)
|
||||
{
|
||||
// if(name != null && value != null)
|
||||
// {
|
||||
properties.put(name, value);
|
||||
// }
|
||||
}
|
||||
|
||||
public Person updatePerson(String personId, final Person person)
|
||||
{
|
||||
personId = validatePerson(personId);
|
||||
|
||||
final Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
// addToMap(properties, ContentModel.PROP_USERNAME, person.getUserName());
|
||||
addToMap(properties, ContentModel.PROP_FIRSTNAME, person.getFirstName());
|
||||
addToMap(properties, ContentModel.PROP_LASTNAME, person.getLastName());
|
||||
addToMap(properties, ContentModel.PROP_JOBTITLE, person.getJobTitle());
|
||||
addToMap(properties, ContentModel.PROP_LOCATION, person.getLocation());
|
||||
addToMap(properties, ContentModel.PROP_TELEPHONE, person.getTelephone());
|
||||
addToMap(properties, ContentModel.PROP_MOBILE, person.getMobile());
|
||||
addToMap(properties, ContentModel.PROP_EMAIL, person.getEmail());
|
||||
|
||||
Company company = person.getCompany();
|
||||
if(company != null)
|
||||
{
|
||||
addToMap(properties, ContentModel.PROP_ORGANIZATION, company.getOrganization());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, company.getAddress1());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, company.getAddress2());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, company.getAddress3());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, company.getPostcode());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, company.getTelephone());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYFAX, company.getFax());
|
||||
addToMap(properties, ContentModel.PROP_COMPANYEMAIL, company.getEmail());
|
||||
}
|
||||
else
|
||||
{
|
||||
addToMap(properties, ContentModel.PROP_ORGANIZATION, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYFAX, null);
|
||||
addToMap(properties, ContentModel.PROP_COMPANYEMAIL, null);
|
||||
}
|
||||
|
||||
addToMap(properties, ContentModel.PROP_SKYPE, person.getSkypeId());
|
||||
addToMap(properties, ContentModel.PROP_INSTANTMSG, person.getInstantMessageId());
|
||||
addToMap(properties, ContentModel.PROP_USER_STATUS, person.getUserStatus());
|
||||
addToMap(properties, ContentModel.PROP_USER_STATUS_TIME, person.getStatusUpdatedAt());
|
||||
addToMap(properties, ContentModel.PROP_GOOGLEUSERNAME, person.getGoogleId());
|
||||
addToMap(properties, ContentModel.PROP_SIZE_QUOTA, person.getQuota());
|
||||
addToMap(properties, ContentModel.PROP_SIZE_CURRENT, person.getQuotaUsed());
|
||||
addToMap(properties, ContentModel.PROP_DESCRIPTION, person.getDescription());
|
||||
|
||||
final String pId = personId;
|
||||
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
personService.setPersonProperties(pId, properties, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return getPerson(personId);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@@ -1,66 +1,66 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Preferences;
|
||||
import org.alfresco.rest.api.model.Preference;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.preference.PreferenceService;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Centralises access to preference services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class PreferencesImpl implements Preferences
|
||||
{
|
||||
private People people;
|
||||
private PreferenceService preferenceService;
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setPreferenceService(PreferenceService preferenceService)
|
||||
{
|
||||
this.preferenceService = preferenceService;
|
||||
}
|
||||
|
||||
public Preference getPreference(String personId, String preferenceName)
|
||||
{
|
||||
personId = people.validatePerson(personId);
|
||||
Serializable preferenceValue = preferenceService.getPreference(personId, preferenceName);
|
||||
if(preferenceValue != null)
|
||||
{
|
||||
return new Preference(preferenceName, preferenceValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, preferenceName);
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Preference> getPreferences(String personId, Paging paging)
|
||||
{
|
||||
personId = people.validatePerson(personId);
|
||||
|
||||
PagingResults<Pair<String, Serializable>> preferences = preferenceService.getPagedPreferences(personId, null, Util.getPagingRequest(paging));
|
||||
List<Preference> ret = new ArrayList<Preference>(preferences.getPage().size());
|
||||
for(Pair<String, Serializable> prefEntity : preferences.getPage())
|
||||
{
|
||||
Preference pref = new Preference(prefEntity.getFirst(), prefEntity.getSecond());
|
||||
ret.add(pref);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, ret, preferences.hasMoreItems(), preferences.getTotalResultCount().getFirst());
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.Preferences;
|
||||
import org.alfresco.rest.api.model.Preference;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.preference.PreferenceService;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Centralises access to preference services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class PreferencesImpl implements Preferences
|
||||
{
|
||||
private People people;
|
||||
private PreferenceService preferenceService;
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setPreferenceService(PreferenceService preferenceService)
|
||||
{
|
||||
this.preferenceService = preferenceService;
|
||||
}
|
||||
|
||||
public Preference getPreference(String personId, String preferenceName)
|
||||
{
|
||||
personId = people.validatePerson(personId);
|
||||
Serializable preferenceValue = preferenceService.getPreference(personId, preferenceName);
|
||||
if(preferenceValue != null)
|
||||
{
|
||||
return new Preference(preferenceName, preferenceValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, preferenceName);
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Preference> getPreferences(String personId, Paging paging)
|
||||
{
|
||||
personId = people.validatePerson(personId);
|
||||
|
||||
PagingResults<Pair<String, Serializable>> preferences = preferenceService.getPagedPreferences(personId, null, Util.getPagingRequest(paging));
|
||||
List<Preference> ret = new ArrayList<Preference>(preferences.getPage().size());
|
||||
for(Pair<String, Serializable> prefEntity : preferences.getPage())
|
||||
{
|
||||
Preference pref = new Preference(prefEntity.getFirst(), prefEntity.getSecond());
|
||||
ret.add(pref);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, ret, preferences.hasMoreItems(), preferences.getTotalResultCount().getFirst());
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden;
|
||||
|
||||
public class SiteMembershipRequestsExceptionHandler extends DefaultExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Throwable t)
|
||||
{
|
||||
if(t instanceof InvitationExceptionForbidden)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return super.handle(t);
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden;
|
||||
|
||||
public class SiteMembershipRequestsExceptionHandler extends DefaultExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Throwable t)
|
||||
{
|
||||
if(t instanceof InvitationExceptionForbidden)
|
||||
{
|
||||
// Note: security, no message to indicate why
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return super.handle(t);
|
||||
}
|
||||
}
|
||||
|
@@ -1,445 +1,445 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.invitation.InvitationSearchCriteriaImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.repo.tenant.NetworksService;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.SiteMembershipRequests;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.model.SiteMembershipRequest;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.invitation.Invitation;
|
||||
import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
|
||||
import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound;
|
||||
import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType;
|
||||
import org.alfresco.service.cmr.invitation.InvitationService;
|
||||
import org.alfresco.service.cmr.invitation.ModeratedInvitation;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Public REST API: centralises access to site membership requests and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class SiteMembershipRequestsImpl implements SiteMembershipRequests
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(SiteMembershipRequestsImpl.class);
|
||||
|
||||
// Default role to assign to the site membership request
|
||||
public final static String DEFAULT_ROLE = SiteModel.SITE_CONSUMER;
|
||||
|
||||
private People people;
|
||||
private Sites sites;
|
||||
private SiteService siteService;
|
||||
private NodeService nodeService;
|
||||
private InvitationService invitationService;
|
||||
private NetworksService networksService;
|
||||
|
||||
public void setNetworksService(NetworksService networksService)
|
||||
{
|
||||
this.networksService = networksService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setInvitationService(InvitationService invitationService)
|
||||
{
|
||||
this.invitationService = invitationService;
|
||||
}
|
||||
|
||||
private Invitation getSiteInvitation(String inviteeId, String siteId)
|
||||
{
|
||||
// Is there an outstanding site invite request for the invitee?
|
||||
InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl();
|
||||
criteria.setInvitationType(InvitationType.MODERATED);
|
||||
criteria.setInvitee(inviteeId);
|
||||
criteria.setResourceName(siteId);
|
||||
criteria.setResourceType(ResourceType.WEB_SITE);
|
||||
List<Invitation> invitations = invitationService.searchInvitation(criteria);
|
||||
if(invitations.size() > 1)
|
||||
{
|
||||
// TODO exception
|
||||
throw new AlfrescoRuntimeException("There should be only one outstanding site invitation");
|
||||
}
|
||||
return (invitations.size() == 0 ? null : invitations.get(0));
|
||||
}
|
||||
|
||||
private List<Invitation> getSiteInvitations(String inviteeId)
|
||||
{
|
||||
InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl();
|
||||
criteria.setInvitationType(InvitationType.MODERATED);
|
||||
criteria.setInvitee(inviteeId);
|
||||
criteria.setResourceType(ResourceType.WEB_SITE);
|
||||
List<Invitation> invitations = invitationService.searchInvitation(criteria);
|
||||
return invitations;
|
||||
}
|
||||
|
||||
private SiteMembershipRequest inviteToModeratedSite(final String message, final String inviteeId, final String siteId,
|
||||
final String inviteeRole)
|
||||
{
|
||||
ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole);
|
||||
|
||||
SiteMembershipRequest ret = new SiteMembershipRequest();
|
||||
ret.setId(siteId);
|
||||
ret.setMessage(message);
|
||||
ret.setCreatedAt(invitation.getCreatedAt());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SiteMembershipRequest inviteToSite(String siteId, String inviteeId, String inviteeRole, String message)
|
||||
{
|
||||
siteService.setMembership(siteId, inviteeId, inviteeRole);
|
||||
SiteMembershipRequest ret = new SiteMembershipRequest();
|
||||
ret.setId(siteId);
|
||||
ret.setMessage(message);
|
||||
Date createdAt = new Date();
|
||||
ret.setCreatedAt(createdAt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SiteMembershipRequest inviteToPublicSite(final SiteInfo siteInfo, final String message, final String inviteeId,
|
||||
final String inviteeRole)
|
||||
{
|
||||
SiteMembershipRequest siteMembershipRequest = null;
|
||||
|
||||
final String siteId = siteInfo.getShortName();
|
||||
NodeRef siteNodeRef = siteInfo.getNodeRef();
|
||||
String siteCreator = (String)nodeService.getProperty(siteNodeRef, ContentModel.PROP_CREATOR);
|
||||
|
||||
final String siteNetwork = networksService.getUserDefaultNetwork(siteCreator);
|
||||
if(StringUtils.isNotEmpty(siteNetwork))
|
||||
{
|
||||
// MT
|
||||
siteMembershipRequest = TenantUtil.runAsUserTenant(new TenantRunAsWork<SiteMembershipRequest>()
|
||||
{
|
||||
@Override
|
||||
public SiteMembershipRequest doWork() throws Exception
|
||||
{
|
||||
return inviteToSite(siteId, inviteeId, inviteeRole, message);
|
||||
}
|
||||
}, siteCreator, siteNetwork);
|
||||
}
|
||||
else
|
||||
{
|
||||
siteMembershipRequest = AuthenticationUtil.runAs(new RunAsWork<SiteMembershipRequest>()
|
||||
{
|
||||
@Override
|
||||
public SiteMembershipRequest doWork() throws Exception
|
||||
{
|
||||
return inviteToSite(siteId, inviteeId, inviteeRole, message);
|
||||
}
|
||||
}, siteCreator);
|
||||
}
|
||||
|
||||
return siteMembershipRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite)
|
||||
{
|
||||
SiteMembershipRequest request = null;
|
||||
|
||||
inviteeId = people.validatePerson(inviteeId, true);
|
||||
|
||||
// Note that the order of error checking is important. The server first needs to check for the status 404
|
||||
// conditions before checking for status 400 conditions. Otherwise the server is open to a probing attack.
|
||||
String siteId = siteInvite.getId();
|
||||
final SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
|
||||
final SiteVisibility siteVisibility = siteInfo.getVisibility();
|
||||
|
||||
if(siteVisibility.equals(SiteVisibility.PRIVATE))
|
||||
{
|
||||
// note: security, no indication that this is a private site
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
// Is the invitee already a member of the site?
|
||||
boolean isMember = siteService.isMember(siteId, inviteeId);
|
||||
if(isMember)
|
||||
{
|
||||
// yes
|
||||
throw new InvalidArgumentException(inviteeId + " is already a member of site " + siteId);
|
||||
}
|
||||
|
||||
// Is there an outstanding site invite request for the (invitee, site)?
|
||||
Invitation invitation = getSiteInvitation(inviteeId, siteId);
|
||||
if(invitation != null)
|
||||
{
|
||||
// yes
|
||||
throw new InvalidArgumentException(inviteeId + " is already invited to site " + siteId);
|
||||
}
|
||||
|
||||
final String inviteeRole = DEFAULT_ROLE;
|
||||
String message = siteInvite.getMessage();
|
||||
if(message == null)
|
||||
{
|
||||
// the invitation service ignores null messages so convert to an empty message.
|
||||
message = "";
|
||||
}
|
||||
|
||||
if(siteVisibility.equals(SiteVisibility.MODERATED))
|
||||
{
|
||||
request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole);
|
||||
}
|
||||
else if(siteVisibility.equals(SiteVisibility.PUBLIC))
|
||||
{
|
||||
request = inviteToPublicSite(siteInfo, message, inviteeId, inviteeRole);
|
||||
}
|
||||
else
|
||||
{
|
||||
// note: security, no indication that this is a private site
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiteMembershipRequest updateSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite)
|
||||
{
|
||||
SiteMembershipRequest updatedSiteInvite = null;
|
||||
|
||||
inviteeId = people.validatePerson(inviteeId, true);
|
||||
|
||||
String siteId = siteInvite.getId();
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
|
||||
String message = siteInvite.getMessage();
|
||||
if(message == null)
|
||||
{
|
||||
// the invitation service ignores null messages so convert to an empty message.
|
||||
message = "";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ModeratedInvitation updatedInvitation = invitationService.updateModeratedInvitation(inviteeId, siteId, message);
|
||||
if(updatedInvitation == null)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
updatedSiteInvite = getSiteMembershipRequest(updatedInvitation);
|
||||
}
|
||||
catch(InvitationExceptionNotFound e)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
if(updatedSiteInvite == null)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
return updatedSiteInvite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelSiteMembershipRequest(String inviteeId, String siteId)
|
||||
{
|
||||
inviteeId = people.validatePerson(inviteeId);
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
|
||||
Invitation invitation = getSiteInvitation(inviteeId, siteId);
|
||||
if(invitation == null)
|
||||
{
|
||||
// no such invitation
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
invitationService.cancel(invitation.getInviteId());
|
||||
}
|
||||
|
||||
public SiteMembershipRequest getSiteMembershipRequest(String inviteeId, final String siteId)
|
||||
{
|
||||
inviteeId = people.validatePerson(inviteeId);
|
||||
|
||||
SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork<SiteInfo>()
|
||||
{
|
||||
@Override
|
||||
public SiteInfo doWork() throws Exception
|
||||
{
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
return siteInfo;
|
||||
}
|
||||
});
|
||||
|
||||
if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED))
|
||||
{
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
String normalizedSiteId = siteInfo.getShortName();
|
||||
|
||||
Invitation invitation = getSiteInvitation(inviteeId, normalizedSiteId);
|
||||
if(invitation == null)
|
||||
{
|
||||
// no such invitation
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, normalizedSiteId);
|
||||
}
|
||||
if(invitation instanceof ModeratedInvitation)
|
||||
{
|
||||
ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation;
|
||||
SiteMembershipRequest siteInvite = getSiteMembershipRequest(moderatedInvitation);
|
||||
return siteInvite;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Expected moderated invitation");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-moderated sites cannot appear in a site membership request, so throw an exception
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
private SiteMembershipRequest getSiteMembershipRequest(ModeratedInvitation moderatedInvitation)
|
||||
{
|
||||
SiteMembershipRequest siteMembershipRequest = null;
|
||||
|
||||
ResourceType resourceType = moderatedInvitation.getResourceType();
|
||||
if(resourceType.equals(ResourceType.WEB_SITE))
|
||||
{
|
||||
final String siteId = moderatedInvitation.getResourceName();
|
||||
|
||||
SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork<SiteInfo>()
|
||||
{
|
||||
@Override
|
||||
public SiteInfo doWork() throws Exception
|
||||
{
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
return siteInfo;
|
||||
}
|
||||
});
|
||||
|
||||
if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED))
|
||||
{
|
||||
// return a site membership request only if this is a moderated site
|
||||
siteMembershipRequest = new SiteMembershipRequest();
|
||||
String title = siteInfo.getTitle();
|
||||
siteMembershipRequest.setTitle(title);
|
||||
siteMembershipRequest.setId(siteId);
|
||||
siteMembershipRequest.setMessage(moderatedInvitation.getInviteeComments());
|
||||
siteMembershipRequest.setCreatedAt(moderatedInvitation.getCreatedAt());
|
||||
siteMembershipRequest.setModifiedAt(moderatedInvitation.getModifiedAt());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Unexpected resource type " + resourceType + " for site membership request");
|
||||
}
|
||||
|
||||
return siteMembershipRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<SiteMembershipRequest> getPagedSiteMembershipRequests(String personId, Paging paging)
|
||||
{
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
int skipCount = paging.getSkipCount();
|
||||
int maxItems = paging.getMaxItems();
|
||||
int max = skipCount + maxItems + 1; // to detect hasMoreItems
|
||||
|
||||
List<Invitation> invitations = getSiteInvitations(personId);
|
||||
List<SiteMembershipRequest> siteMembershipRequests = new ArrayList<SiteMembershipRequest>(invitations.size());
|
||||
for(Invitation invitation : invitations)
|
||||
{
|
||||
if(invitation instanceof ModeratedInvitation)
|
||||
{
|
||||
ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation;
|
||||
SiteMembershipRequest siteMembershipRequest = getSiteMembershipRequest(moderatedInvitation);
|
||||
if(siteMembershipRequest != null)
|
||||
{
|
||||
// note: siteMembershipRequest may be null if the site is now no longer a moderated site
|
||||
// or if the invitation is malformed and does not refer to a site.
|
||||
siteMembershipRequests.add(siteMembershipRequest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just ignore, shouldn't happen because getSiteInvitations filters by ModeratedInvitation
|
||||
}
|
||||
}
|
||||
|
||||
// unfortunately, need to sort in memory because there's no way to get site membership requests sorted by title from
|
||||
// the workflow apis
|
||||
Collections.sort(siteMembershipRequests);
|
||||
|
||||
int totalItems = siteMembershipRequests.size();
|
||||
|
||||
if(skipCount >= totalItems)
|
||||
{
|
||||
List<SiteMembershipRequest> empty = Collections.emptyList();
|
||||
return CollectionWithPagingInfo.asPaged(paging, empty, false, totalItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
int end = Math.min(max - 1, totalItems);
|
||||
boolean hasMoreItems = totalItems > end;
|
||||
|
||||
siteMembershipRequests = siteMembershipRequests.subList(skipCount, end);
|
||||
return CollectionWithPagingInfo.asPaged(paging, siteMembershipRequests, hasMoreItems, totalItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.invitation.InvitationSearchCriteriaImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.repo.tenant.NetworksService;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.SiteMembershipRequests;
|
||||
import org.alfresco.rest.api.Sites;
|
||||
import org.alfresco.rest.api.model.SiteMembershipRequest;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.cmr.invitation.Invitation;
|
||||
import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
|
||||
import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound;
|
||||
import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType;
|
||||
import org.alfresco.service.cmr.invitation.InvitationService;
|
||||
import org.alfresco.service.cmr.invitation.ModeratedInvitation;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Public REST API: centralises access to site membership requests and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class SiteMembershipRequestsImpl implements SiteMembershipRequests
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(SiteMembershipRequestsImpl.class);
|
||||
|
||||
// Default role to assign to the site membership request
|
||||
public final static String DEFAULT_ROLE = SiteModel.SITE_CONSUMER;
|
||||
|
||||
private People people;
|
||||
private Sites sites;
|
||||
private SiteService siteService;
|
||||
private NodeService nodeService;
|
||||
private InvitationService invitationService;
|
||||
private NetworksService networksService;
|
||||
|
||||
public void setNetworksService(NetworksService networksService)
|
||||
{
|
||||
this.networksService = networksService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
this.people = people;
|
||||
}
|
||||
|
||||
public void setSites(Sites sites)
|
||||
{
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setInvitationService(InvitationService invitationService)
|
||||
{
|
||||
this.invitationService = invitationService;
|
||||
}
|
||||
|
||||
private Invitation getSiteInvitation(String inviteeId, String siteId)
|
||||
{
|
||||
// Is there an outstanding site invite request for the invitee?
|
||||
InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl();
|
||||
criteria.setInvitationType(InvitationType.MODERATED);
|
||||
criteria.setInvitee(inviteeId);
|
||||
criteria.setResourceName(siteId);
|
||||
criteria.setResourceType(ResourceType.WEB_SITE);
|
||||
List<Invitation> invitations = invitationService.searchInvitation(criteria);
|
||||
if(invitations.size() > 1)
|
||||
{
|
||||
// TODO exception
|
||||
throw new AlfrescoRuntimeException("There should be only one outstanding site invitation");
|
||||
}
|
||||
return (invitations.size() == 0 ? null : invitations.get(0));
|
||||
}
|
||||
|
||||
private List<Invitation> getSiteInvitations(String inviteeId)
|
||||
{
|
||||
InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl();
|
||||
criteria.setInvitationType(InvitationType.MODERATED);
|
||||
criteria.setInvitee(inviteeId);
|
||||
criteria.setResourceType(ResourceType.WEB_SITE);
|
||||
List<Invitation> invitations = invitationService.searchInvitation(criteria);
|
||||
return invitations;
|
||||
}
|
||||
|
||||
private SiteMembershipRequest inviteToModeratedSite(final String message, final String inviteeId, final String siteId,
|
||||
final String inviteeRole)
|
||||
{
|
||||
ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole);
|
||||
|
||||
SiteMembershipRequest ret = new SiteMembershipRequest();
|
||||
ret.setId(siteId);
|
||||
ret.setMessage(message);
|
||||
ret.setCreatedAt(invitation.getCreatedAt());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SiteMembershipRequest inviteToSite(String siteId, String inviteeId, String inviteeRole, String message)
|
||||
{
|
||||
siteService.setMembership(siteId, inviteeId, inviteeRole);
|
||||
SiteMembershipRequest ret = new SiteMembershipRequest();
|
||||
ret.setId(siteId);
|
||||
ret.setMessage(message);
|
||||
Date createdAt = new Date();
|
||||
ret.setCreatedAt(createdAt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SiteMembershipRequest inviteToPublicSite(final SiteInfo siteInfo, final String message, final String inviteeId,
|
||||
final String inviteeRole)
|
||||
{
|
||||
SiteMembershipRequest siteMembershipRequest = null;
|
||||
|
||||
final String siteId = siteInfo.getShortName();
|
||||
NodeRef siteNodeRef = siteInfo.getNodeRef();
|
||||
String siteCreator = (String)nodeService.getProperty(siteNodeRef, ContentModel.PROP_CREATOR);
|
||||
|
||||
final String siteNetwork = networksService.getUserDefaultNetwork(siteCreator);
|
||||
if(StringUtils.isNotEmpty(siteNetwork))
|
||||
{
|
||||
// MT
|
||||
siteMembershipRequest = TenantUtil.runAsUserTenant(new TenantRunAsWork<SiteMembershipRequest>()
|
||||
{
|
||||
@Override
|
||||
public SiteMembershipRequest doWork() throws Exception
|
||||
{
|
||||
return inviteToSite(siteId, inviteeId, inviteeRole, message);
|
||||
}
|
||||
}, siteCreator, siteNetwork);
|
||||
}
|
||||
else
|
||||
{
|
||||
siteMembershipRequest = AuthenticationUtil.runAs(new RunAsWork<SiteMembershipRequest>()
|
||||
{
|
||||
@Override
|
||||
public SiteMembershipRequest doWork() throws Exception
|
||||
{
|
||||
return inviteToSite(siteId, inviteeId, inviteeRole, message);
|
||||
}
|
||||
}, siteCreator);
|
||||
}
|
||||
|
||||
return siteMembershipRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite)
|
||||
{
|
||||
SiteMembershipRequest request = null;
|
||||
|
||||
inviteeId = people.validatePerson(inviteeId, true);
|
||||
|
||||
// Note that the order of error checking is important. The server first needs to check for the status 404
|
||||
// conditions before checking for status 400 conditions. Otherwise the server is open to a probing attack.
|
||||
String siteId = siteInvite.getId();
|
||||
final SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
|
||||
final SiteVisibility siteVisibility = siteInfo.getVisibility();
|
||||
|
||||
if(siteVisibility.equals(SiteVisibility.PRIVATE))
|
||||
{
|
||||
// note: security, no indication that this is a private site
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
// Is the invitee already a member of the site?
|
||||
boolean isMember = siteService.isMember(siteId, inviteeId);
|
||||
if(isMember)
|
||||
{
|
||||
// yes
|
||||
throw new InvalidArgumentException(inviteeId + " is already a member of site " + siteId);
|
||||
}
|
||||
|
||||
// Is there an outstanding site invite request for the (invitee, site)?
|
||||
Invitation invitation = getSiteInvitation(inviteeId, siteId);
|
||||
if(invitation != null)
|
||||
{
|
||||
// yes
|
||||
throw new InvalidArgumentException(inviteeId + " is already invited to site " + siteId);
|
||||
}
|
||||
|
||||
final String inviteeRole = DEFAULT_ROLE;
|
||||
String message = siteInvite.getMessage();
|
||||
if(message == null)
|
||||
{
|
||||
// the invitation service ignores null messages so convert to an empty message.
|
||||
message = "";
|
||||
}
|
||||
|
||||
if(siteVisibility.equals(SiteVisibility.MODERATED))
|
||||
{
|
||||
request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole);
|
||||
}
|
||||
else if(siteVisibility.equals(SiteVisibility.PUBLIC))
|
||||
{
|
||||
request = inviteToPublicSite(siteInfo, message, inviteeId, inviteeRole);
|
||||
}
|
||||
else
|
||||
{
|
||||
// note: security, no indication that this is a private site
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiteMembershipRequest updateSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite)
|
||||
{
|
||||
SiteMembershipRequest updatedSiteInvite = null;
|
||||
|
||||
inviteeId = people.validatePerson(inviteeId, true);
|
||||
|
||||
String siteId = siteInvite.getId();
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
|
||||
String message = siteInvite.getMessage();
|
||||
if(message == null)
|
||||
{
|
||||
// the invitation service ignores null messages so convert to an empty message.
|
||||
message = "";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ModeratedInvitation updatedInvitation = invitationService.updateModeratedInvitation(inviteeId, siteId, message);
|
||||
if(updatedInvitation == null)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
updatedSiteInvite = getSiteMembershipRequest(updatedInvitation);
|
||||
}
|
||||
catch(InvitationExceptionNotFound e)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
if(updatedSiteInvite == null)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
|
||||
return updatedSiteInvite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelSiteMembershipRequest(String inviteeId, String siteId)
|
||||
{
|
||||
inviteeId = people.validatePerson(inviteeId);
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
if(siteInfo == null)
|
||||
{
|
||||
// site does not exist
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
siteId = siteInfo.getShortName();
|
||||
|
||||
Invitation invitation = getSiteInvitation(inviteeId, siteId);
|
||||
if(invitation == null)
|
||||
{
|
||||
// no such invitation
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
invitationService.cancel(invitation.getInviteId());
|
||||
}
|
||||
|
||||
public SiteMembershipRequest getSiteMembershipRequest(String inviteeId, final String siteId)
|
||||
{
|
||||
inviteeId = people.validatePerson(inviteeId);
|
||||
|
||||
SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork<SiteInfo>()
|
||||
{
|
||||
@Override
|
||||
public SiteInfo doWork() throws Exception
|
||||
{
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
return siteInfo;
|
||||
}
|
||||
});
|
||||
|
||||
if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED))
|
||||
{
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
String normalizedSiteId = siteInfo.getShortName();
|
||||
|
||||
Invitation invitation = getSiteInvitation(inviteeId, normalizedSiteId);
|
||||
if(invitation == null)
|
||||
{
|
||||
// no such invitation
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, normalizedSiteId);
|
||||
}
|
||||
if(invitation instanceof ModeratedInvitation)
|
||||
{
|
||||
ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation;
|
||||
SiteMembershipRequest siteInvite = getSiteMembershipRequest(moderatedInvitation);
|
||||
return siteInvite;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Expected moderated invitation");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-moderated sites cannot appear in a site membership request, so throw an exception
|
||||
throw new RelationshipResourceNotFoundException(inviteeId, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
private SiteMembershipRequest getSiteMembershipRequest(ModeratedInvitation moderatedInvitation)
|
||||
{
|
||||
SiteMembershipRequest siteMembershipRequest = null;
|
||||
|
||||
ResourceType resourceType = moderatedInvitation.getResourceType();
|
||||
if(resourceType.equals(ResourceType.WEB_SITE))
|
||||
{
|
||||
final String siteId = moderatedInvitation.getResourceName();
|
||||
|
||||
SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork<SiteInfo>()
|
||||
{
|
||||
@Override
|
||||
public SiteInfo doWork() throws Exception
|
||||
{
|
||||
SiteInfo siteInfo = sites.validateSite(siteId);
|
||||
return siteInfo;
|
||||
}
|
||||
});
|
||||
|
||||
if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED))
|
||||
{
|
||||
// return a site membership request only if this is a moderated site
|
||||
siteMembershipRequest = new SiteMembershipRequest();
|
||||
String title = siteInfo.getTitle();
|
||||
siteMembershipRequest.setTitle(title);
|
||||
siteMembershipRequest.setId(siteId);
|
||||
siteMembershipRequest.setMessage(moderatedInvitation.getInviteeComments());
|
||||
siteMembershipRequest.setCreatedAt(moderatedInvitation.getCreatedAt());
|
||||
siteMembershipRequest.setModifiedAt(moderatedInvitation.getModifiedAt());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Unexpected resource type " + resourceType + " for site membership request");
|
||||
}
|
||||
|
||||
return siteMembershipRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<SiteMembershipRequest> getPagedSiteMembershipRequests(String personId, Paging paging)
|
||||
{
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
int skipCount = paging.getSkipCount();
|
||||
int maxItems = paging.getMaxItems();
|
||||
int max = skipCount + maxItems + 1; // to detect hasMoreItems
|
||||
|
||||
List<Invitation> invitations = getSiteInvitations(personId);
|
||||
List<SiteMembershipRequest> siteMembershipRequests = new ArrayList<SiteMembershipRequest>(invitations.size());
|
||||
for(Invitation invitation : invitations)
|
||||
{
|
||||
if(invitation instanceof ModeratedInvitation)
|
||||
{
|
||||
ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation;
|
||||
SiteMembershipRequest siteMembershipRequest = getSiteMembershipRequest(moderatedInvitation);
|
||||
if(siteMembershipRequest != null)
|
||||
{
|
||||
// note: siteMembershipRequest may be null if the site is now no longer a moderated site
|
||||
// or if the invitation is malformed and does not refer to a site.
|
||||
siteMembershipRequests.add(siteMembershipRequest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just ignore, shouldn't happen because getSiteInvitations filters by ModeratedInvitation
|
||||
}
|
||||
}
|
||||
|
||||
// unfortunately, need to sort in memory because there's no way to get site membership requests sorted by title from
|
||||
// the workflow apis
|
||||
Collections.sort(siteMembershipRequests);
|
||||
|
||||
int totalItems = siteMembershipRequests.size();
|
||||
|
||||
if(skipCount >= totalItems)
|
||||
{
|
||||
List<SiteMembershipRequest> empty = Collections.emptyList();
|
||||
return CollectionWithPagingInfo.asPaged(paging, empty, false, totalItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
int end = Math.min(max - 1, totalItems);
|
||||
boolean hasMoreItems = totalItems > end;
|
||||
|
||||
siteMembershipRequests = siteMembershipRequests.subList(skipCount, end);
|
||||
return CollectionWithPagingInfo.asPaged(paging, siteMembershipRequests, hasMoreItems, totalItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,188 +1,188 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tagging.NonExistentTagException;
|
||||
import org.alfresco.repo.tagging.TagExistsException;
|
||||
import org.alfresco.repo.tagging.TaggingException;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
|
||||
/**
|
||||
* Centralises access to tag services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class TagsImpl implements Tags
|
||||
{
|
||||
private Nodes nodes;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot tag this node");
|
||||
}
|
||||
|
||||
List<String> tagValues = new AbstractList<String>()
|
||||
{
|
||||
@Override
|
||||
public String get(int arg0)
|
||||
{
|
||||
String tag = tags.get(arg0).getTag();
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return tags.size();
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<Tag>(tags.size());
|
||||
for(Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
{
|
||||
ret.add(new Tag(pair.getSecond(), pair.getFirst()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTag(String nodeId, String tagId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(tagId);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Paging paging)
|
||||
{
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(storeRef, Util.getPagingRequest(paging));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
public NodeRef validateTag(String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef validateTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return new Tag(newTagNodeRef, newTagName);
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Tag getTag(String tagId)
|
||||
{
|
||||
return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId);
|
||||
}
|
||||
|
||||
public Tag getTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
return new Tag(tagNodeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params)
|
||||
{
|
||||
NodeRef nodeRef = validateTag(nodeId);
|
||||
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging()));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tagging.NonExistentTagException;
|
||||
import org.alfresco.repo.tagging.TagExistsException;
|
||||
import org.alfresco.repo.tagging.TaggingException;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
|
||||
/**
|
||||
* Centralises access to tag services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class TagsImpl implements Tags
|
||||
{
|
||||
private Nodes nodes;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot tag this node");
|
||||
}
|
||||
|
||||
List<String> tagValues = new AbstractList<String>()
|
||||
{
|
||||
@Override
|
||||
public String get(int arg0)
|
||||
{
|
||||
String tag = tags.get(arg0).getTag();
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return tags.size();
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<Tag>(tags.size());
|
||||
for(Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
{
|
||||
ret.add(new Tag(pair.getSecond(), pair.getFirst()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTag(String nodeId, String tagId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(tagId);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Paging paging)
|
||||
{
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(storeRef, Util.getPagingRequest(paging));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
public NodeRef validateTag(String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef validateTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return new Tag(newTagNodeRef, newTagName);
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Tag getTag(String tagId)
|
||||
{
|
||||
return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId);
|
||||
}
|
||||
|
||||
public Tag getTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
return new Tag(tagNodeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params)
|
||||
{
|
||||
NodeRef nodeRef = validateTag(nodeId);
|
||||
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging()));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,15 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.query.CannedQueryPageDetails;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
|
||||
public class Util
|
||||
{
|
||||
public static PagingRequest getPagingRequest(Paging paging)
|
||||
{
|
||||
PagingRequest pagingRequest = new PagingRequest(paging.getSkipCount(), paging.getMaxItems());
|
||||
pagingRequest.setRequestTotalCountMax(CannedQueryPageDetails.DEFAULT_PAGE_SIZE);
|
||||
return pagingRequest;
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import org.alfresco.query.CannedQueryPageDetails;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
|
||||
public class Util
|
||||
{
|
||||
public static PagingRequest getPagingRequest(Paging paging)
|
||||
{
|
||||
PagingRequest pagingRequest = new PagingRequest(paging.getSkipCount(), paging.getMaxItems());
|
||||
pagingRequest.setRequestTotalCountMax(CannedQueryPageDetails.DEFAULT_PAGE_SIZE);
|
||||
return pagingRequest;
|
||||
}
|
||||
}
|
||||
|
@@ -1,119 +1,119 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
|
||||
public abstract class AbstractActivitySummaryProcessor extends AbstractLifecycleBean implements ActivitySummaryProcessor
|
||||
{
|
||||
protected static Log logger = LogFactory.getLog(ActivitySummaryProcessor.class);
|
||||
|
||||
protected ActivitySummaryProcessorRegistry registry;
|
||||
private List<String> eventTypes;
|
||||
|
||||
public void setEventTypes(List<String> eventTypes)
|
||||
{
|
||||
this.eventTypes = eventTypes;
|
||||
}
|
||||
|
||||
public void setRegistry(ActivitySummaryProcessorRegistry registry)
|
||||
{
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public void setCustomRenditions(List<String> eventTypes)
|
||||
{
|
||||
this.eventTypes = eventTypes;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
register();
|
||||
}
|
||||
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> process(Map<String, Object> entries)
|
||||
{
|
||||
List<Change> changes = new LinkedList<Change>();
|
||||
Map<String, Object> ret = new HashMap<String, Object>(entries.size());
|
||||
for(Map.Entry<String, Object> entry : entries.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
Change change = processEntry(key, value);
|
||||
if(change != null)
|
||||
{
|
||||
changes.add(change);
|
||||
}
|
||||
}
|
||||
|
||||
for(Change change : changes)
|
||||
{
|
||||
if(change != null)
|
||||
{
|
||||
change.process(entries);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected abstract Change processEntry(String key, Object value);
|
||||
|
||||
protected void register()
|
||||
{
|
||||
for(String eventType : eventTypes)
|
||||
{
|
||||
registry.register(eventType, this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChangeKey implements Change
|
||||
{
|
||||
private String oldKey;
|
||||
private String newKey;
|
||||
|
||||
public ChangeKey(String oldKey, String newKey) {
|
||||
super();
|
||||
this.oldKey = oldKey;
|
||||
this.newKey = newKey;
|
||||
}
|
||||
|
||||
public void process(Map<String, Object> entries)
|
||||
{
|
||||
Object value = entries.remove(oldKey);
|
||||
entries.put(newKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RemoveKey implements Change
|
||||
{
|
||||
private String key;
|
||||
|
||||
public RemoveKey(String key) {
|
||||
super();
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void process(Map<String, Object> entries)
|
||||
{
|
||||
entries.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
|
||||
public abstract class AbstractActivitySummaryProcessor extends AbstractLifecycleBean implements ActivitySummaryProcessor
|
||||
{
|
||||
protected static Log logger = LogFactory.getLog(ActivitySummaryProcessor.class);
|
||||
|
||||
protected ActivitySummaryProcessorRegistry registry;
|
||||
private List<String> eventTypes;
|
||||
|
||||
public void setEventTypes(List<String> eventTypes)
|
||||
{
|
||||
this.eventTypes = eventTypes;
|
||||
}
|
||||
|
||||
public void setRegistry(ActivitySummaryProcessorRegistry registry)
|
||||
{
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public void setCustomRenditions(List<String> eventTypes)
|
||||
{
|
||||
this.eventTypes = eventTypes;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
register();
|
||||
}
|
||||
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> process(Map<String, Object> entries)
|
||||
{
|
||||
List<Change> changes = new LinkedList<Change>();
|
||||
Map<String, Object> ret = new HashMap<String, Object>(entries.size());
|
||||
for(Map.Entry<String, Object> entry : entries.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
Change change = processEntry(key, value);
|
||||
if(change != null)
|
||||
{
|
||||
changes.add(change);
|
||||
}
|
||||
}
|
||||
|
||||
for(Change change : changes)
|
||||
{
|
||||
if(change != null)
|
||||
{
|
||||
change.process(entries);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected abstract Change processEntry(String key, Object value);
|
||||
|
||||
protected void register()
|
||||
{
|
||||
for(String eventType : eventTypes)
|
||||
{
|
||||
registry.register(eventType, this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChangeKey implements Change
|
||||
{
|
||||
private String oldKey;
|
||||
private String newKey;
|
||||
|
||||
public ChangeKey(String oldKey, String newKey) {
|
||||
super();
|
||||
this.oldKey = oldKey;
|
||||
this.newKey = newKey;
|
||||
}
|
||||
|
||||
public void process(Map<String, Object> entries)
|
||||
{
|
||||
Object value = entries.remove(oldKey);
|
||||
entries.put(newKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RemoveKey implements Change
|
||||
{
|
||||
private String key;
|
||||
|
||||
public RemoveKey(String key) {
|
||||
super();
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void process(Map<String, Object> entries)
|
||||
{
|
||||
entries.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,168 +1,168 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
|
||||
/*
|
||||
* Adapted from JSONtoFmModel
|
||||
*/
|
||||
public class ActivitySummaryParser implements ActivitySummaryProcessorRegistry
|
||||
{
|
||||
private final Log logger = LogFactory.getLog(ActivitySummaryParser.class);
|
||||
|
||||
// note: current format is dependent on ISO8601DateFormat.parser, eg. YYYY-MM-DDThh:mm:ss.sssTZD
|
||||
private static String REGEXP_ISO8061 = "^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(.([0-9]){3})?(Z|[\\+\\-]([0-9]{2}):([0-9]{2}))$";
|
||||
private static Pattern matcherISO8601 = Pattern.compile(REGEXP_ISO8061);
|
||||
private static final Pattern nodeRefPattern = Pattern.compile("^[a-zA-Z]+://.+/.+");
|
||||
|
||||
private NamedObjectRegistry<ActivitySummaryProcessor> processors;
|
||||
|
||||
private boolean autoConvertISO8601 = true;
|
||||
|
||||
public ActivitySummaryParser()
|
||||
{
|
||||
}
|
||||
|
||||
public void setProcessors(NamedObjectRegistry<ActivitySummaryProcessor> processors)
|
||||
{
|
||||
this.processors = processors;
|
||||
}
|
||||
|
||||
public void register(String activityType, ActivitySummaryProcessor processor)
|
||||
{
|
||||
ActivitySummaryProcessor existingProcessor = processors.getNamedObject(activityType);
|
||||
if(existingProcessor != null)
|
||||
{
|
||||
logger.warn("Activity summary processor " + existingProcessor + " is being overridden by " + processor + " for activity type " + activityType);
|
||||
}
|
||||
|
||||
processors.register(activityType, processor);
|
||||
}
|
||||
|
||||
private void processActivitySummary(String activityType, Map<String, Object> entries)
|
||||
{
|
||||
ActivitySummaryProcessor processor = processors.getNamedObject(activityType);
|
||||
if(processor == null)
|
||||
{
|
||||
processor = new BaseActivitySummaryProcessor();
|
||||
}
|
||||
|
||||
processor.process(entries);
|
||||
}
|
||||
|
||||
public Map<String, Object> parse(String activityType, String activitySummary) throws JSONException
|
||||
{
|
||||
JSONObject json = (JSONObject)JSONValue.parse(activitySummary);
|
||||
Map<String, Object> map = convertJSONObjectToMap(json);
|
||||
processActivitySummary(activityType, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if passed string conforms to the pattern of a node reference
|
||||
*
|
||||
* @param nodeRef the node reference as a string
|
||||
* @return true => it matches the pattern of a node reference
|
||||
*/
|
||||
private boolean isNodeRef(String nodeRef)
|
||||
{
|
||||
Matcher matcher = nodeRefPattern.matcher(nodeRef);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
Map<String, Object> convertJSONObjectToMap(JSONObject jo) throws JSONException
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
for(Object key : jo.keySet())
|
||||
{
|
||||
Object value = jo.get(key);
|
||||
if (value instanceof JSONObject)
|
||||
{
|
||||
model.put((String)key, convertJSONObjectToMap((JSONObject)value));
|
||||
}
|
||||
else if (value instanceof JSONArray)
|
||||
{
|
||||
model.put((String)key, convertJSONArrayToList((JSONArray)value));
|
||||
}
|
||||
else if (value == null)
|
||||
{
|
||||
model.put((String)key, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((value instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)value).matches()))
|
||||
{
|
||||
value = ISO8601DateFormat.parse((String)value);
|
||||
}
|
||||
|
||||
if ((value instanceof String) && isNodeRef((String)value))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = new NodeRef((String)value);
|
||||
}
|
||||
catch(AlfrescoRuntimeException e)
|
||||
{
|
||||
// cannot convert to a nodeRef, just keep as a string
|
||||
logger.warn("Cannot convert activity summary NodeRef string " + value + " to a NodeRef");
|
||||
}
|
||||
}
|
||||
|
||||
model.put((String)key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
List<Object> convertJSONArrayToList(JSONArray ja) throws JSONException
|
||||
{
|
||||
List<Object> model = new ArrayList<Object>();
|
||||
|
||||
for (int i = 0; i < ja.size(); i++)
|
||||
{
|
||||
Object o = ja.get(i);
|
||||
|
||||
if (o instanceof JSONArray)
|
||||
{
|
||||
model.add(convertJSONArrayToList((JSONArray)o));
|
||||
}
|
||||
else if (o instanceof JSONObject)
|
||||
{
|
||||
model.add(convertJSONObjectToMap((JSONObject)o));
|
||||
}
|
||||
else if (o == null)
|
||||
{
|
||||
model.add(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((o instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)o).matches()))
|
||||
{
|
||||
o = ISO8601DateFormat.parse((String)o);
|
||||
}
|
||||
|
||||
model.add(o);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
|
||||
/*
|
||||
* Adapted from JSONtoFmModel
|
||||
*/
|
||||
public class ActivitySummaryParser implements ActivitySummaryProcessorRegistry
|
||||
{
|
||||
private final Log logger = LogFactory.getLog(ActivitySummaryParser.class);
|
||||
|
||||
// note: current format is dependent on ISO8601DateFormat.parser, eg. YYYY-MM-DDThh:mm:ss.sssTZD
|
||||
private static String REGEXP_ISO8061 = "^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(.([0-9]){3})?(Z|[\\+\\-]([0-9]{2}):([0-9]{2}))$";
|
||||
private static Pattern matcherISO8601 = Pattern.compile(REGEXP_ISO8061);
|
||||
private static final Pattern nodeRefPattern = Pattern.compile("^[a-zA-Z]+://.+/.+");
|
||||
|
||||
private NamedObjectRegistry<ActivitySummaryProcessor> processors;
|
||||
|
||||
private boolean autoConvertISO8601 = true;
|
||||
|
||||
public ActivitySummaryParser()
|
||||
{
|
||||
}
|
||||
|
||||
public void setProcessors(NamedObjectRegistry<ActivitySummaryProcessor> processors)
|
||||
{
|
||||
this.processors = processors;
|
||||
}
|
||||
|
||||
public void register(String activityType, ActivitySummaryProcessor processor)
|
||||
{
|
||||
ActivitySummaryProcessor existingProcessor = processors.getNamedObject(activityType);
|
||||
if(existingProcessor != null)
|
||||
{
|
||||
logger.warn("Activity summary processor " + existingProcessor + " is being overridden by " + processor + " for activity type " + activityType);
|
||||
}
|
||||
|
||||
processors.register(activityType, processor);
|
||||
}
|
||||
|
||||
private void processActivitySummary(String activityType, Map<String, Object> entries)
|
||||
{
|
||||
ActivitySummaryProcessor processor = processors.getNamedObject(activityType);
|
||||
if(processor == null)
|
||||
{
|
||||
processor = new BaseActivitySummaryProcessor();
|
||||
}
|
||||
|
||||
processor.process(entries);
|
||||
}
|
||||
|
||||
public Map<String, Object> parse(String activityType, String activitySummary) throws JSONException
|
||||
{
|
||||
JSONObject json = (JSONObject)JSONValue.parse(activitySummary);
|
||||
Map<String, Object> map = convertJSONObjectToMap(json);
|
||||
processActivitySummary(activityType, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if passed string conforms to the pattern of a node reference
|
||||
*
|
||||
* @param nodeRef the node reference as a string
|
||||
* @return true => it matches the pattern of a node reference
|
||||
*/
|
||||
private boolean isNodeRef(String nodeRef)
|
||||
{
|
||||
Matcher matcher = nodeRefPattern.matcher(nodeRef);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
Map<String, Object> convertJSONObjectToMap(JSONObject jo) throws JSONException
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
for(Object key : jo.keySet())
|
||||
{
|
||||
Object value = jo.get(key);
|
||||
if (value instanceof JSONObject)
|
||||
{
|
||||
model.put((String)key, convertJSONObjectToMap((JSONObject)value));
|
||||
}
|
||||
else if (value instanceof JSONArray)
|
||||
{
|
||||
model.put((String)key, convertJSONArrayToList((JSONArray)value));
|
||||
}
|
||||
else if (value == null)
|
||||
{
|
||||
model.put((String)key, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((value instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)value).matches()))
|
||||
{
|
||||
value = ISO8601DateFormat.parse((String)value);
|
||||
}
|
||||
|
||||
if ((value instanceof String) && isNodeRef((String)value))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = new NodeRef((String)value);
|
||||
}
|
||||
catch(AlfrescoRuntimeException e)
|
||||
{
|
||||
// cannot convert to a nodeRef, just keep as a string
|
||||
logger.warn("Cannot convert activity summary NodeRef string " + value + " to a NodeRef");
|
||||
}
|
||||
}
|
||||
|
||||
model.put((String)key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
List<Object> convertJSONArrayToList(JSONArray ja) throws JSONException
|
||||
{
|
||||
List<Object> model = new ArrayList<Object>();
|
||||
|
||||
for (int i = 0; i < ja.size(); i++)
|
||||
{
|
||||
Object o = ja.get(i);
|
||||
|
||||
if (o instanceof JSONArray)
|
||||
{
|
||||
model.add(convertJSONArrayToList((JSONArray)o));
|
||||
}
|
||||
else if (o instanceof JSONObject)
|
||||
{
|
||||
model.add(convertJSONObjectToMap((JSONObject)o));
|
||||
}
|
||||
else if (o == null)
|
||||
{
|
||||
model.add(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((o instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)o).matches()))
|
||||
{
|
||||
o = ISO8601DateFormat.parse((String)o);
|
||||
}
|
||||
|
||||
model.add(o);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ActivitySummaryProcessor
|
||||
{
|
||||
public interface Change
|
||||
{
|
||||
void process(Map<String, Object> entries);
|
||||
}
|
||||
|
||||
public Map<String, Object> process(Map<String, Object> entries);
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ActivitySummaryProcessor
|
||||
{
|
||||
public interface Change
|
||||
{
|
||||
void process(Map<String, Object> entries);
|
||||
}
|
||||
|
||||
public Map<String, Object> process(Map<String, Object> entries);
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
/**
|
||||
* A registry for activity summary parsers/post processors.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public interface ActivitySummaryProcessorRegistry
|
||||
{
|
||||
public void register(String activityType, ActivitySummaryProcessor processor);
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
/**
|
||||
* A registry for activity summary parsers/post processors.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public interface ActivitySummaryProcessorRegistry
|
||||
{
|
||||
public void register(String activityType, ActivitySummaryProcessor processor);
|
||||
}
|
||||
|
@@ -1,96 +1,96 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.rest.api.impl.activities.AbstractActivitySummaryProcessor.RemoveKey;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
public class BaseActivitySummaryProcessor extends AbstractActivitySummaryProcessor
|
||||
{
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = null;
|
||||
|
||||
if(key.equals("page"))
|
||||
{
|
||||
change = new ChangePageValue(key);
|
||||
}
|
||||
|
||||
if(key.equals("tenantDomain"))
|
||||
{
|
||||
change = new RemoveKey(key);
|
||||
}
|
||||
|
||||
if(key.equals("nodeRef"))
|
||||
{
|
||||
change = new ChangeKey(key, "objectId");
|
||||
}
|
||||
|
||||
if(key.equals("parentNodeRef"))
|
||||
{
|
||||
change = new ChangeKey(key, "parentObjectId");
|
||||
}
|
||||
|
||||
// remove null or empty properties
|
||||
if(value == null || value.equals(""))
|
||||
{
|
||||
change = new RemoveKey(key);
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
public static class ChangePageValue implements Change
|
||||
{
|
||||
private String key;
|
||||
private static final String regex = Pattern.quote("document-details?nodeRef=") + "(.*)";
|
||||
private static final Pattern pattern = Pattern.compile(regex);
|
||||
|
||||
public ChangePageValue(String key) {
|
||||
super();
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract and output the node id from input that looks like this: document-details?nodeRef=workspace%3A%2F%2FSpacesStore%2Fd4c1a75e-a17e-4033-94f4-988cca39a357 (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.rest.api.impl.activities.ActivitySummaryProcessor.Change#process(java.util.Map)
|
||||
*/
|
||||
public void process(Map<String, Object> entries)
|
||||
{
|
||||
String value = (String)entries.remove(key);
|
||||
try
|
||||
{
|
||||
value = URLDecoder.decode(value, "UTF-8");
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if(matcher.matches())
|
||||
{
|
||||
String nodeRefStr = matcher.group(1);
|
||||
boolean isNodeRef = NodeRef.isNodeRef(nodeRefStr);
|
||||
if(isNodeRef)
|
||||
{
|
||||
NodeRef nodeRef = new NodeRef(nodeRefStr);
|
||||
entries.put("objectId", nodeRef.getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Activity page url contains an invalid NodeRef " + value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Failed to match activity page url for objectId extraction " + value);
|
||||
}
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
logger.warn("Unable to decode activity page url " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.rest.api.impl.activities.AbstractActivitySummaryProcessor.RemoveKey;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
public class BaseActivitySummaryProcessor extends AbstractActivitySummaryProcessor
|
||||
{
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = null;
|
||||
|
||||
if(key.equals("page"))
|
||||
{
|
||||
change = new ChangePageValue(key);
|
||||
}
|
||||
|
||||
if(key.equals("tenantDomain"))
|
||||
{
|
||||
change = new RemoveKey(key);
|
||||
}
|
||||
|
||||
if(key.equals("nodeRef"))
|
||||
{
|
||||
change = new ChangeKey(key, "objectId");
|
||||
}
|
||||
|
||||
if(key.equals("parentNodeRef"))
|
||||
{
|
||||
change = new ChangeKey(key, "parentObjectId");
|
||||
}
|
||||
|
||||
// remove null or empty properties
|
||||
if(value == null || value.equals(""))
|
||||
{
|
||||
change = new RemoveKey(key);
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
public static class ChangePageValue implements Change
|
||||
{
|
||||
private String key;
|
||||
private static final String regex = Pattern.quote("document-details?nodeRef=") + "(.*)";
|
||||
private static final Pattern pattern = Pattern.compile(regex);
|
||||
|
||||
public ChangePageValue(String key) {
|
||||
super();
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract and output the node id from input that looks like this: document-details?nodeRef=workspace%3A%2F%2FSpacesStore%2Fd4c1a75e-a17e-4033-94f4-988cca39a357 (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.rest.api.impl.activities.ActivitySummaryProcessor.Change#process(java.util.Map)
|
||||
*/
|
||||
public void process(Map<String, Object> entries)
|
||||
{
|
||||
String value = (String)entries.remove(key);
|
||||
try
|
||||
{
|
||||
value = URLDecoder.decode(value, "UTF-8");
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if(matcher.matches())
|
||||
{
|
||||
String nodeRefStr = matcher.group(1);
|
||||
boolean isNodeRef = NodeRef.isNodeRef(nodeRefStr);
|
||||
if(isNodeRef)
|
||||
{
|
||||
NodeRef nodeRef = new NodeRef(nodeRefStr);
|
||||
entries.put("objectId", nodeRef.getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Activity page url contains an invalid NodeRef " + value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Failed to match activity page url for objectId extraction " + value);
|
||||
}
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
logger.warn("Unable to decode activity page url " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class CommentsActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class CommentsActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,17 +1,17 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class DiscussionsActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = null;
|
||||
|
||||
if(key.equals("params"))
|
||||
{
|
||||
change = new RemoveKey(key);
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class DiscussionsActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = null;
|
||||
|
||||
if(key.equals("params"))
|
||||
{
|
||||
change = new RemoveKey(key);
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class DocumentLibraryActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class DocumentLibraryActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class SiteActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = super.processEntry(key, value);
|
||||
|
||||
if(key.equals("memberUserName"))
|
||||
{
|
||||
change = new ChangeKey(key, "memberPersonId");
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class SiteActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = super.processEntry(key, value);
|
||||
|
||||
if(key.equals("memberUserName"))
|
||||
{
|
||||
change = new ChangeKey(key, "memberPersonId");
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,26 +1,26 @@
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class SubscriptionsActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
//{"lastName":"Glover","userFirstName":"David","followerLastName":"Glover","userUserName":"david.bowie@alfresco.com","followerFirstName":"Steve",
|
||||
// "userLastName":"Bowie","followerUserName":"steven.glover@alfresco.com","firstName":"Steve","tenantDomain":"alfresco.com"}
|
||||
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = super.processEntry(key, value);
|
||||
|
||||
if(key.equals("userUserName"))
|
||||
{
|
||||
change = new ChangeKey(key, "userPersonId");
|
||||
}
|
||||
|
||||
if(key.equals("followerUserName"))
|
||||
{
|
||||
change = new ChangeKey(key, "followerPersonId");
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.activities;
|
||||
|
||||
public class SubscriptionsActivitySummaryProcessor extends BaseActivitySummaryProcessor
|
||||
{
|
||||
//{"lastName":"Glover","userFirstName":"David","followerLastName":"Glover","userUserName":"david.bowie@alfresco.com","followerFirstName":"Steve",
|
||||
// "userLastName":"Bowie","followerUserName":"steven.glover@alfresco.com","firstName":"Steve","tenantDomain":"alfresco.com"}
|
||||
|
||||
@Override
|
||||
protected Change processEntry(String key, Object value)
|
||||
{
|
||||
Change change = super.processEntry(key, value);
|
||||
|
||||
if(key.equals("userUserName"))
|
||||
{
|
||||
change = new ChangeKey(key, "userPersonId");
|
||||
}
|
||||
|
||||
if(key.equals("followerUserName"))
|
||||
{
|
||||
change = new ChangeKey(key, "followerPersonId");
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,210 +1,210 @@
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.rest.api.model.DocumentRatingSummary;
|
||||
import org.alfresco.rest.api.model.NodeRating;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.rating.Rating;
|
||||
import org.alfresco.service.cmr.rating.RatingService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Manages the mapping between the rest api's representation of a node rating and the repository's
|
||||
* representation of a node rating.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractRatingScheme implements RatingScheme, InitializingBean
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(RatingScheme.class);
|
||||
|
||||
protected String ratingSchemeName; // for interaction with the RatingService
|
||||
protected String ratingSchemeId; // exposed through the api
|
||||
protected RatingService ratingService;
|
||||
protected NodeService nodeService;
|
||||
protected DictionaryService dictionaryService;
|
||||
protected ActivityService activityService;
|
||||
protected SiteService siteService;
|
||||
|
||||
protected NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry;
|
||||
|
||||
public AbstractRatingScheme(String ratingSchemeId, String ratingSchemeName)
|
||||
{
|
||||
super();
|
||||
this.ratingSchemeName = ratingSchemeName;
|
||||
this.ratingSchemeId = ratingSchemeId;
|
||||
}
|
||||
|
||||
public String getRatingSchemeId()
|
||||
{
|
||||
return ratingSchemeId;
|
||||
}
|
||||
|
||||
public String getRatingServiceName()
|
||||
{
|
||||
return ratingSchemeName;
|
||||
}
|
||||
|
||||
public void setNodeRatingSchemeRegistry(NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry)
|
||||
{
|
||||
this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry;
|
||||
}
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setRatingService(RatingService ratingService)
|
||||
{
|
||||
this.ratingService = ratingService;
|
||||
}
|
||||
|
||||
protected org.alfresco.service.cmr.rating.RatingScheme getRepoRatingScheme()
|
||||
{
|
||||
return ratingService.getRatingScheme(ratingSchemeName);
|
||||
}
|
||||
|
||||
protected abstract DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef);
|
||||
protected abstract Object getApiRating(Float rating);
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
nodeRatingSchemeRegistry.register(ratingSchemeId, this);
|
||||
nodeRatingSchemeRegistry.register(ratingSchemeName, this);
|
||||
}
|
||||
|
||||
public void validateRating(Float rating)
|
||||
{
|
||||
org.alfresco.service.cmr.rating.RatingScheme ratingScheme = getRepoRatingScheme();
|
||||
Float minRating = ratingScheme.getMinRating();
|
||||
Float maxRating = ratingScheme.getMaxRating();
|
||||
if(rating < minRating || rating > maxRating)
|
||||
{
|
||||
throw new InvalidArgumentException("Rating is out of bounds.");
|
||||
}
|
||||
}
|
||||
|
||||
public NodeRating getNodeRating(NodeRef nodeRef)
|
||||
{
|
||||
Rating ratingByCurrentUser = ratingService.getRatingByCurrentUser(nodeRef, ratingSchemeName);
|
||||
Float rating = null;
|
||||
Date appliedAt = null;
|
||||
|
||||
if(ratingByCurrentUser != null)
|
||||
{
|
||||
rating = ratingByCurrentUser.getScore();
|
||||
appliedAt = ratingByCurrentUser.getAppliedAt();
|
||||
}
|
||||
|
||||
Object myRating = null;
|
||||
if(rating != null)
|
||||
{
|
||||
validateRating(rating);
|
||||
myRating = getApiRating(rating);
|
||||
}
|
||||
|
||||
DocumentRatingSummary documentRatingSummary = getDocumentRatingSummary(nodeRef);
|
||||
|
||||
NodeRating nodeRating = new NodeRating(ratingSchemeId, myRating, appliedAt, documentRatingSummary);
|
||||
return nodeRating;
|
||||
}
|
||||
|
||||
private String getSiteId(final NodeRef nodeRef)
|
||||
{
|
||||
// may not be able to read site data so run as system
|
||||
String siteId = AuthenticationUtil.runAsSystem(new RunAsWork<String>()
|
||||
{
|
||||
@Override
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
String siteId = null;
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
if(siteInfo != null)
|
||||
{
|
||||
siteId = siteInfo.getShortName();
|
||||
}
|
||||
return siteId;
|
||||
}
|
||||
});
|
||||
|
||||
return siteId;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private JSONObject getActivityData(final NodeRef nodeRef, String siteId)
|
||||
{
|
||||
JSONObject activityData = null;
|
||||
|
||||
if(siteId != null)
|
||||
{
|
||||
// may not be able to read these nodes, but we need to for the activity processing so run as system
|
||||
activityData = AuthenticationUtil.runAsSystem(new RunAsWork<JSONObject>()
|
||||
{
|
||||
@Override
|
||||
public JSONObject doWork() throws Exception
|
||||
{
|
||||
JSONObject activityData = new JSONObject();
|
||||
activityData.put("title", nodeService.getProperty(nodeRef, ContentModel.PROP_NAME));
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("document-details?nodeRef=");
|
||||
sb.append(URLEncoder.encode(nodeRef.toString(), "UTF-8"));
|
||||
activityData.put("page", sb.toString());
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
logger.warn("Unable to urlencode page for create nodeRating activity");
|
||||
}
|
||||
|
||||
return activityData;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return activityData;
|
||||
}
|
||||
|
||||
protected void postActivity(final NodeRef nodeRef, final String activityType)
|
||||
{
|
||||
String siteId = getSiteId(nodeRef);
|
||||
JSONObject activityData = getActivityData(nodeRef, siteId);
|
||||
if(activityData != null)
|
||||
{
|
||||
activityService.postActivity(activityType, siteId, "nodeRatings", activityData.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.rest.api.model.DocumentRatingSummary;
|
||||
import org.alfresco.rest.api.model.NodeRating;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.rating.Rating;
|
||||
import org.alfresco.service.cmr.rating.RatingService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Manages the mapping between the rest api's representation of a node rating and the repository's
|
||||
* representation of a node rating.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractRatingScheme implements RatingScheme, InitializingBean
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(RatingScheme.class);
|
||||
|
||||
protected String ratingSchemeName; // for interaction with the RatingService
|
||||
protected String ratingSchemeId; // exposed through the api
|
||||
protected RatingService ratingService;
|
||||
protected NodeService nodeService;
|
||||
protected DictionaryService dictionaryService;
|
||||
protected ActivityService activityService;
|
||||
protected SiteService siteService;
|
||||
|
||||
protected NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry;
|
||||
|
||||
public AbstractRatingScheme(String ratingSchemeId, String ratingSchemeName)
|
||||
{
|
||||
super();
|
||||
this.ratingSchemeName = ratingSchemeName;
|
||||
this.ratingSchemeId = ratingSchemeId;
|
||||
}
|
||||
|
||||
public String getRatingSchemeId()
|
||||
{
|
||||
return ratingSchemeId;
|
||||
}
|
||||
|
||||
public String getRatingServiceName()
|
||||
{
|
||||
return ratingSchemeName;
|
||||
}
|
||||
|
||||
public void setNodeRatingSchemeRegistry(NamedObjectRegistry<RatingScheme> nodeRatingSchemeRegistry)
|
||||
{
|
||||
this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry;
|
||||
}
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setRatingService(RatingService ratingService)
|
||||
{
|
||||
this.ratingService = ratingService;
|
||||
}
|
||||
|
||||
protected org.alfresco.service.cmr.rating.RatingScheme getRepoRatingScheme()
|
||||
{
|
||||
return ratingService.getRatingScheme(ratingSchemeName);
|
||||
}
|
||||
|
||||
protected abstract DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef);
|
||||
protected abstract Object getApiRating(Float rating);
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
nodeRatingSchemeRegistry.register(ratingSchemeId, this);
|
||||
nodeRatingSchemeRegistry.register(ratingSchemeName, this);
|
||||
}
|
||||
|
||||
public void validateRating(Float rating)
|
||||
{
|
||||
org.alfresco.service.cmr.rating.RatingScheme ratingScheme = getRepoRatingScheme();
|
||||
Float minRating = ratingScheme.getMinRating();
|
||||
Float maxRating = ratingScheme.getMaxRating();
|
||||
if(rating < minRating || rating > maxRating)
|
||||
{
|
||||
throw new InvalidArgumentException("Rating is out of bounds.");
|
||||
}
|
||||
}
|
||||
|
||||
public NodeRating getNodeRating(NodeRef nodeRef)
|
||||
{
|
||||
Rating ratingByCurrentUser = ratingService.getRatingByCurrentUser(nodeRef, ratingSchemeName);
|
||||
Float rating = null;
|
||||
Date appliedAt = null;
|
||||
|
||||
if(ratingByCurrentUser != null)
|
||||
{
|
||||
rating = ratingByCurrentUser.getScore();
|
||||
appliedAt = ratingByCurrentUser.getAppliedAt();
|
||||
}
|
||||
|
||||
Object myRating = null;
|
||||
if(rating != null)
|
||||
{
|
||||
validateRating(rating);
|
||||
myRating = getApiRating(rating);
|
||||
}
|
||||
|
||||
DocumentRatingSummary documentRatingSummary = getDocumentRatingSummary(nodeRef);
|
||||
|
||||
NodeRating nodeRating = new NodeRating(ratingSchemeId, myRating, appliedAt, documentRatingSummary);
|
||||
return nodeRating;
|
||||
}
|
||||
|
||||
private String getSiteId(final NodeRef nodeRef)
|
||||
{
|
||||
// may not be able to read site data so run as system
|
||||
String siteId = AuthenticationUtil.runAsSystem(new RunAsWork<String>()
|
||||
{
|
||||
@Override
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
String siteId = null;
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
if(siteInfo != null)
|
||||
{
|
||||
siteId = siteInfo.getShortName();
|
||||
}
|
||||
return siteId;
|
||||
}
|
||||
});
|
||||
|
||||
return siteId;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private JSONObject getActivityData(final NodeRef nodeRef, String siteId)
|
||||
{
|
||||
JSONObject activityData = null;
|
||||
|
||||
if(siteId != null)
|
||||
{
|
||||
// may not be able to read these nodes, but we need to for the activity processing so run as system
|
||||
activityData = AuthenticationUtil.runAsSystem(new RunAsWork<JSONObject>()
|
||||
{
|
||||
@Override
|
||||
public JSONObject doWork() throws Exception
|
||||
{
|
||||
JSONObject activityData = new JSONObject();
|
||||
activityData.put("title", nodeService.getProperty(nodeRef, ContentModel.PROP_NAME));
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("document-details?nodeRef=");
|
||||
sb.append(URLEncoder.encode(nodeRef.toString(), "UTF-8"));
|
||||
activityData.put("page", sb.toString());
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
logger.warn("Unable to urlencode page for create nodeRating activity");
|
||||
}
|
||||
|
||||
return activityData;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return activityData;
|
||||
}
|
||||
|
||||
protected void postActivity(final NodeRef nodeRef, final String activityType)
|
||||
{
|
||||
String siteId = getSiteId(nodeRef);
|
||||
JSONObject activityData = getActivityData(nodeRef, siteId);
|
||||
if(activityData != null)
|
||||
{
|
||||
activityService.postActivity(activityType, siteId, "nodeRatings", activityData.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,79 +1,79 @@
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import org.alfresco.rest.api.model.DocumentRatingSummary;
|
||||
import org.alfresco.rest.api.model.FiveStarRatingSummary;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.rating.RatingServiceException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* The rest apis representation of the 'fiveStar' rating scheme.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class FiveStarRatingScheme extends AbstractRatingScheme
|
||||
{
|
||||
public FiveStarRatingScheme()
|
||||
{
|
||||
super("fiveStar", "fiveStarRatingScheme");
|
||||
}
|
||||
|
||||
public Float getRatingServiceRating(Object rating)
|
||||
{
|
||||
Float ratingToApply = null;
|
||||
|
||||
if(rating instanceof Integer)
|
||||
{
|
||||
ratingToApply = ((Integer)rating).floatValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Rating should be non-null and an integer for 'fiveStar' rating scheme.");
|
||||
}
|
||||
|
||||
validateRating(ratingToApply);
|
||||
|
||||
return ratingToApply;
|
||||
}
|
||||
|
||||
public Object getApiRating(Float rating)
|
||||
{
|
||||
Object apiRating = Integer.valueOf(rating.intValue());
|
||||
return apiRating;
|
||||
}
|
||||
|
||||
public DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef)
|
||||
{
|
||||
return new FiveStarRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName),
|
||||
ratingService.getTotalRating(nodeRef, ratingSchemeName),
|
||||
ratingService.getAverageRating(nodeRef, ratingSchemeName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRating(NodeRef nodeRef, Object rating)
|
||||
{
|
||||
try
|
||||
{
|
||||
Float ratingServiceRating = getRatingServiceRating(rating);
|
||||
ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName());
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRating(NodeRef nodeRef)
|
||||
{
|
||||
try
|
||||
{
|
||||
ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName());
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import org.alfresco.rest.api.model.DocumentRatingSummary;
|
||||
import org.alfresco.rest.api.model.FiveStarRatingSummary;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.rating.RatingServiceException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* The rest apis representation of the 'fiveStar' rating scheme.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class FiveStarRatingScheme extends AbstractRatingScheme
|
||||
{
|
||||
public FiveStarRatingScheme()
|
||||
{
|
||||
super("fiveStar", "fiveStarRatingScheme");
|
||||
}
|
||||
|
||||
public Float getRatingServiceRating(Object rating)
|
||||
{
|
||||
Float ratingToApply = null;
|
||||
|
||||
if(rating instanceof Integer)
|
||||
{
|
||||
ratingToApply = ((Integer)rating).floatValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Rating should be non-null and an integer for 'fiveStar' rating scheme.");
|
||||
}
|
||||
|
||||
validateRating(ratingToApply);
|
||||
|
||||
return ratingToApply;
|
||||
}
|
||||
|
||||
public Object getApiRating(Float rating)
|
||||
{
|
||||
Object apiRating = Integer.valueOf(rating.intValue());
|
||||
return apiRating;
|
||||
}
|
||||
|
||||
public DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef)
|
||||
{
|
||||
return new FiveStarRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName),
|
||||
ratingService.getTotalRating(nodeRef, ratingSchemeName),
|
||||
ratingService.getAverageRating(nodeRef, ratingSchemeName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRating(NodeRef nodeRef, Object rating)
|
||||
{
|
||||
try
|
||||
{
|
||||
Float ratingServiceRating = getRatingServiceRating(rating);
|
||||
ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName());
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRating(NodeRef nodeRef)
|
||||
{
|
||||
try
|
||||
{
|
||||
ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName());
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,100 +1,100 @@
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.activities.ActivityType;
|
||||
import org.alfresco.rest.api.model.DocumentRatingSummary;
|
||||
import org.alfresco.rest.api.model.LikesRatingSummary;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.rating.RatingServiceException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* The rest api representation of the 'likes' rating scheme.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class LikesRatingScheme extends AbstractRatingScheme
|
||||
{
|
||||
public LikesRatingScheme()
|
||||
{
|
||||
super("likes", "likesRatingScheme");
|
||||
}
|
||||
|
||||
public Float getRatingServiceRating(Object rating)
|
||||
{
|
||||
Float ratingToApply = null;
|
||||
|
||||
if(rating instanceof Boolean)
|
||||
{
|
||||
boolean liked = ((Boolean)rating).booleanValue();
|
||||
ratingToApply = Float.valueOf((liked ? 1.0f : 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Rating should be non-null and a boolean for 'likes' rating scheme.");
|
||||
}
|
||||
|
||||
return ratingToApply;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRating(NodeRef nodeRef, Object rating)
|
||||
{
|
||||
try
|
||||
{
|
||||
Float ratingServiceRating = getRatingServiceRating(rating);
|
||||
ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName());
|
||||
|
||||
QName nodeType = nodeService.getType(nodeRef);
|
||||
boolean isContainer = dictionaryService.isSubClass(nodeType, ContentModel.TYPE_FOLDER) &&
|
||||
!dictionaryService.isSubClass(nodeType, ContentModel.TYPE_SYSTEM_FOLDER);
|
||||
postActivity(nodeRef, isContainer ? ActivityType.FOLDER_LIKED : ActivityType.FILE_LIKED);
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRating(NodeRef nodeRef)
|
||||
{
|
||||
try
|
||||
{
|
||||
ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName());
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getApiRating(Float rating)
|
||||
{
|
||||
Object apiRating = null;
|
||||
if(rating == 1.0f)
|
||||
{
|
||||
apiRating = true;
|
||||
}
|
||||
else if(rating == 0.0f)
|
||||
{
|
||||
apiRating = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Rating is invalid.");
|
||||
}
|
||||
|
||||
return apiRating;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef)
|
||||
{
|
||||
return new LikesRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName));
|
||||
}
|
||||
|
||||
}
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.activities.ActivityType;
|
||||
import org.alfresco.rest.api.model.DocumentRatingSummary;
|
||||
import org.alfresco.rest.api.model.LikesRatingSummary;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.cmr.rating.RatingServiceException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* The rest api representation of the 'likes' rating scheme.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class LikesRatingScheme extends AbstractRatingScheme
|
||||
{
|
||||
public LikesRatingScheme()
|
||||
{
|
||||
super("likes", "likesRatingScheme");
|
||||
}
|
||||
|
||||
public Float getRatingServiceRating(Object rating)
|
||||
{
|
||||
Float ratingToApply = null;
|
||||
|
||||
if(rating instanceof Boolean)
|
||||
{
|
||||
boolean liked = ((Boolean)rating).booleanValue();
|
||||
ratingToApply = Float.valueOf((liked ? 1.0f : 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Rating should be non-null and a boolean for 'likes' rating scheme.");
|
||||
}
|
||||
|
||||
return ratingToApply;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRating(NodeRef nodeRef, Object rating)
|
||||
{
|
||||
try
|
||||
{
|
||||
Float ratingServiceRating = getRatingServiceRating(rating);
|
||||
ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName());
|
||||
|
||||
QName nodeType = nodeService.getType(nodeRef);
|
||||
boolean isContainer = dictionaryService.isSubClass(nodeType, ContentModel.TYPE_FOLDER) &&
|
||||
!dictionaryService.isSubClass(nodeType, ContentModel.TYPE_SYSTEM_FOLDER);
|
||||
postActivity(nodeRef, isContainer ? ActivityType.FOLDER_LIKED : ActivityType.FILE_LIKED);
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRating(NodeRef nodeRef)
|
||||
{
|
||||
try
|
||||
{
|
||||
ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName());
|
||||
}
|
||||
catch(RatingServiceException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getApiRating(Float rating)
|
||||
{
|
||||
Object apiRating = null;
|
||||
if(rating == 1.0f)
|
||||
{
|
||||
apiRating = true;
|
||||
}
|
||||
else if(rating == 0.0f)
|
||||
{
|
||||
apiRating = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Rating is invalid.");
|
||||
}
|
||||
|
||||
return apiRating;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef)
|
||||
{
|
||||
return new LikesRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,11 +1,11 @@
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import org.alfresco.rest.api.model.NodeRating;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
public interface RatingScheme
|
||||
{
|
||||
public void applyRating(NodeRef nodeRef, Object rating);
|
||||
public void removeRating(NodeRef nodeRef);
|
||||
public NodeRating getNodeRating(NodeRef nodeRef);
|
||||
}
|
||||
package org.alfresco.rest.api.impl.node.ratings;
|
||||
|
||||
import org.alfresco.rest.api.model.NodeRating;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
public interface RatingScheme
|
||||
{
|
||||
public void applyRating(NodeRef nodeRef, Object rating);
|
||||
public void removeRating(NodeRef nodeRef);
|
||||
public NodeRating getNodeRating(NodeRef nodeRef);
|
||||
}
|
||||
|
Reference in New Issue
Block a user