From 8d24f35395bfeccd24c5fc7114ee9adc414b365d Mon Sep 17 00:00:00 2001 From: Ancuta Morarasu Date: Wed, 11 May 2016 10:47:59 +0000 Subject: [PATCH] Merged HEAD (5.2) to 5.2.N (5.2.1) 126360 jkaabimofrad: Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2) 119711 jvonka: FileFolder API - consistently handle node aspects &/or properties (on create or update) - also allow specialise node type (when updating a node) - minor tweaks to javadoc/comments - RA-635, RA-636, RA-639 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@126706 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/rest/api/impl/NodesImpl.java | 82 ++++++++++++++----- .../rest/api/nodes/NodeChildrenRelation.java | 21 +++-- 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index 00086d1a5a..8492aaf24d 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -549,8 +549,8 @@ public class NodesImpl implements Nodes if (! minimalInfo) { - node.setProperties(mapProperties(properties, selectParam, mapUserInfo)); - node.setAspectNames(mapAspects(nodeService.getAspects(nodeRef))); + node.setProperties(mapFromNodeProperties(properties, selectParam, mapUserInfo)); + node.setAspectNames(mapFromNodeAspects(nodeService.getAspects(nodeRef))); } node.setNodeType(typeQName.toPrefixString(namespaceService)); @@ -661,7 +661,20 @@ public class NodesImpl implements Nodes return new PathInfo(pathStr, isComplete, pathElements); } - protected Map mapProperties(Map nodeProps, List selectParam, Map mapUserInfo) + protected Map mapToNodeProperties(Map props) + { + Map nodeProps = new HashMap<>(props.size()); + + for (Entry entry : props.entrySet()) + { + QName propQName = QName.createQName(entry.getKey(), namespaceService); + nodeProps.put(propQName, (Serializable)entry.getValue()); + } + + return nodeProps; + } + + protected Map mapFromNodeProperties(Map nodeProps, List selectParam, Map mapUserInfo) { List selectedProperties; @@ -708,7 +721,7 @@ public class NodesImpl implements Nodes return props; } - protected List mapAspects(Set nodeAspects) + protected List mapFromNodeAspects(Set nodeAspects) { List aspectNames = new ArrayList<>(nodeAspects.size()); @@ -833,19 +846,20 @@ public class NodesImpl implements Nodes throw new InvalidArgumentException("NodeId of folder is expected: "+parentNodeRef); } + // node name - mandatory String nodeName = nodeInfo.getName(); if ((nodeName == null) || nodeName.isEmpty()) { throw new InvalidArgumentException("Node name is expected: "+parentNodeRef); } + // node type - check that requested type is a (sub-) type of folder or content String nodeType = nodeInfo.getNodeType(); if ((nodeType == null) || nodeType.isEmpty()) { throw new InvalidArgumentException("Node type is expected: "+parentNodeRef+","+nodeName); } - // check that requested type is a (sub-) type of folder or content QName nodeTypeQName = createQName(nodeType); Set contentAndFolders = new HashSet<>(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT)); @@ -855,15 +869,12 @@ public class NodesImpl implements Nodes boolean isContent = typeMatches(nodeTypeQName, Collections.singleton(ContentModel.TYPE_CONTENT), null); - Map props = new HashMap<>(10); + Map props = new HashMap<>(1); if (nodeInfo.getProperties() != null) { - for (Entry entry : nodeInfo.getProperties().entrySet()) - { - QName propQName = QName.createQName(entry.getKey(), namespaceService); - props.put(propQName, (Serializable)entry.getValue()); - } + // node properties - set any additional properties + props = mapToNodeProperties(nodeInfo.getProperties()); } props.put(ContentModel.PROP_NAME, nodeName); @@ -871,6 +882,22 @@ public class NodesImpl implements Nodes QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName)); NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, nodeTypeQName, props).getChildRef(); + List aspectNames = nodeInfo.getAspectNames(); + if (aspectNames != null) + { + // node aspects - set any additional aspects + for (String aspectName : aspectNames) + { + QName aspectQName = QName.createQName(aspectName, namespaceService); + if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE)) + { + continue; // ignore + } + + nodeService.addAspect(nodeRef, aspectQName, null); + } + } + if (isContent) { // add empty file ContentWriter writer = sr.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true); @@ -886,34 +913,48 @@ public class NodesImpl implements Nodes { final NodeRef nodeRef = validateNode(nodeId); + QName nodeTypeQName = nodeService.getType(nodeRef); + final Set fileOrFolder = new HashSet<>(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT)); - if (! nodeMatches(nodeRef, fileOrFolder, null)) + if (! typeMatches(nodeTypeQName, fileOrFolder, null)) { throw new InvalidArgumentException("NodeId of file or folder is expected"); } - Map props = new HashMap<>(10); + Map props = new HashMap<>(0); if (nodeInfo.getProperties() != null) { - for (Entry entry : nodeInfo.getProperties().entrySet()) - { - QName propQName = QName.createQName(entry.getKey(), namespaceService); - props.put(propQName, (Serializable)entry.getValue()); - } + props = mapToNodeProperties(nodeInfo.getProperties()); } String name = nodeInfo.getName(); if ((name != null) && (! name.isEmpty())) { - // note: this is equivalent of a rename within target folder + // update node name if needed - note: if the name is different than existing then this is equivalent of a rename (within parent folder) props.put(ContentModel.PROP_NAME, name); } + String nodeType = nodeInfo.getNodeType(); + if ((nodeType != null) && (! nodeType.isEmpty())) + { + // update node type - ensure that we are performing a specialise (we do not support generalise) + QName destNodeTypeQName = QName.createQName(nodeType, namespaceService); + + if ((! destNodeTypeQName.equals(nodeTypeQName)) && dictionaryService.isSubClass(destNodeTypeQName, nodeTypeQName)) + { + nodeService.setType(nodeRef, destNodeTypeQName); + } + else + { + throw new IllegalArgumentException("Cannot generalise the node type (from "+nodeTypeQName+" to "+destNodeTypeQName+")"); + } + } + List aspectNames = nodeInfo.getAspectNames(); if (aspectNames != null) { - // note: can be empty (eg. to remove existing aspects (+ aspect properties) ... apart from cm:auditable, sys:referencable, sys:localized) + // update aspects - note: can be empty (eg. to remove existing aspects+properties) but not cm:auditable, sys:referencable, sys:localized Set aspectQNames = new HashSet<>(aspectNames.size()); for (String aspectName : aspectNames) { @@ -967,6 +1008,7 @@ public class NodesImpl implements Nodes if (props.size() > 0) { + // update node properties - note: null will unset the specified property nodeService.addProperties(nodeRef, props); } diff --git a/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java b/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java index 07e2a9834d..99d997d475 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java +++ b/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java @@ -35,7 +35,11 @@ import java.util.ArrayList; import java.util.List; /** - * TODO ... work-in-progress + * Node Children + * + * - list folder children + * - create folder &/or empty file + * - create (ie. upload) file with content * * @author janv * @author Jamal Kaabi-Mofrad @@ -59,17 +63,12 @@ public class NodeChildrenRelation implements RelationshipResourceAction.Read