use of org.alfresco.repo.copy.CopyBehaviourCallback.CopyAssociationDetails 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");
}
}
}
}
Aggregations