mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2)
120807 jvonka: FileFolder API - create/update node will return 400 for unknown property or aspect (not in dictionary models) - we no longer ignore invalid property and now also return correct error code for invalid aspect - update NodeApiTest and A/C of JIRAs ( RA-635, RA-636, RA-637, RA-638 ) - note: in the future, we could consider option (eg. via query param) to allow residual props on create or update (or at least ability to nullify) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@126398 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -90,7 +90,7 @@ public interface Nodes
|
|||||||
* - incFiles, incFolders (both true by default)
|
* - incFiles, incFolders (both true by default)
|
||||||
* @return a paged list of {@code org.alfresco.rest.api.model.Node} objects
|
* @return a paged list of {@code org.alfresco.rest.api.model.Node} objects
|
||||||
*/
|
*/
|
||||||
CollectionWithPagingInfo<Node> getChildren(String parentFolderNodeId, Parameters parameters);
|
CollectionWithPagingInfo<Node> listChildren(String parentFolderNodeId, Parameters parameters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the given node. Note: will cascade delete for a folder.
|
* Delete the given node. Note: will cascade delete for a folder.
|
||||||
|
@@ -18,6 +18,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.api.impl;
|
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.ApplicationModel;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.query.PagingRequest;
|
import org.alfresco.query.PagingRequest;
|
||||||
@@ -55,6 +69,7 @@ import org.alfresco.service.ServiceRegistry;
|
|||||||
import org.alfresco.service.cmr.action.Action;
|
import org.alfresco.service.cmr.action.Action;
|
||||||
import org.alfresco.service.cmr.action.ActionDefinition;
|
import org.alfresco.service.cmr.action.ActionDefinition;
|
||||||
import org.alfresco.service.cmr.action.ActionService;
|
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.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
@@ -86,20 +101,6 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.springframework.extensions.surf.util.Content;
|
import org.springframework.extensions.surf.util.Content;
|
||||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
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.
|
* Centralises access to file/folder/node services and maps between representations.
|
||||||
*
|
*
|
||||||
@@ -702,13 +703,36 @@ public class NodesImpl implements Nodes
|
|||||||
return new PathInfo(pathStr, isComplete, pathElements);
|
return new PathInfo(pathStr, isComplete, pathElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Set<QName> mapToNodeAspects(List<String> aspectNames)
|
||||||
|
{
|
||||||
|
Set<QName> 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<QName, Serializable> mapToNodeProperties(Map<String, Object> props)
|
protected Map<QName, Serializable> mapToNodeProperties(Map<String, Object> props)
|
||||||
{
|
{
|
||||||
Map<QName, Serializable> nodeProps = new HashMap<>(props.size());
|
Map<QName, Serializable> nodeProps = new HashMap<>(props.size());
|
||||||
|
|
||||||
for (Entry<String, Object> entry : props.entrySet())
|
for (Entry<String, Object> entry : props.entrySet())
|
||||||
{
|
{
|
||||||
QName propQName = createQName(entry.getKey());
|
String propName = entry.getKey();
|
||||||
|
QName propQName = createQName(propName);
|
||||||
|
|
||||||
PropertyDefinition pd = dictionaryService.getProperty(propQName);
|
PropertyDefinition pd = dictionaryService.getProperty(propQName);
|
||||||
if (pd != null)
|
if (pd != null)
|
||||||
@@ -732,6 +756,10 @@ public class NodesImpl implements Nodes
|
|||||||
}
|
}
|
||||||
nodeProps.put(propQName, value);
|
nodeProps.put(propQName, value);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("Unknown property: "+propName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeProps;
|
return nodeProps;
|
||||||
@@ -805,7 +833,7 @@ public class NodesImpl implements Nodes
|
|||||||
return aspectNames;
|
return aspectNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CollectionWithPagingInfo<Node> getChildren(String parentFolderNodeId, Parameters parameters)
|
public CollectionWithPagingInfo<Node> listChildren(String parentFolderNodeId, Parameters parameters)
|
||||||
{
|
{
|
||||||
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
|
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
|
||||||
|
|
||||||
@@ -818,7 +846,7 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
if (q != null)
|
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);
|
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES, null);
|
||||||
QueryHelper.walk(q, propertyWalker);
|
QueryHelper.walk(q, propertyWalker);
|
||||||
|
|
||||||
@@ -950,9 +978,9 @@ public class NodesImpl implements Nodes
|
|||||||
if (aspectNames != null)
|
if (aspectNames != null)
|
||||||
{
|
{
|
||||||
// node aspects - set any additional aspects
|
// node aspects - set any additional aspects
|
||||||
for (String aspectName : aspectNames)
|
Set<QName> aspectQNames = mapToNodeAspects(aspectNames);
|
||||||
|
for (QName aspectQName : aspectQNames)
|
||||||
{
|
{
|
||||||
QName aspectQName = createQName(aspectName);
|
|
||||||
if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE))
|
if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE))
|
||||||
{
|
{
|
||||||
continue; // ignore
|
continue; // ignore
|
||||||
@@ -1048,12 +1076,8 @@ public class NodesImpl implements Nodes
|
|||||||
if (aspectNames != null)
|
if (aspectNames != null)
|
||||||
{
|
{
|
||||||
// update aspects - note: can be empty (eg. to remove existing aspects+properties) but not 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<QName> aspectQNames = new HashSet<>(aspectNames.size());
|
|
||||||
for (String aspectName : aspectNames)
|
Set<QName> aspectQNames = mapToNodeAspects(aspectNames);
|
||||||
{
|
|
||||||
QName aspectQName = createQName(aspectName);
|
|
||||||
aspectQNames.add(aspectQName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<QName> existingAspects = nodeService.getAspects(nodeRef);
|
Set<QName> existingAspects = nodeService.getAspects(nodeRef);
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -18,6 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.api.nodes;
|
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.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;
|
||||||
@@ -31,9 +34,6 @@ import org.alfresco.util.ParameterCheck;
|
|||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
import org.springframework.extensions.webscripts.servlet.FormData;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node Children
|
* Node Children
|
||||||
*
|
*
|
||||||
@@ -83,7 +83,7 @@ public class NodeChildrenRelation implements RelationshipResourceAction.Read<Nod
|
|||||||
@WebApiDescription(title = "Return a paged list of nodes for the document/folder identified by parentFolderNodeId")
|
@WebApiDescription(title = "Return a paged list of nodes for the document/folder identified by parentFolderNodeId")
|
||||||
public CollectionWithPagingInfo<Node> readAll(String parentFolderNodeId, Parameters parameters)
|
public CollectionWithPagingInfo<Node> readAll(String parentFolderNodeId, Parameters parameters)
|
||||||
{
|
{
|
||||||
return nodes.getChildren(parentFolderNodeId, parameters);
|
return nodes.listChildren(parentFolderNodeId, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -196,7 +196,7 @@ public class NodeApiTest extends AbstractBaseApiTest
|
|||||||
repoService.addToDocumentLibrary(userOneN1Site, folder2, ContentModel.TYPE_FOLDER);
|
repoService.addToDocumentLibrary(userOneN1Site, folder2, ContentModel.TYPE_FOLDER);
|
||||||
|
|
||||||
String content1 = "content" + System.currentTimeMillis() + "_1";
|
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";
|
String content2 = "content" + System.currentTimeMillis() + "_2";
|
||||||
repoService.addToDocumentLibrary(userOneN1Site, content2, ContentModel.TYPE_CONTENT);
|
repoService.addToDocumentLibrary(userOneN1Site, content2, ContentModel.TYPE_CONTENT);
|
||||||
@@ -1256,14 +1256,19 @@ public class NodeApiTest extends AbstractBaseApiTest
|
|||||||
f1.setNodeType("app:glossary");
|
f1.setNodeType("app:glossary");
|
||||||
f1.expected(folderResp);
|
f1.expected(folderResp);
|
||||||
|
|
||||||
// -ve test - ignore unknown property
|
// -ve test - fail on unknown property
|
||||||
props = new HashMap<>();
|
props = new HashMap<>();
|
||||||
props.put("cm:xyz","my unknown property");
|
props.put("cm:xyz","my unknown property");
|
||||||
dUpdate = new Document();
|
dUpdate = new Document();
|
||||||
dUpdate.setProperties(props);
|
dUpdate.setProperties(props);
|
||||||
response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200);
|
put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 400);
|
||||||
documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
|
||||||
d1.expected(documentResp);
|
// -ve test - fail on unknown aspect
|
||||||
|
List<String> 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
|
// -ve test - duplicate name
|
||||||
dUpdate = new Document();
|
dUpdate = new Document();
|
||||||
|
Reference in New Issue
Block a user