diff --git a/source/java/org/alfresco/rest/api/Nodes.java b/source/java/org/alfresco/rest/api/Nodes.java index 545259cbf2..5a448cd83a 100644 --- a/source/java/org/alfresco/rest/api/Nodes.java +++ b/source/java/org/alfresco/rest/api/Nodes.java @@ -97,7 +97,7 @@ public interface Nodes * - incFiles, incFolders (both true by default) * @return a paged list of {@code org.alfresco.rest.api.model.Node} objects */ - CollectionWithPagingInfo getChildren(String parentFolderNodeId, Parameters parameters); + CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters); /** * Delete the given node. Note: will cascade delete for a folder. diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index 3479d6de02..f3913a9e97 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -25,6 +25,20 @@ */ package org.alfresco.rest.api.impl; +import java.io.InputStream; +import java.io.Serializable; +import java.math.BigInteger; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.query.PagingRequest; @@ -62,6 +76,7 @@ import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionDefinition; import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; @@ -93,20 +108,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.extensions.surf.util.Content; import org.springframework.extensions.webscripts.servlet.FormData; -import java.io.InputStream; -import java.io.Serializable; -import java.math.BigInteger; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - /** * Centralises access to file/folder/node services and maps between representations. * @@ -652,13 +653,13 @@ public class NodesImpl implements Nodes boolean isLink = typeMatches(nodeTypeQName, Collections.singleton(ContentModel.TYPE_LINK), null); node.setIsLink(isLink); } - + node.setNodeType(nodeTypeQName.toPrefixString(namespaceService)); node.setPath(pathInfo); return node; } - + protected PathInfo lookupPathInfo(NodeRef nodeRefIn) { final Path nodePath = nodeService.getPath(nodeRefIn); @@ -708,6 +709,28 @@ public class NodesImpl implements Nodes } return new PathInfo(pathStr, isComplete, pathElements); } + + protected Set mapToNodeAspects(List aspectNames) + { + Set nodeAspects = new HashSet<>(aspectNames.size()); + + for (String aspectName : aspectNames) + { + QName aspectQName = createQName(aspectName); + + AspectDefinition ad = dictionaryService.getAspect(aspectQName); + if (ad != null) + { + nodeAspects.add(aspectQName); + } + else + { + throw new InvalidArgumentException("Unknown aspect: "+aspectName); + } + } + + return nodeAspects; + } protected Map mapToNodeProperties(Map props) { @@ -715,7 +738,8 @@ public class NodesImpl implements Nodes for (Entry entry : props.entrySet()) { - QName propQName = createQName(entry.getKey()); + String propName = entry.getKey(); + QName propQName = createQName(propName); PropertyDefinition pd = dictionaryService.getProperty(propQName); if (pd != null) @@ -739,6 +763,10 @@ public class NodesImpl implements Nodes } nodeProps.put(propQName, value); } + else + { + throw new InvalidArgumentException("Unknown property: "+propName); + } } return nodeProps; @@ -812,7 +840,7 @@ public class NodesImpl implements Nodes return aspectNames; } - public CollectionWithPagingInfo getChildren(String parentFolderNodeId, Parameters parameters) + public CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters) { final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); @@ -825,7 +853,7 @@ public class NodesImpl implements Nodes if (q != null) { - // TODO confirm list of filter props - what about custom props (+ across types/aspects) ? + // TODO confirm list of filter props - what about custom props (+ across types/aspects) ? What about VF extension ? MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES, null); QueryHelper.walk(q, propertyWalker); @@ -957,9 +985,9 @@ public class NodesImpl implements Nodes if (aspectNames != null) { // node aspects - set any additional aspects - for (String aspectName : aspectNames) + Set aspectQNames = mapToNodeAspects(aspectNames); + for (QName aspectQName : aspectQNames) { - QName aspectQName = createQName(aspectName); if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE)) { continue; // ignore @@ -1055,12 +1083,8 @@ public class NodesImpl implements Nodes if (aspectNames != null) { // 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) - { - QName aspectQName = createQName(aspectName); - aspectQNames.add(aspectQName); - } + + Set aspectQNames = mapToNodeAspects(aspectNames); Set existingAspects = nodeService.getAspects(nodeRef); diff --git a/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java b/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java index 99d997d475..6182d5e4ab 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java +++ b/source/java/org/alfresco/rest/api/nodes/NodeChildrenRelation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2015 Alfresco Software Limited. + * Copyright (C) 2005-2016 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,6 +18,9 @@ */ package org.alfresco.rest.api.nodes; +import java.util.ArrayList; +import java.util.List; + import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.model.Node; import org.alfresco.rest.framework.WebApiDescription; @@ -31,9 +34,6 @@ import org.alfresco.util.ParameterCheck; import org.springframework.beans.factory.InitializingBean; import org.springframework.extensions.webscripts.servlet.FormData; -import java.util.ArrayList; -import java.util.List; - /** * Node Children * @@ -83,7 +83,7 @@ public class NodeChildrenRelation implements RelationshipResourceAction.Read readAll(String parentFolderNodeId, Parameters parameters) { - return nodes.getChildren(parentFolderNodeId, parameters); + return nodes.listChildren(parentFolderNodeId, parameters); } /** diff --git a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java index 65f4282966..dbc4799ccd 100644 --- a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -196,7 +196,7 @@ public class NodeApiTest extends AbstractBaseApiTest repoService.addToDocumentLibrary(userOneN1Site, folder2, ContentModel.TYPE_FOLDER); String content1 = "content" + System.currentTimeMillis() + "_1"; - NodeRef contentNodeRef = repoService.addToDocumentLibrary(userOneN1Site, content1, ContentModel.TYPE_CONTENT); + repoService.addToDocumentLibrary(userOneN1Site, content1, ContentModel.TYPE_CONTENT); String content2 = "content" + System.currentTimeMillis() + "_2"; repoService.addToDocumentLibrary(userOneN1Site, content2, ContentModel.TYPE_CONTENT); @@ -1256,14 +1256,19 @@ public class NodeApiTest extends AbstractBaseApiTest f1.setNodeType("app:glossary"); f1.expected(folderResp); - // -ve test - ignore unknown property + // -ve test - fail on unknown property props = new HashMap<>(); props.put("cm:xyz","my unknown property"); dUpdate = new Document(); dUpdate.setProperties(props); - response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200); - documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); - d1.expected(documentResp); + put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 400); + + // -ve test - fail on unknown aspect + List aspects = new ArrayList<>(d1.getAspectNames()); + aspects.add("cm:unknownAspect"); + dUpdate = new Document(); + dUpdate.setAspectNames(aspects); + put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 400); // -ve test - duplicate name dUpdate = new Document();