Search in sources :

Example 1 with CopyChildAssociationDetails

use of org.alfresco.repo.copy.CopyBehaviourCallback.CopyChildAssociationDetails in project alfresco-repository by Alfresco.

the class CopyServiceImpl method copyChildren.

/**
 * @param copyChildren              <tt>false</tt> if the client selected not to recurse
 */
private void copyChildren(CopyDetails copyDetails, QName classQName, NodeRef copyTarget, boolean copyTargetIsNew, boolean copyChildren, Map<NodeRef, NodeRef> copiesByOriginals, Set<NodeRef> copies, Map<QName, CopyBehaviourCallback> callbacks) {
    NodeRef sourceNodeRef = copyDetails.getSourceNodeRef();
    ClassDefinition classDef = dictionaryService.getClass(classQName);
    if (classDef == null) {
        // Ignore missing types
        return;
    }
    // Check the behaviour
    CopyBehaviourCallback callback = callbacks.get(classQName);
    if (callback == null) {
        throw new IllegalStateException("Source node class has no callback: " + classQName);
    }
    // Prepare storage for post-copy association handling
    List<Pair<AssociationRef, AssocCopyTargetAction>> postCopyAssocs = TransactionalResourceHelper.getList(KEY_POST_COPY_ASSOCS);
    // Handle peer associations.
    for (Map.Entry<QName, AssociationDefinition> entry : classDef.getAssociations().entrySet()) {
        QName assocTypeQName = entry.getKey();
        AssociationDefinition assocDef = entry.getValue();
        if (assocDef.isChild()) {
            // Ignore child assocs
            continue;
        }
        boolean haveRemovedFromCopyTarget = false;
        // Get the associations
        List<AssociationRef> assocRefs = nodeService.getTargetAssocs(sourceNodeRef, assocTypeQName);
        for (AssociationRef assocRef : assocRefs) {
            // Get the copy action for the association instance
            CopyAssociationDetails assocCopyDetails = new CopyAssociationDetails(assocRef, copyTarget, copyTargetIsNew);
            Pair<AssocCopySourceAction, AssocCopyTargetAction> assocCopyAction = callback.getAssociationCopyAction(classQName, copyDetails, assocCopyDetails);
            // Consider the source side first
            switch(assocCopyAction.getFirst()) {
                case IGNORE:
                    // Do nothing
                    continue;
                case COPY_REMOVE_EXISTING:
                    if (!copyTargetIsNew && !haveRemovedFromCopyTarget) {
                        // Only do this if we are copying over an existing node and we have NOT
                        // already cleaned up for this association type
                        haveRemovedFromCopyTarget = true;
                        for (AssociationRef assocToRemoveRef : internalNodeService.getTargetAssocs(copyTarget, assocTypeQName)) {
                            internalNodeService.removeAssociation(assocToRemoveRef.getSourceRef(), assocToRemoveRef.getTargetRef(), assocTypeQName);
                        }
                    }
                // Fall through to copy
                case COPY:
                    // Record the type of target behaviour that is expected
                    switch(assocCopyAction.getSecond()) {
                        case USE_ORIGINAL_TARGET:
                        case USE_COPIED_TARGET:
                        case USE_COPIED_OTHERWISE_ORIGINAL_TARGET:
                            // Have to save for later to see if the target node is copied, too
                            postCopyAssocs.add(new Pair<AssociationRef, AssocCopyTargetAction>(assocRef, assocCopyAction.getSecond()));
                            break;
                        default:
                            throw new IllegalStateException("Unknown association target copy action: " + assocCopyAction);
                    }
                    break;
                default:
                    throw new IllegalStateException("Unknown association source copy action: " + assocCopyAction);
            }
        }
    }
    // Handle child associations.  These need special attention due to their recursive nature.
    for (Map.Entry<QName, ChildAssociationDefinition> childEntry : classDef.getChildAssociations().entrySet()) {
        QName childAssocTypeQName = childEntry.getKey();
        ChildAssociationDefinition childAssocDef = childEntry.getValue();
        if (!childAssocDef.isChild()) {
            // Ignore non-child assocs
            continue;
        }
        // Get the child associations
        List<ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(sourceNodeRef, childAssocTypeQName, RegexQNamePattern.MATCH_ALL);
        for (ChildAssociationRef childAssocRef : childAssocRefs) {
            NodeRef childNodeRef = childAssocRef.getChildRef();
            QName assocQName = childAssocRef.getQName();
            CopyChildAssociationDetails childAssocCopyDetails = new CopyChildAssociationDetails(childAssocRef, copyTarget, copyTargetIsNew, copyChildren);
            // Handle nested copies
            if (copies.contains(childNodeRef)) {
                // of the same type.  This is ignorable.
                continue;
            }
            // Get the copy action for the association instance
            ChildAssocCopyAction childAssocCopyAction = callback.getChildAssociationCopyAction(classQName, copyDetails, childAssocCopyDetails);
            switch(childAssocCopyAction) {
                case IGNORE:
                    break;
                case COPY_ASSOC:
                    nodeService.addChild(copyTarget, childNodeRef, childAssocTypeQName, assocQName);
                    break;
                case COPY_CHILD:
                    // Handle potentially cyclic relationships
                    if (copiesByOriginals.containsKey(childNodeRef)) {
                        // This is either a cyclic relationship or there are multiple different
                        // types of associations between the same parent and child.
                        // Just hook the child up with the association.
                        nodeService.addChild(copyTarget, childNodeRef, childAssocTypeQName, assocQName);
                    } else {
                        // Find out whether to force a recursion
                        ChildAssocRecurseAction childAssocRecurseAction = callback.getChildAssociationRecurseAction(classQName, copyDetails, childAssocCopyDetails);
                        switch(childAssocRecurseAction) {
                            case RESPECT_RECURSE_FLAG:
                                // Keep child copy flag the same
                                break;
                            case FORCE_RECURSE:
                                // Force recurse
                                copyChildren = true;
                                break;
                            default:
                                throw new IllegalStateException("Unrecognized enum");
                        }
                        // This copy may fail silently
                        copyImpl(childNodeRef, copyTarget, childAssocTypeQName, assocQName, // Keep child names for deep copies
                        copyChildren, // Keep child names for deep copies
                        false, copiesByOriginals, copies);
                    }
                    break;
                default:
                    throw new IllegalStateException("Unrecognized enum");
            }
        }
    }
}
Also used : CopyAssociationDetails(org.alfresco.repo.copy.CopyBehaviourCallback.CopyAssociationDetails) ClassDefinition(org.alfresco.service.cmr.dictionary.ClassDefinition) AssocCopySourceAction(org.alfresco.repo.copy.CopyBehaviourCallback.AssocCopySourceAction) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) AssociationRef(org.alfresco.service.cmr.repository.AssociationRef) NodeRef(org.alfresco.service.cmr.repository.NodeRef) ChildAssocRecurseAction(org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocRecurseAction) Pair(org.alfresco.util.Pair) ChildAssocCopyAction(org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocCopyAction) QName(org.alfresco.service.namespace.QName) AssocCopyTargetAction(org.alfresco.repo.copy.CopyBehaviourCallback.AssocCopyTargetAction) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) CopyChildAssociationDetails(org.alfresco.repo.copy.CopyBehaviourCallback.CopyChildAssociationDetails) ChildAssociationDefinition(org.alfresco.service.cmr.dictionary.ChildAssociationDefinition) AssociationDefinition(org.alfresco.service.cmr.dictionary.AssociationDefinition) ChildAssociationDefinition(org.alfresco.service.cmr.dictionary.ChildAssociationDefinition) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 AssocCopySourceAction (org.alfresco.repo.copy.CopyBehaviourCallback.AssocCopySourceAction)1 AssocCopyTargetAction (org.alfresco.repo.copy.CopyBehaviourCallback.AssocCopyTargetAction)1 ChildAssocCopyAction (org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocCopyAction)1 ChildAssocRecurseAction (org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocRecurseAction)1 CopyAssociationDetails (org.alfresco.repo.copy.CopyBehaviourCallback.CopyAssociationDetails)1 CopyChildAssociationDetails (org.alfresco.repo.copy.CopyBehaviourCallback.CopyChildAssociationDetails)1 AssociationDefinition (org.alfresco.service.cmr.dictionary.AssociationDefinition)1 ChildAssociationDefinition (org.alfresco.service.cmr.dictionary.ChildAssociationDefinition)1 ClassDefinition (org.alfresco.service.cmr.dictionary.ClassDefinition)1 AssociationRef (org.alfresco.service.cmr.repository.AssociationRef)1 ChildAssociationRef (org.alfresco.service.cmr.repository.ChildAssociationRef)1 NodeRef (org.alfresco.service.cmr.repository.NodeRef)1 QName (org.alfresco.service.namespace.QName)1 Pair (org.alfresco.util.Pair)1