Search in sources :

Example 86 with AssociationRef

use of org.alfresco.service.cmr.repository.AssociationRef in project alfresco-repository by Alfresco.

the class CopyServiceImpl method recursiveCopy.

/**
 * Recursive copy algorithm
 *
 * @param dropName      drop the name property when associations don't allow duplicately named children
 */
private NodeRef recursiveCopy(CopyDetails copyDetails, boolean copyChildren, boolean dropName, Map<NodeRef, NodeRef> copiesByOriginal, Set<NodeRef> copies, Map<QName, CopyBehaviourCallback> callbacks) {
    NodeRef sourceNodeRef = copyDetails.getSourceNodeRef();
    Set<QName> sourceNodeAspectQNames = copyDetails.getSourceNodeAspectQNames();
    NodeRef targetParentNodeRef = copyDetails.getTargetParentNodeRef();
    QName assocTypeQName = copyDetails.getAssocTypeQName();
    QName assocQName = copyDetails.getAssocQName();
    // Avoid duplicate and cyclic copies
    if (copies.contains(sourceNodeRef)) {
        throw new IllegalStateException("Nested copy prevention has failed: \n" + "   " + copyDetails + "\n" + "   Copies by original: " + copiesByOriginal);
    } else if (copiesByOriginal.containsKey(sourceNodeRef)) {
        throw new IllegalStateException("Multiple child assocs between same two nodes detected: \n" + "   " + copyDetails + "\n" + "   Copies by original: " + copiesByOriginal);
    }
    // Extract Type Definition
    QName sourceNodeTypeQName = copyDetails.getSourceNodeTypeQName();
    // Does this node get copied at all?
    // The source node's type-bound behaviour has an effective veto.
    CopyBehaviourCallback sourceTypeBehaviour = callbacks.get(sourceNodeTypeQName);
    if (sourceTypeBehaviour == null) {
        throw new IllegalStateException("Source node type has no callback: " + sourceNodeTypeQName);
    }
    if (!sourceTypeBehaviour.getMustCopy(sourceNodeTypeQName, copyDetails)) {
        // Nothing to do
        return null;
    }
    // Get the type properties to copy
    Map<QName, Serializable> targetNodeProperties = buildCopyProperties(copyDetails, Collections.singleton(sourceNodeTypeQName), callbacks);
    // Some aspects are going to be applied automatically.  For efficiency, the initial node properties
    // for these aspects should be provided.
    Set<QName> defaultAspectQNames = getDefaultAspects(sourceNodeTypeQName);
    Map<QName, Serializable> defaultAspectsProperties = buildCopyProperties(copyDetails, defaultAspectQNames, callbacks);
    targetNodeProperties.putAll(defaultAspectsProperties);
    // Drop the name property, if required.  This prevents duplicate names and leaves it up to the client
    // to assign a new name.
    AssociationDefinition assocDef = dictionaryService.getAssociation(assocTypeQName);
    if (!assocDef.isChild()) {
        throw new AlfrescoRuntimeException("Association is not a child association: " + assocTypeQName);
    } else {
        ChildAssociationDefinition childAssocDef = (ChildAssociationDefinition) assocDef;
        if (dropName && !childAssocDef.getDuplicateChildNamesAllowed()) {
            // ALF-13949: A behaviour callback (e.g. WorkingCopyAspect) may already have generated a new name, so
            // preserve the new name if it has changed
            String newName = (String) targetNodeProperties.get(ContentModel.PROP_NAME);
            if (newName != null && newName.equals(nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME))) {
                // duplicate children are not allowed.
                targetNodeProperties.remove(ContentModel.PROP_NAME);
            }
        }
    }
    // Lastly, make sure the the Node UUID is set correctly; after all, the contract
    // of the CopyDetails says that the targetNodeRef was already determined.
    String targetNodeUuid = copyDetails.getTargetNodeRef().getId();
    targetNodeProperties.put(ContentModel.PROP_NODE_UUID, targetNodeUuid);
    // The initial node copy is good to go
    ChildAssociationRef targetChildAssocRef = this.nodeService.createNode(targetParentNodeRef, assocTypeQName, assocQName, sourceNodeTypeQName, targetNodeProperties);
    NodeRef copyTarget = targetChildAssocRef.getChildRef();
    // Save the mapping for later
    copiesByOriginal.put(sourceNodeRef, copyTarget);
    copies.add(copyTarget);
    // We now have a node, so fire the BeforeCopyPolicy
    invokeBeforeCopy(sourceNodeRef, copyTarget);
    // Work out which aspects still need copying.  The source aspects less the default aspects
    // will give this set.
    Set<QName> remainingAspectQNames = new HashSet<QName>(sourceNodeAspectQNames);
    remainingAspectQNames.removeAll(defaultAspectQNames);
    // Prevent any rules being fired on the new destination node
    this.ruleService.disableRules(copyTarget);
    try {
        // Apply the remaining aspects and properties
        for (QName remainingAspectQName : remainingAspectQNames) {
            copyProperties(copyDetails, copyTarget, remainingAspectQName, callbacks);
        }
        // Copy residual properties
        copyResidualProperties(copyDetails, copyTarget);
        // Link the new node to the original, but ensure that we only keep track of the last copy
        List<AssociationRef> originalAssocs = internalNodeService.getTargetAssocs(copyTarget, ContentModel.ASSOC_ORIGINAL);
        for (AssociationRef originalAssoc : originalAssocs) {
            internalNodeService.removeAssociation(originalAssoc.getSourceRef(), originalAssoc.getTargetRef(), ContentModel.ASSOC_ORIGINAL);
        }
        // We create the link if the source is a cm:object and the not sys:pendingDelete
        QName sourceTypeQName = internalNodeService.getType(sourceNodeRef);
        if (dictionaryService.isSubClass(sourceTypeQName, ContentModel.TYPE_CMOBJECT) && !sourceNodeAspectQNames.contains(ContentModel.ASPECT_PENDING_DELETE)) {
            internalNodeService.createAssociation(copyTarget, sourceNodeRef, ContentModel.ASSOC_ORIGINAL);
        } else {
            // We are not creating the association, so remove the associated aspect
            internalNodeService.removeAspect(copyTarget, ContentModel.ASPECT_COPIEDFROM);
        }
        // Copy permissions
        copyPermissions(sourceNodeRef, copyTarget);
        // We present the recursion option regardless of what the client chooses
        copyChildren(copyDetails, copyTarget, // We know that the node has been created
        true, copyChildren, copiesByOriginal, copies, callbacks);
    } finally {
        this.ruleService.enableRules(copyTarget);
    }
    return copyTarget;
}
Also used : Serializable(java.io.Serializable) QName(org.alfresco.service.namespace.QName) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) AssociationRef(org.alfresco.service.cmr.repository.AssociationRef) NodeRef(org.alfresco.service.cmr.repository.NodeRef) ChildAssociationDefinition(org.alfresco.service.cmr.dictionary.ChildAssociationDefinition) AssociationDefinition(org.alfresco.service.cmr.dictionary.AssociationDefinition) ChildAssociationDefinition(org.alfresco.service.cmr.dictionary.ChildAssociationDefinition) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) HashSet(java.util.HashSet)

Example 87 with AssociationRef

use of org.alfresco.service.cmr.repository.AssociationRef in project alfresco-repository by Alfresco.

the class CMISConnector method getRelationships.

public List<ObjectData> getRelationships(NodeRef nodeRef, IncludeRelationships includeRelationships) /*, CmisVersion cmisVersion*/
{
    List<ObjectData> result = new ArrayList<ObjectData>();
    if (nodeRef.getStoreRef().getProtocol().equals(VersionBaseModel.STORE_PROTOCOL)) {
        // relationships from and to versions are not preserved
        return result;
    }
    // get relationships
    List<AssociationRef> assocs = new ArrayList<AssociationRef>();
    if (includeRelationships == IncludeRelationships.SOURCE || includeRelationships == IncludeRelationships.BOTH) {
        assocs.addAll(nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL));
    }
    if (includeRelationships == IncludeRelationships.TARGET || includeRelationships == IncludeRelationships.BOTH) {
        assocs.addAll(nodeService.getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL));
    }
    // filter relationships that not map the CMIS domain model
    for (AssociationRef assocRef : assocs) {
        TypeDefinitionWrapper assocTypeDef = getOpenCMISDictionaryService().findAssocType(assocRef.getTypeQName());
        if (assocTypeDef == null || getType(assocRef.getSourceRef()) == null || getType(assocRef.getTargetRef()) == null) {
            continue;
        }
        try {
            result.add(createCMISObject(createNodeInfo(assocRef), null, false, IncludeRelationships.NONE, RENDITION_NONE, false, false));
        } catch (AccessDeniedException e) {
        // PUBLICAPI-110
        // ok, just skip it
        } catch (CmisObjectNotFoundException e) {
        // ignore objects that have not been found (perhaps because their type is unknown to CMIS)
        }// TODO: Somewhere this has not been wrapped correctly
         catch (net.sf.acegisecurity.AccessDeniedException e) {
        // skip
        }
    }
    return result;
}
Also used : AccessDeniedException(org.alfresco.repo.security.permissions.AccessDeniedException) CmisObjectNotFoundException(org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException) ItemTypeDefinitionWrapper(org.alfresco.opencmis.dictionary.ItemTypeDefinitionWrapper) TypeDefinitionWrapper(org.alfresco.opencmis.dictionary.TypeDefinitionWrapper) DocumentTypeDefinitionWrapper(org.alfresco.opencmis.dictionary.DocumentTypeDefinitionWrapper) ObjectData(org.apache.chemistry.opencmis.commons.data.ObjectData) ArrayList(java.util.ArrayList) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) AssociationRef(org.alfresco.service.cmr.repository.AssociationRef)

Example 88 with AssociationRef

use of org.alfresco.service.cmr.repository.AssociationRef in project alfresco-repository by Alfresco.

the class CMISConnector method getObjectRelationships.

public ObjectList getObjectRelationships(NodeRef nodeRef, RelationshipDirection relationshipDirection, String typeId, String filter, Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount) {
    ObjectListImpl result = new ObjectListImpl();
    result.setHasMoreItems(false);
    result.setNumItems(BigInteger.ZERO);
    result.setObjects(new ArrayList<ObjectData>());
    if (nodeRef.getStoreRef().getProtocol().equals(VersionBaseModel.STORE_PROTOCOL)) {
        // relationships from and to versions are not preserved
        return result;
    }
    // get relationships
    List<AssociationRef> assocs = new ArrayList<AssociationRef>();
    if (relationshipDirection == RelationshipDirection.SOURCE || relationshipDirection == RelationshipDirection.EITHER) {
        assocs.addAll(nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL));
    }
    if (relationshipDirection == RelationshipDirection.TARGET || relationshipDirection == RelationshipDirection.EITHER) {
        assocs.addAll(nodeService.getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL));
    }
    int skip = (skipCount == null ? 0 : skipCount.intValue());
    int max = (maxItems == null ? Integer.MAX_VALUE : maxItems.intValue());
    int counter = 0;
    boolean hasMore = false;
    if (max > 0) {
        // filter relationships that not map the CMIS domain model
        for (AssociationRef assocRef : assocs) {
            TypeDefinitionWrapper assocTypeDef = getOpenCMISDictionaryService().findAssocType(assocRef.getTypeQName());
            if (assocTypeDef == null || getType(assocRef.getSourceRef()) == null || getType(assocRef.getTargetRef()) == null) {
                continue;
            }
            if ((typeId != null) && !assocTypeDef.getTypeId().equals(typeId)) {
                continue;
            }
            counter++;
            if (skip > 0) {
                skip--;
                continue;
            }
            max--;
            if (max > 0) {
                try {
                    result.getObjects().add(createCMISObject(createNodeInfo(assocRef), filter, includeAllowableActions, IncludeRelationships.NONE, RENDITION_NONE, false, false));
                } catch (CmisObjectNotFoundException e) {
                // ignore objects that have not been found (perhaps because their type is unknown to CMIS)
                }
            } else {
                hasMore = true;
            }
        }
    }
    result.setNumItems(BigInteger.valueOf(counter));
    result.setHasMoreItems(hasMore);
    return result;
}
Also used : CmisObjectNotFoundException(org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException) ItemTypeDefinitionWrapper(org.alfresco.opencmis.dictionary.ItemTypeDefinitionWrapper) TypeDefinitionWrapper(org.alfresco.opencmis.dictionary.TypeDefinitionWrapper) DocumentTypeDefinitionWrapper(org.alfresco.opencmis.dictionary.DocumentTypeDefinitionWrapper) ObjectData(org.apache.chemistry.opencmis.commons.data.ObjectData) ArrayList(java.util.ArrayList) ObjectListImpl(org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) AssociationRef(org.alfresco.service.cmr.repository.AssociationRef)

Example 89 with AssociationRef

use of org.alfresco.service.cmr.repository.AssociationRef in project alfresco-repository by Alfresco.

the class AbstractNodeDAOImpl method getTargetNodeAssocs.

@Override
public Collection<Pair<Long, AssociationRef>> getTargetNodeAssocs(Long sourceNodeId, QName typeQName) {
    Long typeQNameId = null;
    if (typeQName != null) {
        Pair<Long, QName> typeQNamePair = qnameDAO.getQName(typeQName);
        if (typeQNamePair == null) {
            // No such QName
            return Collections.emptyList();
        }
        typeQNameId = typeQNamePair.getFirst();
    }
    List<NodeAssocEntity> nodeAssocEntities = selectNodeAssocsBySource(sourceNodeId, typeQNameId);
    List<Pair<Long, AssociationRef>> results = new ArrayList<Pair<Long, AssociationRef>>(nodeAssocEntities.size());
    for (NodeAssocEntity nodeAssocEntity : nodeAssocEntities) {
        Long assocId = nodeAssocEntity.getId();
        AssociationRef assocRef = nodeAssocEntity.getAssociationRef(qnameDAO);
        results.add(new Pair<Long, AssociationRef>(assocId, assocRef));
    }
    return results;
}
Also used : QName(org.alfresco.service.namespace.QName) ArrayList(java.util.ArrayList) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) AssociationRef(org.alfresco.service.cmr.repository.AssociationRef) Pair(org.alfresco.util.Pair)

Example 90 with AssociationRef

use of org.alfresco.service.cmr.repository.AssociationRef in project alfresco-repository by Alfresco.

the class ScriptNode method getSourceAssocs.

/**
 * Return the source associations to this Node. As a Map of assoc name to a JavaScript array of Nodes.
 * The Map returned implements the Scriptable interface to allow access to the assoc arrays via JavaScript
 * associative array access. This means source associations to this node can be access thus:
 * <code>node.sourceAssocs["translations"][0]</code>
 *
 * @return source associations as a Map of assoc name to a JavaScript array of Nodes.
 */
@SuppressWarnings("unchecked")
public Map<String, Object> getSourceAssocs() {
    if (this.sourceAssocs == null) {
        // this Map implements the Scriptable interface for native JS syntax property access
        this.sourceAssocs = new ScriptableQNameMap<String, Object>(this);
        // get the list of source nodes for each association type
        List<AssociationRef> refs = this.nodeService.getSourceAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL);
        for (AssociationRef ref : refs) {
            String qname = ref.getTypeQName().toString();
            List<ScriptNode> nodes = (List<ScriptNode>) this.sourceAssocs.get(qname);
            if (nodes == null) {
                // first access of the list for this qname
                nodes = new ArrayList<ScriptNode>(4);
                this.sourceAssocs.put(ref.getTypeQName().toString(), nodes);
            }
            nodes.add(newInstance(ref.getSourceRef(), this.services, this.scope));
        }
        // convert each Node list into a JavaScript array object
        for (String qname : this.sourceAssocs.keySet()) {
            List<ScriptNode> nodes = (List<ScriptNode>) this.sourceAssocs.get(qname);
            Object[] objs = nodes.toArray(new Object[nodes.size()]);
            this.sourceAssocs.put(qname, Context.getCurrentContext().newArray(this.scope, objs));
        }
    }
    return this.sourceAssocs;
}
Also used : JSONObject(org.json.JSONObject) ScriptableObject(org.mozilla.javascript.ScriptableObject) ArrayList(java.util.ArrayList) List(java.util.List) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) AssociationRef(org.alfresco.service.cmr.repository.AssociationRef)

Aggregations

AssociationRef (org.alfresco.service.cmr.repository.AssociationRef)138 ChildAssociationRef (org.alfresco.service.cmr.repository.ChildAssociationRef)112 NodeRef (org.alfresco.service.cmr.repository.NodeRef)102 QName (org.alfresco.service.namespace.QName)56 ArrayList (java.util.ArrayList)44 Serializable (java.io.Serializable)30 Test (org.junit.Test)26 HashMap (java.util.HashMap)24 List (java.util.List)15 Pair (org.alfresco.util.Pair)14 HashSet (java.util.HashSet)13 Map (java.util.Map)13 StoreRef (org.alfresco.service.cmr.repository.StoreRef)12 BaseSpringTest (org.alfresco.util.BaseSpringTest)10 Extend (org.alfresco.traitextender.Extend)8 Iterator (java.util.Iterator)7 AlfrescoRuntimeException (org.alfresco.error.AlfrescoRuntimeException)7 PropertyDefinition (org.alfresco.service.cmr.dictionary.PropertyDefinition)7 Path (org.alfresco.service.cmr.repository.Path)6 Version (org.alfresco.service.cmr.version.Version)6