mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged HEAD (5.2) to 5.2.N (5.2.1)
127606 jkaabimofrad: Merged API-STRIKES-BACK (5.2.0) to HEAD (5.2) 127419 jvonka: Node Associations - 1st cut for creating/listing primary child assoc type other than cm:contains - TODO sanity tests, api spec tweaks RA-1092 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@127713 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -287,4 +287,5 @@ public interface Nodes
|
|||||||
String PARAM_VERSION_COMMENT = "comment";
|
String PARAM_VERSION_COMMENT = "comment";
|
||||||
|
|
||||||
String PARAM_ISPRIMARY = "isPrimary";
|
String PARAM_ISPRIMARY = "isPrimary";
|
||||||
|
String PARAM_ASSOC_TYPE = "assocType";
|
||||||
}
|
}
|
||||||
|
@@ -129,6 +129,8 @@ import org.alfresco.service.cmr.version.VersionService;
|
|||||||
import org.alfresco.service.cmr.version.VersionType;
|
import org.alfresco.service.cmr.version.VersionType;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.namespace.QNamePattern;
|
||||||
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.PropertyCheck;
|
import org.alfresco.util.PropertyCheck;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
@@ -347,7 +349,7 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
// list children filtering (via where clause)
|
// list children filtering (via where clause)
|
||||||
private final static Set<String> LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES =
|
private final static Set<String> LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES =
|
||||||
new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER, PARAM_ISFILE, PARAM_NODETYPE, PARAM_ISPRIMARY}));
|
new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER, PARAM_ISFILE, PARAM_NODETYPE, PARAM_ISPRIMARY, PARAM_ASSOC_TYPE}));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validates that node exists.
|
* Validates that node exists.
|
||||||
@@ -1163,18 +1165,13 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path);
|
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path);
|
||||||
|
|
||||||
// check that resolved node is a folder
|
|
||||||
if (!nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false))
|
|
||||||
{
|
|
||||||
throw new InvalidArgumentException("NodeId of folder is expected: " + parentNodeRef.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> includeParam = parameters.getInclude();
|
final List<String> includeParam = parameters.getInclude();
|
||||||
|
|
||||||
// filters
|
// filters
|
||||||
Boolean includeFolders = null;
|
Boolean includeFolders = null;
|
||||||
Boolean includeFiles = null;
|
Boolean includeFiles = null;
|
||||||
Boolean isPrimary = null;
|
Boolean isPrimary = null;
|
||||||
|
QName assocTypeQNameParam = null;
|
||||||
QName filterNodeTypeQName = null;
|
QName filterNodeTypeQName = null;
|
||||||
|
|
||||||
// note: for files/folders, include subtypes by default (unless filtering by a specific nodeType - see below)
|
// note: for files/folders, include subtypes by default (unless filtering by a specific nodeType - see below)
|
||||||
@@ -1190,6 +1187,12 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
isPrimary = propertyWalker.getProperty(PARAM_ISPRIMARY, WhereClauseParser.EQUALS, Boolean.class);
|
isPrimary = propertyWalker.getProperty(PARAM_ISPRIMARY, WhereClauseParser.EQUALS, Boolean.class);
|
||||||
|
|
||||||
|
String assocTypeQNameStr = propertyWalker.getProperty(PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class);
|
||||||
|
if (assocTypeQNameStr != null)
|
||||||
|
{
|
||||||
|
assocTypeQNameParam = getAssocType(assocTypeQNameStr);
|
||||||
|
}
|
||||||
|
|
||||||
Boolean isFolder = propertyWalker.getProperty(PARAM_ISFOLDER, WhereClauseParser.EQUALS, Boolean.class);
|
Boolean isFolder = propertyWalker.getProperty(PARAM_ISFOLDER, WhereClauseParser.EQUALS, Boolean.class);
|
||||||
Boolean isFile = propertyWalker.getProperty(PARAM_ISFILE, WhereClauseParser.EQUALS, Boolean.class);
|
Boolean isFile = propertyWalker.getProperty(PARAM_ISFILE, WhereClauseParser.EQUALS, Boolean.class);
|
||||||
|
|
||||||
@@ -1302,7 +1305,10 @@ public class NodesImpl implements Nodes
|
|||||||
Set<QName> searchTypeQNames = pair.getFirst();
|
Set<QName> searchTypeQNames = pair.getFirst();
|
||||||
Set<QName> ignoreAspectQNames = pair.getSecond();
|
Set<QName> ignoreAspectQNames = pair.getSecond();
|
||||||
|
|
||||||
pagingResults = fileFolderService.list(parentNodeRef, searchTypeQNames, ignoreAspectQNames, sortProps, filterProps, pagingRequest);
|
Set<QName> assocTypeQNames = buildAssocTypes(assocTypeQNameParam);
|
||||||
|
|
||||||
|
// call GetChildrenCannedQuery (via FileFolderService)
|
||||||
|
pagingResults = fileFolderService.list(parentNodeRef, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, sortProps, filterProps, pagingRequest);
|
||||||
|
|
||||||
|
|
||||||
final Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
final Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
||||||
@@ -1359,6 +1365,34 @@ public class NodesImpl implements Nodes
|
|||||||
return new Pair<>(filterNodeTypeQName, filterIncludeSubTypes);
|
return new Pair<>(filterNodeTypeQName, filterIncludeSubTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Set<QName> buildAssocTypes(QName assocTypeQName)
|
||||||
|
{
|
||||||
|
Set<QName> assocTypeQNames = null;
|
||||||
|
if (assocTypeQName != null)
|
||||||
|
{
|
||||||
|
assocTypeQNames = Collections.singleton(assocTypeQName);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// TODO review - this works, but reduces from ~100 to ~96 (OOTB)
|
||||||
|
// maybe we could post filter (rather than join) - examples: sys:children, sys:lost_found, sys:archivedLink, sys:archiveUserLink
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Collection<QName> qnames = dictionaryService.getAllAssociations();
|
||||||
|
assocTypeQNames = new HashSet<>(qnames.size());
|
||||||
|
|
||||||
|
// remove system assoc types
|
||||||
|
for (QName qname : qnames)
|
||||||
|
{
|
||||||
|
if ((!EXCLUDED_NS.contains(qname.getNamespaceURI())))
|
||||||
|
{
|
||||||
|
assocTypeQNames.add(qname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return assocTypeQNames;
|
||||||
|
}
|
||||||
|
|
||||||
protected Pair<Set<QName>, Set<QName>> buildSearchTypesAndIgnoreAspects(QName nodeTypeQName, boolean includeSubTypes, Set<QName> ignoreQNameTypes, Boolean includeFiles, Boolean includeFolders)
|
protected Pair<Set<QName>, Set<QName>> buildSearchTypesAndIgnoreAspects(QName nodeTypeQName, boolean includeSubTypes, Set<QName> ignoreQNameTypes, Boolean includeFiles, Boolean includeFolders)
|
||||||
{
|
{
|
||||||
Set<QName> searchTypeQNames = new HashSet<>(100);
|
Set<QName> searchTypeQNames = new HashSet<>(100);
|
||||||
@@ -1570,8 +1604,14 @@ public class NodesImpl implements Nodes
|
|||||||
String relativePath = nodeInfo.getRelativePath();
|
String relativePath = nodeInfo.getRelativePath();
|
||||||
parentNodeRef = getOrCreatePath(parentNodeRef, relativePath);
|
parentNodeRef = getOrCreatePath(parentNodeRef, relativePath);
|
||||||
|
|
||||||
|
QName assocTypeQName = ContentModel.ASSOC_CONTAINS;
|
||||||
|
if ((nodeInfo.getAssociation() != null) && (nodeInfo.getAssociation().getAssocType() != null))
|
||||||
|
{
|
||||||
|
assocTypeQName = getAssocType(nodeInfo.getAssociation().getAssocType());
|
||||||
|
}
|
||||||
|
|
||||||
// Create the node
|
// Create the node
|
||||||
NodeRef nodeRef = createNodeImpl(parentNodeRef, nodeName, nodeTypeQName, props);
|
NodeRef nodeRef = createNodeImpl(parentNodeRef, nodeName, nodeTypeQName, props, assocTypeQName);
|
||||||
|
|
||||||
List<String> aspectNames = nodeInfo.getAspectNames();
|
List<String> aspectNames = nodeInfo.getAspectNames();
|
||||||
if (aspectNames != null)
|
if (aspectNames != null)
|
||||||
@@ -1734,7 +1774,7 @@ public class NodesImpl implements Nodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private NodeRef createNodeImpl(NodeRef parentNodeRef, String nodeName, QName nodeTypeQName, Map<QName, Serializable> props)
|
private NodeRef createNodeImpl(NodeRef parentNodeRef, String nodeName, QName nodeTypeQName, Map<QName, Serializable> props, QName assocTypeQName)
|
||||||
{
|
{
|
||||||
NodeRef newNode = null;
|
NodeRef newNode = null;
|
||||||
if (props == null)
|
if (props == null)
|
||||||
@@ -1748,7 +1788,7 @@ public class NodesImpl implements Nodes
|
|||||||
QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName));
|
QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
newNode = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, nodeTypeQName, props).getChildRef();
|
newNode = nodeService.createNode(parentNodeRef, assocTypeQName, assocQName, nodeTypeQName, props).getChildRef();
|
||||||
}
|
}
|
||||||
catch (DuplicateChildNodeNameException dcne)
|
catch (DuplicateChildNodeNameException dcne)
|
||||||
{
|
{
|
||||||
@@ -2413,6 +2453,8 @@ public class NodesImpl implements Nodes
|
|||||||
// if requested, make (get or create) path
|
// if requested, make (get or create) path
|
||||||
parentNodeRef = getOrCreatePath(parentNodeRef, relativePath);
|
parentNodeRef = getOrCreatePath(parentNodeRef, relativePath);
|
||||||
|
|
||||||
|
QName assocTypeQName = ContentModel.ASSOC_CONTAINS;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Map the given properties, if any.
|
// Map the given properties, if any.
|
||||||
@@ -2424,7 +2466,7 @@ public class NodesImpl implements Nodes
|
|||||||
/*
|
/*
|
||||||
* Existing file handling
|
* Existing file handling
|
||||||
*/
|
*/
|
||||||
NodeRef existingFile = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, fileName);
|
NodeRef existingFile = nodeService.getChildByName(parentNodeRef, assocTypeQName, fileName);
|
||||||
if (existingFile != null)
|
if (existingFile != null)
|
||||||
{
|
{
|
||||||
// File already exists, decide what to do
|
// File already exists, decide what to do
|
||||||
@@ -2449,7 +2491,7 @@ public class NodesImpl implements Nodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new file.
|
// Create a new file.
|
||||||
final Node fileNode = createNewFile(parentNodeRef, fileName, nodeTypeQName, content, properties, parameters);
|
Node fileNode = createNewFile(parentNodeRef, fileName, nodeTypeQName, content, properties, assocTypeQName, parameters);
|
||||||
|
|
||||||
// RA-1052
|
// RA-1052
|
||||||
try
|
try
|
||||||
@@ -2501,13 +2543,13 @@ public class NodesImpl implements Nodes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node createNewFile(NodeRef parentNodeRef, String fileName, QName nodeType, Content content, Map<QName, Serializable> props, Parameters params)
|
private Node createNewFile(NodeRef parentNodeRef, String fileName, QName nodeType, Content content, Map<QName, Serializable> props, QName assocTypeQName, Parameters params)
|
||||||
{
|
{
|
||||||
if (nodeType == null)
|
if (nodeType == null)
|
||||||
{
|
{
|
||||||
nodeType = ContentModel.TYPE_CONTENT;
|
nodeType = ContentModel.TYPE_CONTENT;
|
||||||
}
|
}
|
||||||
NodeRef newFile = createNodeImpl(parentNodeRef, fileName, nodeType, props);
|
NodeRef newFile = createNodeImpl(parentNodeRef, fileName, nodeType, props, assocTypeQName);
|
||||||
|
|
||||||
// Write content
|
// Write content
|
||||||
write(newFile, content);
|
write(newFile, content);
|
||||||
|
@@ -58,13 +58,11 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class AbstractNodeRelation implements InitializingBean
|
public class AbstractNodeRelation implements InitializingBean
|
||||||
{
|
{
|
||||||
public final static String PARAM_ASSOC_TYPE = "assocType";
|
|
||||||
|
|
||||||
// excluded namespaces (assoc types)
|
// excluded namespaces (assoc types)
|
||||||
protected static final List<String> EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI);
|
protected static final List<String> EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI);
|
||||||
|
|
||||||
private final static Set<String> WHERE_PARAMS_ASSOC_TYPE =
|
private final static Set<String> WHERE_PARAMS_ASSOC_TYPE =
|
||||||
new HashSet<>(Arrays.asList(new String[] {PARAM_ASSOC_TYPE}));
|
new HashSet<>(Arrays.asList(new String[] {Nodes.PARAM_ASSOC_TYPE}));
|
||||||
|
|
||||||
protected ServiceRegistry sr;
|
protected ServiceRegistry sr;
|
||||||
protected NodeService nodeService;
|
protected NodeService nodeService;
|
||||||
@@ -110,7 +108,7 @@ public class AbstractNodeRelation implements InitializingBean
|
|||||||
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(WHERE_PARAMS_ASSOC_TYPE, null);
|
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(WHERE_PARAMS_ASSOC_TYPE, null);
|
||||||
QueryHelper.walk(q, propertyWalker);
|
QueryHelper.walk(q, propertyWalker);
|
||||||
|
|
||||||
String assocTypeQNameStr = propertyWalker.getProperty(PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class);
|
String assocTypeQNameStr = propertyWalker.getProperty(Nodes.PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class);
|
||||||
if (assocTypeQNameStr != null)
|
if (assocTypeQNameStr != null)
|
||||||
{
|
{
|
||||||
assocTypeQNamePattern = nodes.getAssocType(assocTypeQNameStr);
|
assocTypeQNamePattern = nodes.getAssocType(assocTypeQNameStr);
|
||||||
|
@@ -47,10 +47,8 @@ import java.util.Set;
|
|||||||
@RelationshipResource(name = "parents", entityResource = NodesEntityResource.class, title = "Node Parents")
|
@RelationshipResource(name = "parents", entityResource = NodesEntityResource.class, title = "Node Parents")
|
||||||
public class NodeParentsRelation extends AbstractNodeRelation implements RelationshipResourceAction.Read<Node>
|
public class NodeParentsRelation extends AbstractNodeRelation implements RelationshipResourceAction.Read<Node>
|
||||||
{
|
{
|
||||||
public final static String PARAM_IS_PRIMARY = Nodes.PARAM_ISPRIMARY;
|
|
||||||
|
|
||||||
private final static Set<String> WHERE_PARAMS_PARENTS =
|
private final static Set<String> WHERE_PARAMS_PARENTS =
|
||||||
new HashSet<>(Arrays.asList(new String[] {PARAM_ASSOC_TYPE, PARAM_IS_PRIMARY}));
|
new HashSet<>(Arrays.asList(new String[] {Nodes.PARAM_ASSOC_TYPE, Nodes.PARAM_ISPRIMARY}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List child node's parent(s) based on (parent ->) child associations.
|
* List child node's parent(s) based on (parent ->) child associations.
|
||||||
@@ -74,9 +72,9 @@ public class NodeParentsRelation extends AbstractNodeRelation implements Relatio
|
|||||||
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(WHERE_PARAMS_PARENTS, null);
|
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(WHERE_PARAMS_PARENTS, null);
|
||||||
QueryHelper.walk(q, propertyWalker);
|
QueryHelper.walk(q, propertyWalker);
|
||||||
|
|
||||||
isPrimary = propertyWalker.getProperty(PARAM_IS_PRIMARY, WhereClauseParser.EQUALS, Boolean.class);
|
isPrimary = propertyWalker.getProperty(Nodes.PARAM_ISPRIMARY, WhereClauseParser.EQUALS, Boolean.class);
|
||||||
|
|
||||||
String assocTypeQNameStr = propertyWalker.getProperty(PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class);
|
String assocTypeQNameStr = propertyWalker.getProperty(Nodes.PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class);
|
||||||
if (assocTypeQNameStr != null)
|
if (assocTypeQNameStr != null)
|
||||||
{
|
{
|
||||||
assocTypeQNameParam = nodes.getAssocType(assocTypeQNameStr);
|
assocTypeQNameParam = nodes.getAssocType(assocTypeQNameStr);
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.api.nodes;
|
package org.alfresco.rest.api.nodes;
|
||||||
|
|
||||||
|
import org.alfresco.rest.api.Nodes;
|
||||||
import org.alfresco.rest.api.model.AssocChild;
|
import org.alfresco.rest.api.model.AssocChild;
|
||||||
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;
|
||||||
@@ -94,7 +95,7 @@ public class NodeSecondaryChildrenRelation extends AbstractNodeRelation implemen
|
|||||||
NodeRef parentNodeRef = nodes.validateNode(parentNodeId);
|
NodeRef parentNodeRef = nodes.validateNode(parentNodeId);
|
||||||
NodeRef childNodeRef = nodes.validateNode(childNodeId);
|
NodeRef childNodeRef = nodes.validateNode(childNodeId);
|
||||||
|
|
||||||
String assocTypeStr = parameters.getParameter(PARAM_ASSOC_TYPE);
|
String assocTypeStr = parameters.getParameter(Nodes.PARAM_ASSOC_TYPE);
|
||||||
QName assocTypeQName = nodes.getAssocType(assocTypeStr, false);
|
QName assocTypeQName = nodes.getAssocType(assocTypeStr, false);
|
||||||
|
|
||||||
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(parentNodeRef);
|
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(parentNodeRef);
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.api.nodes;
|
package org.alfresco.rest.api.nodes;
|
||||||
|
|
||||||
|
import org.alfresco.rest.api.Nodes;
|
||||||
import org.alfresco.rest.api.model.AssocTarget;
|
import org.alfresco.rest.api.model.AssocTarget;
|
||||||
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;
|
||||||
@@ -79,7 +80,7 @@ public class NodeTargetsRelation extends AbstractNodeRelation implements
|
|||||||
NodeRef srcNodeRef = nodes.validateNode(sourceNodeId);
|
NodeRef srcNodeRef = nodes.validateNode(sourceNodeId);
|
||||||
NodeRef tgtNodeRef = nodes.validateNode(targetNodeId);
|
NodeRef tgtNodeRef = nodes.validateNode(targetNodeId);
|
||||||
|
|
||||||
String assocTypeStr = parameters.getParameter(PARAM_ASSOC_TYPE);
|
String assocTypeStr = parameters.getParameter(Nodes.PARAM_ASSOC_TYPE);
|
||||||
QNamePattern assocTypeQName = nodes.getAssocType(assocTypeStr, false);
|
QNamePattern assocTypeQName = nodes.getAssocType(assocTypeStr, false);
|
||||||
|
|
||||||
if (assocTypeQName == null)
|
if (assocTypeQName == null)
|
||||||
|
Reference in New Issue
Block a user