Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2)

121557 jvonka: FileFolder API - experimental support for multi move/copy via post to target folder
   - please note: API (including uri endpoint) is subject to change
   RA-683, RA-684


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@126410 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jamal Kaabi-Mofrad
2016-05-10 10:49:33 +00:00
parent 08bb18b229
commit 82f984e791
4 changed files with 137 additions and 37 deletions

View File

@@ -100,7 +100,7 @@ public interface Nodes
void deleteNode(String nodeId); void deleteNode(String nodeId);
/** /**
* Create node(s) - folder or (empty) file. * Create node - folder or (empty) file.
* *
* @param parentFolderNodeId * @param parentFolderNodeId
* @param nodeInfo * @param nodeInfo
@@ -109,6 +109,28 @@ public interface Nodes
*/ */
Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters); Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters);
/**
* Move node
*
* @param sourceNodeId
* @param parentFolderNodeId
* @param name
* @param parameters
* @return
*/
Node moveNode(String sourceNodeId, String parentFolderNodeId, String name, Parameters parameters);
/**
* Copy node
*
* @param sourceNodeId
* @param parentFolderNodeId
* @param name
* @param parameters
* @return
*/
Node copyNode(String sourceNodeId, String parentFolderNodeId, String name, Parameters parameters);
/** /**
* Update node meta-data. * Update node meta-data.
* *

View File

@@ -1083,9 +1083,19 @@ public class NodesImpl implements Nodes
NodeRef parentNodeRef = nodeInfo.getParentId(); NodeRef parentNodeRef = nodeInfo.getParentId();
if (parentNodeRef != null) if (parentNodeRef != null)
{
NodeRef currentParentNodeRef = getParentNodeRef(nodeRef);
if (currentParentNodeRef == null)
{
// implies root (Company Home) hence return 403 here
throw new PermissionDeniedException();
}
if (! currentParentNodeRef.equals(parentNodeRef))
{ {
// move/rename - with exception mapping // move/rename - with exception mapping
move(nodeRef, parentNodeRef, name); moveOrCopy(nodeRef, parentNodeRef, name, false);
}
} }
List<String> aspectNames = nodeInfo.getAspectNames(); List<String> aspectNames = nodeInfo.getAspectNames();
@@ -1171,23 +1181,39 @@ public class NodesImpl implements Nodes
return getFolderOrDocument(nodeRef.getId(), parameters); return getFolderOrDocument(nodeRef.getId(), parameters);
} }
private void move(NodeRef nodeRef, NodeRef parentNodeRef, String name) public Node moveNode(String sourceNodeId, String parentFolderNodeId, String name, Parameters parameters)
{ {
NodeRef currentParentNodeRef = getParentNodeRef(nodeRef); final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
if (currentParentNodeRef == null) final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null);
{
// implies root (Company Home) hence return 403 here FileInfo fi = moveOrCopy(sourceNodeRef, parentNodeRef, name, false);
throw new PermissionDeniedException(); return getFolderOrDocument(fi.getNodeRef().getId(), parameters);
} }
if (! currentParentNodeRef.equals(parentNodeRef)) public Node copyNode(String sourceNodeId, String parentFolderNodeId, String name, Parameters parameters)
{
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null);
FileInfo fi = moveOrCopy(sourceNodeRef, parentNodeRef, name, true);
return getFolderOrDocument(fi.getNodeRef().getId(), parameters);
}
protected FileInfo moveOrCopy(NodeRef nodeRef, NodeRef parentNodeRef, String name, boolean isCopy)
{ {
try try
{
if (isCopy)
{
return fileFolderService.copy(nodeRef, parentNodeRef, name);
}
else
{ {
// updating "parentId" means moving primary parent ! // updating "parentId" means moving primary parent !
// note: in the future (as and when we support secondary parent/child assocs) we may also // note: in the future (as and when we support secondary parent/child assocs) we may also
// wish to select which parent to "move from" (in case where the node resides in multiple locations) // wish to select which parent to "move from" (in case where the node resides in multiple locations)
fileFolderService.move(nodeRef, parentNodeRef, name); return fileFolderService.move(nodeRef, parentNodeRef, name);
}
} }
catch (InvalidNodeRefException inre) catch (InvalidNodeRefException inre)
{ {
@@ -1209,8 +1235,7 @@ public class NodesImpl implements Nodes
} }
catch (CyclicChildRelationshipException ccre) catch (CyclicChildRelationshipException ccre)
{ {
throw new InvalidArgumentException(ccre.getMessage()+" ["+nodeRef+","+parentNodeRef+"]"); throw new InvalidArgumentException(ccre.getMessage() + " [" + nodeRef + "," + parentNodeRef + "]");
}
} }
} }

View File

@@ -27,7 +27,6 @@ import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.rest.framework.resource.UniqueId; import org.alfresco.rest.framework.resource.UniqueId;
import org.alfresco.rest.framework.resource.content.*;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.NoSuchPersonException;
@@ -61,7 +60,6 @@ public class Node implements Comparable<Node>
protected String prefixTypeQName; protected String prefixTypeQName;
protected List<String> aspectNames; protected List<String> aspectNames;
protected Map<String, Object> properties; protected Map<String, Object> properties;
public Node(NodeRef nodeRef, NodeRef parentNodeRef, Map<QName, Serializable> nodeProps, Map<String, UserInfo> mapUserInfo, ServiceRegistry sr) public Node(NodeRef nodeRef, NodeRef parentNodeRef, Map<QName, Serializable> nodeProps, Map<String, UserInfo> mapUserInfo, ServiceRegistry sr)
@@ -136,6 +134,8 @@ public class Node implements Comparable<Node>
return userInfo; return userInfo;
} }
// note: nodeRef maps to json "id" (when serializing/deserializng)
@UniqueId @UniqueId
public NodeRef getNodeRef() public NodeRef getNodeRef()
{ {
@@ -278,6 +278,7 @@ public class Node implements Comparable<Node>
} }
// here to allow POST /nodes/{id}/children when creating empty file with specified content.mimeType // here to allow POST /nodes/{id}/children when creating empty file with specified content.mimeType
protected ContentInfo contentInfo; protected ContentInfo contentInfo;
public void setContent(ContentInfo contentInfo) public void setContent(ContentInfo contentInfo)
@@ -290,6 +291,21 @@ public class Node implements Comparable<Node>
return this.contentInfo; return this.contentInfo;
} }
// TODO experimental (API subject to change) - special property (request-only) to allow move/copy via POST /nodes/{id}/children
protected String action;
public String getAction()
{
return action;
}
public void setAction(String action)
{
this.action = action;
}
// TODO for backwards compat' - set explicitly when needed (ie. favourites) (note: we could choose to have separate old Node/NodeImpl etc) // TODO for backwards compat' - set explicitly when needed (ie. favourites) (note: we could choose to have separate old Node/NodeImpl etc)
protected String title; protected String title;
@@ -376,4 +392,5 @@ public class Node implements Comparable<Node>
{ {
this.modifiedBy = modifiedBy; this.modifiedBy = modifiedBy;
} }
} }

View File

@@ -25,6 +25,7 @@ import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.Node; import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.framework.WebApiDescription; import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam; import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.RelationshipResource; import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.MultiPartRelationshipResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.MultiPartRelationshipResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
@@ -100,10 +101,45 @@ public class NodeChildrenRelation implements RelationshipResourceAction.Read<Nod
{ {
List<Node> result = new ArrayList<>(nodeInfos.size()); List<Node> result = new ArrayList<>(nodeInfos.size());
// TODO experimental (API subject to change) - eg. this may move to a separate endpoint !
for (Node nodeInfo : nodeInfos)
{
String action = nodeInfo.getAction();
if (action != null)
{
String sourceNodeId = nodeInfo.getNodeRef().getId();
String optionalName = nodeInfo.getName();
if (action.equalsIgnoreCase("move"))
{
result.add(nodes.moveNode(sourceNodeId, parentFolderNodeId, optionalName, parameters));
}
else if (action.equalsIgnoreCase("copy"))
{
result.add(nodes.copyNode(sourceNodeId, parentFolderNodeId, optionalName, parameters));
}
else
{
throw new InvalidArgumentException("Unknown action: "+action);
}
}
else
{
if (nodeInfo.getNodeRef() != null)
{
throw new InvalidArgumentException("Unexpected id without action, eg. move/copy: "+nodeInfo.getNodeRef());
}
result.add(nodes.createNode(parentFolderNodeId, nodeInfo, parameters));
}
}
/*
for (Node nodeInfo : nodeInfos) for (Node nodeInfo : nodeInfos)
{ {
result.add(nodes.createNode(parentFolderNodeId, nodeInfo, parameters)); result.add(nodes.createNode(parentFolderNodeId, nodeInfo, parameters));
} }
*/
return result; return result;
} }