mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
Merged HEAD (5.2) to 5.2.N (5.2.1)
127579 jkaabimofrad: Merged API-STRIKES-BACK (5.2.0) to HEAD (5.2) 126567 jvonka: Node Associations - further updates - for child assocs, do not expose assoc child qname (nominally like file/folder for primary child assoc) - additional api tests (+ve & -ve) for peer assocs & secondary child assocs - RA-745, RA-920, RA-921, RA-930, RA-742, RA-918, RA-919 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@127672 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -36,6 +36,7 @@ import org.alfresco.rest.framework.resource.parameters.where.Query;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||
import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.AssociationExistsException;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -70,6 +71,7 @@ public class AbstractNodeRelation implements InitializingBean
|
||||
protected ServiceRegistry sr;
|
||||
protected NodeService nodeService;
|
||||
protected NamespaceService namespaceService;
|
||||
protected DictionaryService dictionaryService;
|
||||
protected Nodes nodes;
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
@@ -90,21 +92,42 @@ public class AbstractNodeRelation implements InitializingBean
|
||||
|
||||
this.nodeService = sr.getNodeService();
|
||||
this.namespaceService = sr.getNamespaceService();
|
||||
this.dictionaryService = sr.getDictionaryService();
|
||||
}
|
||||
|
||||
protected QName getAssocType(String prefixAssocTypeStr, boolean mandatory)
|
||||
protected QName getAssocType(String prefixAssocTypeStr)
|
||||
{
|
||||
if (mandatory && ((prefixAssocTypeStr == null) || prefixAssocTypeStr.isEmpty()))
|
||||
return getAssocType(prefixAssocTypeStr, true, true);
|
||||
}
|
||||
|
||||
protected QName getAssocType(String prefixAssocTypeStr, boolean mandatory, boolean validate)
|
||||
{
|
||||
QName assocType = null;
|
||||
|
||||
if ((prefixAssocTypeStr != null) && (! prefixAssocTypeStr.isEmpty()))
|
||||
{
|
||||
assocType = QName.createQName(prefixAssocTypeStr, namespaceService);
|
||||
|
||||
if (validate)
|
||||
{
|
||||
if (dictionaryService.getAssociation(assocType) == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Unknown filter assocType: "+prefixAssocTypeStr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (mandatory)
|
||||
{
|
||||
throw new InvalidArgumentException("Missing "+PARAM_ASSOC_TYPE);
|
||||
}
|
||||
|
||||
return QName.createQName(prefixAssocTypeStr, namespaceService);
|
||||
return assocType;
|
||||
}
|
||||
|
||||
protected QNamePattern getAssocTypeFromWhereElseAll(Parameters parameters)
|
||||
{
|
||||
QNamePattern assocTypeQNameParam = RegexQNamePattern.MATCH_ALL;
|
||||
QNamePattern assocTypeQNamePattern = RegexQNamePattern.MATCH_ALL;
|
||||
|
||||
Query q = parameters.getQuery();
|
||||
if (q != null)
|
||||
@@ -115,10 +138,10 @@ public class AbstractNodeRelation implements InitializingBean
|
||||
String assocTypeQNameStr = propertyWalker.getProperty(PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class);
|
||||
if (assocTypeQNameStr != null)
|
||||
{
|
||||
assocTypeQNameParam = getAssocType(assocTypeQNameStr, true);
|
||||
assocTypeQNamePattern = getAssocType(assocTypeQNameStr);
|
||||
}
|
||||
}
|
||||
|
||||
return assocTypeQNameParam;
|
||||
return assocTypeQNamePattern;
|
||||
}
|
||||
}
|
||||
|
@@ -41,20 +41,19 @@ import java.util.Map;
|
||||
/**
|
||||
* Node Parents
|
||||
*
|
||||
* List node's parent(s) - primary & also secondary, if any - based on (parent ->) child associations
|
||||
*
|
||||
* @author janv
|
||||
*/
|
||||
@RelationshipResource(name = "parents", entityResource = NodesEntityResource.class, title = "Node Parents")
|
||||
public class NodeParentsRelation extends AbstractNodeRelation implements RelationshipResourceAction.Read<Node>
|
||||
{
|
||||
/**
|
||||
* List parents
|
||||
* List child node's parent(s) based on (parent ->) child associations.
|
||||
* Returns primary parent & also secondary parents, if any.
|
||||
*
|
||||
* @param childNodeId String id of child node
|
||||
*/
|
||||
@Override
|
||||
@WebApiDescription(title = "Return a paged list of parent nodes based on child assocs")
|
||||
@WebApiDescription(title = "Return a list of parent nodes based on child assocs")
|
||||
public CollectionWithPagingInfo<Node> readAll(String childNodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef childNodeRef = nodes.validateOrLookupNode(childNodeId, null);
|
||||
@@ -84,7 +83,6 @@ public class NodeParentsRelation extends AbstractNodeRelation implements Relatio
|
||||
Node node = nodes.getFolderOrDocument(assocRef.getParentRef(), null, null, includeParam, mapUserInfo);
|
||||
|
||||
QName assocTypeQName = assocRef.getTypeQName();
|
||||
QName assocChildQName = assocRef.getQName();
|
||||
|
||||
String assocType = qnameMap.get(assocTypeQName);
|
||||
if (assocType == null)
|
||||
@@ -93,14 +91,7 @@ public class NodeParentsRelation extends AbstractNodeRelation implements Relatio
|
||||
qnameMap.put(assocTypeQName, assocType);
|
||||
}
|
||||
|
||||
String childQNameStr = qnameMap.get(assocChildQName);
|
||||
if (childQNameStr == null)
|
||||
{
|
||||
childQNameStr = assocChildQName.toPrefixString(namespaceService);
|
||||
qnameMap.put(assocChildQName, childQNameStr);
|
||||
}
|
||||
|
||||
node.setAssociation(new AssocChild(assocType, assocRef.isPrimary(), childQNameStr));
|
||||
node.setAssociation(new AssocChild(assocType, assocRef.isPrimary()));
|
||||
|
||||
collection.add(node);
|
||||
}
|
||||
|
@@ -18,11 +18,13 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.rest.api.model.AssocChild;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.api.model.UserInfo;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
@@ -33,6 +35,7 @@ import org.alfresco.service.cmr.repository.AssociationExistsException;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
@@ -106,15 +109,7 @@ public class NodeSecondaryChildrenRelation extends AbstractNodeRelation implemen
|
||||
qnameMap.put(assocTypeQName, assocType);
|
||||
}
|
||||
|
||||
QName assocChildQName = assocRef.getQName();
|
||||
String childQNameStr = qnameMap.get(assocChildQName);
|
||||
if (childQNameStr == null)
|
||||
{
|
||||
childQNameStr = assocChildQName.toPrefixString(namespaceService);
|
||||
qnameMap.put(assocChildQName, childQNameStr);
|
||||
}
|
||||
|
||||
node.setAssociation(new AssocChild(assocType, assocRef.isPrimary(), childQNameStr));
|
||||
node.setAssociation(new AssocChild(assocType, assocRef.isPrimary()));
|
||||
|
||||
collection.add(node);
|
||||
}
|
||||
@@ -134,20 +129,16 @@ public class NodeSecondaryChildrenRelation extends AbstractNodeRelation implemen
|
||||
|
||||
for (AssocChild assoc : entity)
|
||||
{
|
||||
QName assocTypeQName = getAssocType(assoc.getAssocType(), true);
|
||||
|
||||
String childQNameStr = assoc.getChildQName();
|
||||
if ((childQNameStr == null) || childQNameStr.isEmpty())
|
||||
{
|
||||
throw new InvalidArgumentException("Missing childQName");
|
||||
}
|
||||
|
||||
QName childQName = QName.createQName(childQNameStr, namespaceService);
|
||||
QName assocTypeQName = getAssocType(assoc.getAssocType());
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef childNodeRef = nodes.validateNode(assoc.getChildId());
|
||||
nodeService.addChild(parentNodeRef, childNodeRef, assocTypeQName, childQName);
|
||||
|
||||
String nodeName = (String)nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME);
|
||||
QName assocChildQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName));
|
||||
|
||||
nodeService.addChild(parentNodeRef, childNodeRef, assocTypeQName, assocChildQName);
|
||||
}
|
||||
catch (AssociationExistsException aee)
|
||||
{
|
||||
@@ -170,41 +161,53 @@ public class NodeSecondaryChildrenRelation extends AbstractNodeRelation implemen
|
||||
NodeRef parentNodeRef = nodes.validateNode(parentNodeId);
|
||||
NodeRef childNodeRef = nodes.validateNode(childNodeId);
|
||||
|
||||
QName assocTypeQName = getAssocType(parameters.getParameter("assocType"), false);
|
||||
String assocTypeStr = parameters.getParameter(PARAM_ASSOC_TYPE);
|
||||
QName assocTypeQName = getAssocType(assocTypeStr, false, true);
|
||||
|
||||
String childQNameStr = parameters.getParameter("childQName");
|
||||
QName childQName = null;
|
||||
if ((childQNameStr != null) && (!childQNameStr.isEmpty()))
|
||||
{
|
||||
childQName = QName.createQName(childQNameStr, namespaceService);
|
||||
}
|
||||
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(parentNodeRef);
|
||||
|
||||
if (assocTypeQName != null)
|
||||
boolean found = false;
|
||||
|
||||
for (ChildAssociationRef assocRef : assocRefs)
|
||||
{
|
||||
if (childQName != null)
|
||||
if (! assocRef.getChildRef().equals(childNodeRef))
|
||||
{
|
||||
ChildAssociationRef assocRef = new ChildAssociationRef(assocTypeQName, parentNodeRef, childQName, childNodeRef);
|
||||
nodeService.removeSecondaryChildAssociation(assocRef);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (assocTypeQName != null)
|
||||
{
|
||||
if (assocTypeQName.equals(assocRef.getTypeQName()))
|
||||
{
|
||||
if (assocRef.isPrimary())
|
||||
{
|
||||
throw new InvalidArgumentException("Cannot use secondary-children to delete primary assoc: "
|
||||
+parentNodeId+","+assocTypeStr+","+childNodeId);
|
||||
}
|
||||
|
||||
boolean existed = nodeService.removeSecondaryChildAssociation(assocRef);
|
||||
if (existed)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Missing childQName (in addition to assocType)");
|
||||
}
|
||||
}
|
||||
else if (childQName != null)
|
||||
{
|
||||
throw new InvalidArgumentException("Missing assocType (in addition to childQName)");
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(parentNodeRef);
|
||||
for (ChildAssociationRef assocRef : assocRefs)
|
||||
{
|
||||
if (assocRef.getChildRef().equals(childNodeRef) && (! assocRef.isPrimary()))
|
||||
if (! assocRef.isPrimary())
|
||||
{
|
||||
nodeService.removeSecondaryChildAssociation(assocRef);
|
||||
boolean existed = nodeService.removeSecondaryChildAssociation(assocRef);
|
||||
if (existed)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! found)
|
||||
{
|
||||
throw new EntityNotFoundException(parentNodeId+","+assocTypeStr+","+childNodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,8 @@ import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.api.model.UserInfo;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
@@ -108,17 +110,25 @@ public class NodeTargetsRelation extends AbstractNodeRelation implements
|
||||
|
||||
for (AssocTarget assoc : entity)
|
||||
{
|
||||
QName assocTypeQName = getAssocType(assoc.getAssocType(), true);
|
||||
String assocTypeStr = assoc.getAssocType();
|
||||
QName assocTypeQName = getAssocType(assocTypeStr);
|
||||
|
||||
String targetNodeId = assoc.getTargetId();
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef tgtNodeRef = nodes.validateNode(assoc.getTargetId());
|
||||
NodeRef tgtNodeRef = nodes.validateNode(targetNodeId);
|
||||
nodeService.createAssociation(srcNodeRef, tgtNodeRef, assocTypeQName);
|
||||
}
|
||||
catch (AssociationExistsException aee)
|
||||
{
|
||||
throw new ConstraintViolatedException(aee.getMessage());
|
||||
}
|
||||
catch (IllegalArgumentException iae)
|
||||
{
|
||||
// note: for now, we assume it is invalid assocType - alternatively, we could attempt to pre-validate via dictionary.getAssociation
|
||||
throw new InvalidArgumentException(sourceNodeId+","+assocTypeStr+","+targetNodeId);
|
||||
}
|
||||
|
||||
result.add(assoc);
|
||||
}
|
||||
@@ -133,21 +143,31 @@ public class NodeTargetsRelation extends AbstractNodeRelation implements
|
||||
NodeRef tgtNodeRef = nodes.validateNode(targetNodeId);
|
||||
|
||||
String assocTypeStr = parameters.getParameter(PARAM_ASSOC_TYPE);
|
||||
if ((assocTypeStr != null) && (! assocTypeStr.isEmpty()))
|
||||
QNamePattern assocTypeQName = getAssocType(assocTypeStr, false, true);
|
||||
|
||||
if (assocTypeQName == null)
|
||||
{
|
||||
QName assocTypeQName = QName.createQName(assocTypeStr, namespaceService);
|
||||
nodeService.removeAssociation(srcNodeRef, tgtNodeRef, assocTypeQName);
|
||||
assocTypeQName = RegexQNamePattern.MATCH_ALL;
|
||||
}
|
||||
else
|
||||
|
||||
// note: even if assocType is provided, we currently don't use nodeService.removeAssociation(srcNodeRef, tgtNodeRef, assocTypeQName);
|
||||
// since silent it returns void even if nothing deleted, where as we return 404
|
||||
|
||||
boolean found = false;
|
||||
|
||||
List<AssociationRef> assocRefs = nodeService.getTargetAssocs(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, sourceNodeId), assocTypeQName);
|
||||
for (AssociationRef assocRef : assocRefs)
|
||||
{
|
||||
List<AssociationRef> assocRefs = nodeService.getTargetAssocs(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, sourceNodeId), RegexQNamePattern.MATCH_ALL);
|
||||
for (AssociationRef assocRef : assocRefs)
|
||||
if (assocRef.getTargetRef().equals(tgtNodeRef))
|
||||
{
|
||||
if (assocRef.getTargetRef().equals(tgtNodeRef))
|
||||
{
|
||||
nodeService.removeAssociation(srcNodeRef, tgtNodeRef, assocRef.getTypeQName());
|
||||
}
|
||||
nodeService.removeAssociation(srcNodeRef, tgtNodeRef, assocRef.getTypeQName());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found)
|
||||
{
|
||||
throw new EntityNotFoundException(sourceNodeId+","+assocTypeStr+","+targetNodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user