mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
757
source/java/org/alfresco/repo/copy/CopyServiceImpl.java
Normal file
757
source/java/org/alfresco/repo/copy/CopyServiceImpl.java
Normal file
@@ -0,0 +1,757 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.copy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.CopyServiceException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
|
||||
/**
|
||||
* Node operations service implmentation.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class CopyServiceImpl implements CopyService
|
||||
{
|
||||
/**
|
||||
* The node service
|
||||
*/
|
||||
private NodeService nodeService;
|
||||
|
||||
/**
|
||||
* The dictionary service
|
||||
*/
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
/**
|
||||
* Policy component
|
||||
*/
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
/**
|
||||
* Rule service
|
||||
*/
|
||||
private RuleService ruleService;
|
||||
|
||||
/**
|
||||
* Policy delegates
|
||||
*/
|
||||
private ClassPolicyDelegate<CopyServicePolicies.OnCopyNodePolicy> onCopyNodeDelegate;
|
||||
private ClassPolicyDelegate<CopyServicePolicies.OnCopyCompletePolicy> onCopyCompleteDelegate;
|
||||
|
||||
/**
|
||||
* Set the node service
|
||||
*
|
||||
* @param nodeService the node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dictionary service
|
||||
*
|
||||
* @param dictionaryService the dictionary service
|
||||
*/
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the policy component
|
||||
*
|
||||
* @param policyComponent the policy component
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rule service
|
||||
*
|
||||
* @param ruleService the rule service
|
||||
*/
|
||||
public void setRuleService(RuleService ruleService)
|
||||
{
|
||||
this.ruleService = ruleService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise method
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
// Register the policies
|
||||
this.onCopyNodeDelegate = this.policyComponent.registerClassPolicy(CopyServicePolicies.OnCopyNodePolicy.class);
|
||||
this.onCopyCompleteDelegate = this.policyComponent.registerClassPolicy(CopyServicePolicies.OnCopyCompletePolicy.class);
|
||||
|
||||
// Register policy behaviours
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||
ContentModel.ASPECT_COPIEDFROM,
|
||||
new JavaBehaviour(this, "copyAspectOnCopy"));
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"),
|
||||
ContentModel.ASPECT_COPIEDFROM,
|
||||
new JavaBehaviour(this, "onCopyComplete"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.activiti.repo.node.copy.NodeCopyService#copy(com.activiti.repo.ref.NodeRef, com.activiti.repo.ref.NodeRef, com.activiti.repo.ref.QName, QName, boolean)
|
||||
*/
|
||||
public NodeRef copy(
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationParent,
|
||||
QName destinationAssocTypeQName,
|
||||
QName destinationQName,
|
||||
boolean copyChildren)
|
||||
{
|
||||
// Check that all the passed values are not null
|
||||
ParameterCheck.mandatory("Source Node", sourceNodeRef);
|
||||
ParameterCheck.mandatory("Destination Parent", destinationParent);
|
||||
ParameterCheck.mandatory("Destination Association Name", destinationQName);
|
||||
|
||||
if (sourceNodeRef.getStoreRef().equals(destinationParent.getStoreRef()) == false)
|
||||
{
|
||||
// TODO We need to create a new node in the other store with the same id as the source
|
||||
|
||||
// Error - since at the moment we do not support cross store copying
|
||||
throw new UnsupportedOperationException("Copying nodes across stores is not currently supported.");
|
||||
}
|
||||
|
||||
// Recursively copy node
|
||||
Map<NodeRef, NodeRef> copiedChildren = new HashMap<NodeRef, NodeRef>();
|
||||
NodeRef copy = recursiveCopy(sourceNodeRef, destinationParent, destinationAssocTypeQName, destinationQName, copyChildren, copiedChildren);
|
||||
|
||||
// Foreach of the newly created copies call the copy complete policy
|
||||
for (Map.Entry<NodeRef, NodeRef> entry : copiedChildren.entrySet())
|
||||
{
|
||||
invokeCopyComplete(entry.getKey(), entry.getValue(), copiedChildren);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the copy complete policy for the node reference provided
|
||||
*
|
||||
* @param sourceNodeRef the source node reference
|
||||
* @param destinationNodeRef the destination node reference
|
||||
* @param copiedNodeRefs the map of copied node references
|
||||
*/
|
||||
private void invokeCopyComplete(
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationNodeRef,
|
||||
Map<NodeRef, NodeRef> copiedNodeRefs)
|
||||
{
|
||||
QName sourceClassRef = this.nodeService.getType(sourceNodeRef);
|
||||
invokeCopyComplete(sourceClassRef, sourceNodeRef, destinationNodeRef, copiedNodeRefs);
|
||||
|
||||
// Get the source aspects
|
||||
Set<QName> sourceAspects = this.nodeService.getAspects(sourceNodeRef);
|
||||
for (QName sourceAspect : sourceAspects)
|
||||
{
|
||||
invokeCopyComplete(sourceAspect, sourceNodeRef, destinationNodeRef, copiedNodeRefs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeQName
|
||||
* @param sourceNodeRef
|
||||
* @param destinationNodeRef
|
||||
* @param copiedNodeRefs
|
||||
*/
|
||||
private void invokeCopyComplete(
|
||||
QName typeQName,
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationNodeRef,
|
||||
Map<NodeRef, NodeRef> copiedNodeRefs)
|
||||
{
|
||||
Collection<CopyServicePolicies.OnCopyCompletePolicy> policies = this.onCopyCompleteDelegate.getList(typeQName);
|
||||
if (policies.isEmpty() == true)
|
||||
{
|
||||
defaultOnCopyComplete(typeQName, sourceNodeRef, destinationNodeRef, copiedNodeRefs);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (CopyServicePolicies.OnCopyCompletePolicy policy : policies)
|
||||
{
|
||||
policy.onCopyComplete(typeQName, sourceNodeRef, destinationNodeRef, copiedNodeRefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeQName
|
||||
* @param sourceNodeRef
|
||||
* @param destinationNodeRef
|
||||
* @param copiedNodeRefs
|
||||
*/
|
||||
private void defaultOnCopyComplete(
|
||||
QName typeQName,
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationNodeRef,
|
||||
Map<NodeRef, NodeRef> copiedNodeRefs)
|
||||
{
|
||||
ClassDefinition classDefinition = this.dictionaryService.getClass(typeQName);
|
||||
if (classDefinition != null)
|
||||
{
|
||||
// Check the properties
|
||||
Map<QName,PropertyDefinition> propertyDefinitions = classDefinition.getProperties();
|
||||
for (Map.Entry<QName,PropertyDefinition> entry : propertyDefinitions.entrySet())
|
||||
{
|
||||
QName propertyTypeDefinition = entry.getValue().getDataType().getName();
|
||||
if (DataTypeDefinition.NODE_REF.equals(propertyTypeDefinition) == true ||
|
||||
DataTypeDefinition.ANY.equals(propertyTypeDefinition) == true)
|
||||
{
|
||||
// Re-set the node ref so that it is still relative (if appropriate)
|
||||
Serializable value = this.nodeService.getProperty(destinationNodeRef, entry.getKey());
|
||||
if (value != null && value instanceof NodeRef)
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef)value;
|
||||
if (copiedNodeRefs.containsKey(nodeRef) == true)
|
||||
{
|
||||
NodeRef copiedNodeRef = copiedNodeRefs.get(nodeRef);
|
||||
this.nodeService.setProperty(destinationNodeRef, entry.getKey(), copiedNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the associations (child and target)
|
||||
Map<QName, AssociationDefinition> assocDefs = classDefinition.getAssociations();
|
||||
|
||||
// TODO: Need way of getting child assocs of a given type
|
||||
List<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(destinationNodeRef);
|
||||
for (ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(childAssocRef.getTypeQName()) &&
|
||||
childAssocRef.isPrimary() == false &&
|
||||
copiedNodeRefs.containsKey(childAssocRef.getChildRef()) == true)
|
||||
{
|
||||
// Remove the assoc and re-point to the new node
|
||||
this.nodeService.removeChild(destinationNodeRef, childAssocRef.getChildRef());
|
||||
this.nodeService.addChild(
|
||||
destinationNodeRef,
|
||||
copiedNodeRefs.get(childAssocRef.getChildRef()) ,
|
||||
childAssocRef.getTypeQName(),
|
||||
childAssocRef.getQName());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Need way of getting assocs of a given type
|
||||
List<AssociationRef> nodeAssocRefs = this.nodeService.getTargetAssocs(destinationNodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
for (AssociationRef nodeAssocRef : nodeAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(nodeAssocRef.getTypeQName()) &&
|
||||
copiedNodeRefs.containsKey(nodeAssocRef.getTargetRef()) == true)
|
||||
{
|
||||
// Remove the assoc and re-point to the new node
|
||||
this.nodeService.removeAssociation(
|
||||
destinationNodeRef,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName());
|
||||
this.nodeService.createAssociation(
|
||||
destinationNodeRef,
|
||||
copiedNodeRefs.get(nodeAssocRef.getTargetRef()),
|
||||
nodeAssocRef.getTypeQName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive copy algorithm
|
||||
*
|
||||
* @param sourceNodeRef
|
||||
* @param destinationParent
|
||||
* @param destinationAssocTypeQName
|
||||
* @param destinationQName
|
||||
* @param copyChildren
|
||||
* @param copiedChildren
|
||||
* @return
|
||||
*/
|
||||
private NodeRef recursiveCopy(
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationParent,
|
||||
QName destinationAssocTypeQName,
|
||||
QName destinationQName,
|
||||
boolean copyChildren,
|
||||
Map<NodeRef, NodeRef> copiedChildren)
|
||||
{
|
||||
// Extract Type Definition
|
||||
QName sourceTypeRef = this.nodeService.getType(sourceNodeRef);
|
||||
TypeDefinition typeDef = dictionaryService.getType(sourceTypeRef);
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new InvalidTypeException(sourceTypeRef);
|
||||
}
|
||||
|
||||
// Establish the scope of the copy
|
||||
PolicyScope copyDetails = getCopyDetails(sourceNodeRef, destinationParent.getStoreRef(), true);
|
||||
|
||||
// Create collection of properties for type and mandatory aspects
|
||||
Map<QName, Serializable> typeProps = copyDetails.getProperties();
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
if (typeProps != null)
|
||||
{
|
||||
properties.putAll(typeProps);
|
||||
}
|
||||
for (AspectDefinition aspectDef : typeDef.getDefaultAspects())
|
||||
{
|
||||
Map<QName, Serializable> aspectProps = copyDetails.getProperties(aspectDef.getName());
|
||||
if (aspectProps != null)
|
||||
{
|
||||
properties.putAll(aspectProps);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new node
|
||||
ChildAssociationRef destinationChildAssocRef = this.nodeService.createNode(
|
||||
destinationParent,
|
||||
destinationAssocTypeQName,
|
||||
destinationQName,
|
||||
sourceTypeRef,
|
||||
properties);
|
||||
NodeRef destinationNodeRef = destinationChildAssocRef.getChildRef();
|
||||
copiedChildren.put(sourceNodeRef, destinationNodeRef);
|
||||
|
||||
// Prevent any rules being fired on the new destination node
|
||||
this.ruleService.disableRules(destinationNodeRef);
|
||||
try
|
||||
{
|
||||
// Apply the copy aspect to the new node
|
||||
Map<QName, Serializable> copyProperties = new HashMap<QName, Serializable>();
|
||||
copyProperties.put(ContentModel.PROP_COPY_REFERENCE, sourceNodeRef);
|
||||
this.nodeService.addAspect(destinationNodeRef, ContentModel.ASPECT_COPIEDFROM, copyProperties);
|
||||
|
||||
// Copy the aspects
|
||||
copyAspects(destinationNodeRef, copyDetails);
|
||||
|
||||
// Copy the associations
|
||||
copyAssociations(destinationNodeRef, copyDetails, copyChildren, copiedChildren);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.ruleService.enableRules(destinationNodeRef);
|
||||
}
|
||||
|
||||
return destinationNodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the copy details. This calls the appropriate policies that have been registered
|
||||
* against the node and aspect types in order to pick-up any type specific copy behaviour.
|
||||
* <p>
|
||||
* If no policies for a type are registered then the default copy takes place which will
|
||||
* copy all properties and associations in the ususal manner.
|
||||
*
|
||||
* @param sourceNodeRef the source node reference
|
||||
* @return the copy details
|
||||
*/
|
||||
private PolicyScope getCopyDetails(NodeRef sourceNodeRef, StoreRef destinationStoreRef, boolean copyToNewNode)
|
||||
{
|
||||
QName sourceClassRef = this.nodeService.getType(sourceNodeRef);
|
||||
PolicyScope copyDetails = new PolicyScope(sourceClassRef);
|
||||
|
||||
// Invoke the onCopy behaviour
|
||||
invokeOnCopy(sourceClassRef, sourceNodeRef, destinationStoreRef, copyToNewNode, copyDetails);
|
||||
|
||||
// TODO What do we do aboout props and assocs that are on the node node but not part of the type definition?
|
||||
|
||||
// Get the source aspects
|
||||
Set<QName> sourceAspects = this.nodeService.getAspects(sourceNodeRef);
|
||||
for (QName sourceAspect : sourceAspects)
|
||||
{
|
||||
// Invoke the onCopy behaviour
|
||||
invokeOnCopy(sourceAspect, sourceNodeRef, destinationStoreRef, copyToNewNode, copyDetails);
|
||||
}
|
||||
|
||||
return copyDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the correct onCopy behaviour
|
||||
*
|
||||
* @param sourceClassRef source class reference
|
||||
* @param sourceNodeRef source node reference
|
||||
* @param copyDetails the copy details
|
||||
*/
|
||||
private void invokeOnCopy(
|
||||
QName sourceClassRef,
|
||||
NodeRef sourceNodeRef,
|
||||
StoreRef destinationStoreRef,
|
||||
boolean copyToNewNode,
|
||||
PolicyScope copyDetails)
|
||||
{
|
||||
Collection<CopyServicePolicies.OnCopyNodePolicy> policies = this.onCopyNodeDelegate.getList(sourceClassRef);
|
||||
if (policies.isEmpty() == true)
|
||||
{
|
||||
defaultOnCopy(sourceClassRef, sourceNodeRef, copyDetails);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (CopyServicePolicies.OnCopyNodePolicy policy : policies)
|
||||
{
|
||||
policy.onCopyNode(sourceClassRef, sourceNodeRef, destinationStoreRef, copyToNewNode, copyDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of on copy, used when there is no policy specified for a class.
|
||||
*
|
||||
* @param classRef the class reference of the node being copied
|
||||
* @param sourceNodeRef the source node reference
|
||||
* @param copyDetails details of the state being copied
|
||||
*/
|
||||
private void defaultOnCopy(QName classRef, NodeRef sourceNodeRef, PolicyScope copyDetails)
|
||||
{
|
||||
ClassDefinition classDefinition = this.dictionaryService.getClass(classRef);
|
||||
if (classDefinition != null)
|
||||
{
|
||||
// Copy the properties
|
||||
Map<QName,PropertyDefinition> propertyDefinitions = classDefinition.getProperties();
|
||||
for (QName propertyName : propertyDefinitions.keySet())
|
||||
{
|
||||
Serializable propValue = this.nodeService.getProperty(sourceNodeRef, propertyName);
|
||||
copyDetails.addProperty(classDefinition.getName(), propertyName, propValue);
|
||||
}
|
||||
|
||||
// Copy the associations (child and target)
|
||||
Map<QName, AssociationDefinition> assocDefs = classDefinition.getAssociations();
|
||||
|
||||
// TODO: Need way of getting child assocs of a given type
|
||||
if (classDefinition.isContainer())
|
||||
{
|
||||
List<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(sourceNodeRef);
|
||||
for (ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(childAssocRef.getTypeQName()))
|
||||
{
|
||||
copyDetails.addChildAssociation(classDefinition.getName(), childAssocRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Need way of getting assocs of a given type
|
||||
List<AssociationRef> nodeAssocRefs = this.nodeService.getTargetAssocs(sourceNodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
for (AssociationRef nodeAssocRef : nodeAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(nodeAssocRef.getTypeQName()))
|
||||
{
|
||||
copyDetails.addAssociation(classDefinition.getName(), nodeAssocRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the properties for the node type onto the destination node.
|
||||
*
|
||||
* @param destinationNodeRef the destintaion node reference
|
||||
* @param copyDetails the copy details
|
||||
*/
|
||||
private void copyProperties(NodeRef destinationNodeRef, PolicyScope copyDetails)
|
||||
{
|
||||
Map<QName, Serializable> props = copyDetails.getProperties();
|
||||
if (props != null)
|
||||
{
|
||||
for (QName propName : props.keySet())
|
||||
{
|
||||
this.nodeService.setProperty(destinationNodeRef, propName, props.get(propName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the aspects (thus copying the associated properties) onto the destination node
|
||||
*
|
||||
* @param destinationNodeRef the destination node reference
|
||||
* @param copyDetails the copy details
|
||||
*/
|
||||
private void copyAspects(NodeRef destinationNodeRef, PolicyScope copyDetails)
|
||||
{
|
||||
Set<QName> apects = copyDetails.getAspects();
|
||||
for (QName aspect : apects)
|
||||
{
|
||||
if (this.nodeService.hasAspect(destinationNodeRef, aspect) == false)
|
||||
{
|
||||
// Add the aspect to the node
|
||||
this.nodeService.addAspect(
|
||||
destinationNodeRef,
|
||||
aspect,
|
||||
copyDetails.getProperties(aspect));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set each property on the destination node since the aspect has already been applied
|
||||
Map<QName, Serializable> aspectProps = copyDetails.getProperties(aspect);
|
||||
if (aspectProps != null)
|
||||
{
|
||||
for (Map.Entry<QName, Serializable> entry : aspectProps.entrySet())
|
||||
{
|
||||
this.nodeService.setProperty(destinationNodeRef, entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the associations (child and target) for the node type and aspects onto the
|
||||
* destination node.
|
||||
* <p>
|
||||
* If copyChildren is true then all child nodes of primary child associations are copied
|
||||
* before they are associatied with the destination node.
|
||||
*
|
||||
* @param destinationNodeRef the destination node reference
|
||||
* @param copyDetails the copy details
|
||||
* @param copyChildren indicates whether the primary children are copied or not
|
||||
* @param copiedChildren set of children already copied
|
||||
*/
|
||||
private void copyAssociations(
|
||||
NodeRef destinationNodeRef,
|
||||
PolicyScope copyDetails,
|
||||
boolean copyChildren,
|
||||
Map<NodeRef, NodeRef> copiedChildren)
|
||||
{
|
||||
QName classRef = this.nodeService.getType(destinationNodeRef);
|
||||
copyChildAssociations(classRef, destinationNodeRef, copyDetails, copyChildren, copiedChildren);
|
||||
copyTargetAssociations(classRef, destinationNodeRef, copyDetails);
|
||||
|
||||
Set<QName> apects = copyDetails.getAspects();
|
||||
for (QName aspect : apects)
|
||||
{
|
||||
if (this.nodeService.hasAspect(destinationNodeRef, aspect) == false)
|
||||
{
|
||||
// Error since the aspect has not been added to the destination node (should never happen)
|
||||
throw new CopyServiceException("The aspect has not been added to the destination node.");
|
||||
}
|
||||
|
||||
copyChildAssociations(aspect, destinationNodeRef, copyDetails, copyChildren, copiedChildren);
|
||||
copyTargetAssociations(aspect, destinationNodeRef, copyDetails);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the target associations onto the destination node reference.
|
||||
*
|
||||
* @param classRef the class reference
|
||||
* @param destinationNodeRef the destination node reference
|
||||
* @param copyDetails the copy details
|
||||
*/
|
||||
private void copyTargetAssociations(QName classRef, NodeRef destinationNodeRef, PolicyScope copyDetails)
|
||||
{
|
||||
List<AssociationRef> nodeAssocRefs = copyDetails.getAssociations(classRef);
|
||||
if (nodeAssocRefs != null)
|
||||
{
|
||||
for (AssociationRef assocRef : nodeAssocRefs)
|
||||
{
|
||||
// Add the association
|
||||
NodeRef targetRef = assocRef.getTargetRef();
|
||||
this.nodeService.createAssociation(destinationNodeRef, targetRef, assocRef.getTypeQName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the child associations onto the destiantion node reference.
|
||||
* <p>
|
||||
* If copyChildren is true then the nodes at the end of a primary assoc will be copied before they
|
||||
* are associated.
|
||||
*
|
||||
* @param classRef the class reference
|
||||
* @param destinationNodeRef the destination node reference
|
||||
* @param copyDetails the copy details
|
||||
* @param copyChildren indicates whether to copy the primary children
|
||||
*/
|
||||
private void copyChildAssociations(
|
||||
QName classRef,
|
||||
NodeRef destinationNodeRef,
|
||||
PolicyScope copyDetails,
|
||||
boolean copyChildren,
|
||||
Map<NodeRef, NodeRef> copiedChildren)
|
||||
{
|
||||
List<ChildAssociationRef> childAssocs = copyDetails.getChildAssociations(classRef);
|
||||
if (childAssocs != null)
|
||||
{
|
||||
for (ChildAssociationRef childAssoc : childAssocs)
|
||||
{
|
||||
if (copyChildren == true)
|
||||
{
|
||||
if (childAssoc.isPrimary() == true)
|
||||
{
|
||||
// Do not recurse further, if we've already copied this node
|
||||
if (copiedChildren.containsKey(childAssoc.getChildRef()) == false &&
|
||||
copiedChildren.containsValue(childAssoc.getChildRef()) == false)
|
||||
{
|
||||
// Copy the child
|
||||
recursiveCopy(
|
||||
childAssoc.getChildRef(),
|
||||
destinationNodeRef,
|
||||
childAssoc.getTypeQName(),
|
||||
childAssoc.getQName(),
|
||||
copyChildren,
|
||||
copiedChildren);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the child
|
||||
NodeRef childRef = childAssoc.getChildRef();
|
||||
this.nodeService.addChild(destinationNodeRef, childRef, childAssoc.getTypeQName(), childAssoc.getQName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeRef childRef = childAssoc.getChildRef();
|
||||
QName childType = this.nodeService.getType(childRef);
|
||||
|
||||
// TODO will need to remove this reference to the configurations association
|
||||
if (this.dictionaryService.isSubClass(childType, ContentModel.TYPE_CONFIGURATIONS) == true ||
|
||||
copyDetails.isChildAssociationRefAlwaysTraversed(classRef, childAssoc) == true)
|
||||
{
|
||||
if (copiedChildren.containsKey(childRef) == false)
|
||||
{
|
||||
// Always recursivly copy configuration folders
|
||||
recursiveCopy(
|
||||
childRef,
|
||||
destinationNodeRef,
|
||||
childAssoc.getTypeQName(),
|
||||
childAssoc.getQName(),
|
||||
true,
|
||||
copiedChildren);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the child (will not be primary reguardless of its origional state)
|
||||
this.nodeService.addChild(destinationNodeRef, childRef, childAssoc.getTypeQName(), childAssoc.getQName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer to the standard implementation with copyChildren set to false
|
||||
*
|
||||
* @see com.activiti.repo.node.copy.NodeCopyService#copy(com.activiti.repo.ref.NodeRef, com.activiti.repo.ref.NodeRef, com.activiti.repo.ref.QName)
|
||||
*/
|
||||
public NodeRef copy(
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationParent,
|
||||
QName destinationAssocTypeQName,
|
||||
QName destinationQName)
|
||||
{
|
||||
return copy(
|
||||
sourceNodeRef,
|
||||
destinationParent,
|
||||
destinationAssocTypeQName,
|
||||
destinationQName,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.activiti.repo.node.copy.NodeCopyService#copy(com.activiti.repo.ref.NodeRef, com.activiti.repo.ref.NodeRef)
|
||||
*/
|
||||
public void copy(
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationNodeRef)
|
||||
{
|
||||
// Check that the source and destination node are the same type
|
||||
if (this.nodeService.getType(sourceNodeRef).equals(this.nodeService.getType(destinationNodeRef)) == false)
|
||||
{
|
||||
// Error - can not copy objects that are of different types
|
||||
throw new CopyServiceException("The source and destination node must be the same type.");
|
||||
}
|
||||
|
||||
// Get the copy details
|
||||
PolicyScope copyDetails = getCopyDetails(sourceNodeRef, destinationNodeRef.getStoreRef(), false);
|
||||
|
||||
// Copy over the top of the destination node
|
||||
copyProperties(destinationNodeRef, copyDetails);
|
||||
copyAspects(destinationNodeRef, copyDetails);
|
||||
copyAssociations(destinationNodeRef, copyDetails, false, new HashMap<NodeRef, NodeRef>());
|
||||
}
|
||||
|
||||
/**
|
||||
* OnCopy behaviour registered for the copy aspect.
|
||||
* <p>
|
||||
* Doing nothing in this behaviour ensures that the copy aspect found on the source node does not get
|
||||
* copied onto the destination node.
|
||||
*
|
||||
* @param sourceClassRef the source class reference
|
||||
* @param sourceNodeRef the source node reference
|
||||
* @param copyDetails the copy details
|
||||
*/
|
||||
public void copyAspectOnCopy(
|
||||
QName classRef,
|
||||
NodeRef sourceNodeRef,
|
||||
StoreRef destinationStoreRef,
|
||||
boolean copyToNewNode,
|
||||
PolicyScope copyDetails)
|
||||
{
|
||||
// Do nothing. This will ensure that copy aspect on the source node does not get copied onto
|
||||
// the destination node.
|
||||
}
|
||||
|
||||
public void onCopyComplete(
|
||||
QName classRef,
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationRef,
|
||||
Map<NodeRef, NodeRef> copyMap)
|
||||
{
|
||||
// Do nothing since we do not want the copy from aspect to be relative to the copied nodes
|
||||
}
|
||||
}
|
707
source/java/org/alfresco/repo/copy/CopyServiceImplTest.java
Normal file
707
source/java/org/alfresco/repo/copy/CopyServiceImplTest.java
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.copy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.evaluator.NoConditionEvaluator;
|
||||
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
|
||||
import org.alfresco.repo.action.executer.CopyActionExecuter;
|
||||
import org.alfresco.repo.action.executer.MoveActionExecuter;
|
||||
import org.alfresco.repo.dictionary.DictionaryDAO;
|
||||
import org.alfresco.repo.dictionary.M2Aspect;
|
||||
import org.alfresco.repo.dictionary.M2Association;
|
||||
import org.alfresco.repo.dictionary.M2ChildAssociation;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.dictionary.M2Property;
|
||||
import org.alfresco.repo.dictionary.M2Type;
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.debug.NodeStoreInspector;
|
||||
|
||||
/**
|
||||
* Node operations service unit tests
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class CopyServiceImplTest extends BaseSpringTest
|
||||
{
|
||||
/**
|
||||
* Services used by the tests
|
||||
*/
|
||||
private NodeService nodeService;
|
||||
private CopyService copyService;
|
||||
private DictionaryDAO dictionaryDAO;
|
||||
private ContentService contentService;
|
||||
private RuleService ruleService;
|
||||
private ActionService actionService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
/**
|
||||
* Data used by the tests
|
||||
*/
|
||||
private StoreRef storeRef;
|
||||
private NodeRef sourceNodeRef;
|
||||
private NodeRef rootNodeRef;
|
||||
private NodeRef targetNodeRef;
|
||||
private NodeRef nonPrimaryChildNodeRef;
|
||||
private NodeRef childNodeRef;
|
||||
private NodeRef destinationNodeRef;
|
||||
|
||||
/**
|
||||
* Types and properties used by the tests
|
||||
*/
|
||||
private static final String TEST_TYPE_NAMESPACE = "testTypeNamespaceURI";
|
||||
private static final QName TEST_TYPE_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "testType");
|
||||
private static final QName PROP1_QNAME_MANDATORY = QName.createQName(TEST_TYPE_NAMESPACE, "prop1Mandatory");
|
||||
private static final QName PROP2_QNAME_OPTIONAL = QName.createQName(TEST_TYPE_NAMESPACE, "prop2Optional");
|
||||
|
||||
private static final QName TEST_ASPECT_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "testAspect");
|
||||
private static final QName PROP3_QNAME_MANDATORY = QName.createQName(TEST_TYPE_NAMESPACE, "prop3Mandatory");
|
||||
private static final QName PROP4_QNAME_OPTIONAL = QName.createQName(TEST_TYPE_NAMESPACE, "prop4Optional");
|
||||
|
||||
private static final QName PROP_QNAME_MY_NODE_REF = QName.createQName(TEST_TYPE_NAMESPACE, "myNodeRef");
|
||||
private static final QName PROP_QNAME_MY_ANY = QName.createQName(TEST_TYPE_NAMESPACE, "myAny");
|
||||
|
||||
private static final QName TEST_MANDATORY_ASPECT_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "testMandatoryAspect");
|
||||
private static final QName PROP5_QNAME_MANDATORY = QName.createQName(TEST_TYPE_NAMESPACE, "prop5Mandatory");
|
||||
|
||||
private static final String TEST_VALUE_1 = "testValue1";
|
||||
private static final String TEST_VALUE_2 = "testValue2";
|
||||
private static final String TEST_VALUE_3 = "testValue3";
|
||||
|
||||
private static final QName TEST_CHILD_ASSOC_TYPE_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "contains");
|
||||
private static final QName TEST_CHILD_ASSOC_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "testChildAssocName");
|
||||
private static final QName TEST_ASSOC_TYPE_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "testAssocName");
|
||||
private static final QName TEST_CHILD_ASSOC_QNAME2 = QName.createQName(TEST_TYPE_NAMESPACE, "testChildAssocName2");
|
||||
|
||||
private static final ContentData CONTENT_DATA_TEXT = new ContentData(null, "text/plain", 0L, "UTF-8");
|
||||
|
||||
/**
|
||||
* Test content
|
||||
*/
|
||||
private static final String SOME_CONTENT = "This is some content ...";
|
||||
|
||||
/**
|
||||
* Sets the meta model DAO
|
||||
*
|
||||
* @param dictionaryDAO the meta model DAO
|
||||
*/
|
||||
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
|
||||
{
|
||||
this.dictionaryDAO = dictionaryDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
* On setup in transaction implementation
|
||||
*/
|
||||
@Override
|
||||
protected void onSetUpInTransaction()
|
||||
throws Exception
|
||||
{
|
||||
// Set the services
|
||||
this.nodeService = (NodeService)this.applicationContext.getBean("dbNodeService");
|
||||
this.copyService = (CopyService)this.applicationContext.getBean("copyService");
|
||||
this.contentService = (ContentService)this.applicationContext.getBean("contentService");
|
||||
this.ruleService = (RuleService)this.applicationContext.getBean("ruleService");
|
||||
this.actionService = (ActionService)this.applicationContext.getBean("actionService");
|
||||
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
|
||||
|
||||
this.authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// Create the test model
|
||||
createTestModel();
|
||||
|
||||
// Create the store and get the root node reference
|
||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(storeRef);
|
||||
|
||||
// Create the node used for copying
|
||||
ChildAssociationRef childAssocRef = this.nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}test"),
|
||||
TEST_TYPE_QNAME,
|
||||
createTypePropertyBag());
|
||||
this.sourceNodeRef = childAssocRef.getChildRef();
|
||||
|
||||
// Create another bag of properties
|
||||
Map<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>();
|
||||
aspectProperties.put(PROP3_QNAME_MANDATORY, TEST_VALUE_1);
|
||||
aspectProperties.put(PROP4_QNAME_OPTIONAL, TEST_VALUE_2);
|
||||
|
||||
// Apply the test aspect
|
||||
this.nodeService.addAspect(
|
||||
this.sourceNodeRef,
|
||||
TEST_ASPECT_QNAME,
|
||||
aspectProperties);
|
||||
|
||||
this.nodeService.addAspect(sourceNodeRef, ContentModel.ASPECT_TITLED, null);
|
||||
|
||||
// Add a child
|
||||
ChildAssociationRef temp3 =this.nodeService.createNode(
|
||||
this.sourceNodeRef,
|
||||
TEST_CHILD_ASSOC_TYPE_QNAME,
|
||||
TEST_CHILD_ASSOC_QNAME,
|
||||
TEST_TYPE_QNAME,
|
||||
createTypePropertyBag());
|
||||
this.childNodeRef = temp3.getChildRef();
|
||||
|
||||
// Add a child that is primary
|
||||
ChildAssociationRef temp2 = this.nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testNonPrimaryChild"),
|
||||
TEST_TYPE_QNAME,
|
||||
createTypePropertyBag());
|
||||
|
||||
this.nonPrimaryChildNodeRef = temp2.getChildRef();
|
||||
this.nodeService.addChild(
|
||||
this.sourceNodeRef,
|
||||
this.nonPrimaryChildNodeRef,
|
||||
TEST_CHILD_ASSOC_TYPE_QNAME,
|
||||
TEST_CHILD_ASSOC_QNAME2);
|
||||
|
||||
// Add a target assoc
|
||||
ChildAssociationRef temp = this.nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testAssoc"),
|
||||
TEST_TYPE_QNAME,
|
||||
createTypePropertyBag());
|
||||
this.targetNodeRef = temp.getChildRef();
|
||||
this.nodeService.createAssociation(this.sourceNodeRef, this.targetNodeRef, TEST_ASSOC_TYPE_QNAME);
|
||||
|
||||
// Create a node we can use as the destination in a copy
|
||||
Map<QName, Serializable> destinationProps = new HashMap<QName, Serializable>();
|
||||
destinationProps.put(PROP1_QNAME_MANDATORY, TEST_VALUE_1);
|
||||
destinationProps.put(PROP5_QNAME_MANDATORY, TEST_VALUE_3);
|
||||
destinationProps.put(ContentModel.PROP_CONTENT, CONTENT_DATA_TEXT);
|
||||
ChildAssociationRef temp5 = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testDestinationNode"),
|
||||
TEST_TYPE_QNAME,
|
||||
destinationProps);
|
||||
this.destinationNodeRef = temp5.getChildRef();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTearDownInTransaction()
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
super.onTearDownInTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates a bag of properties for the test type
|
||||
*
|
||||
* @return bag of properties
|
||||
*/
|
||||
private Map<QName, Serializable> createTypePropertyBag()
|
||||
{
|
||||
Map<QName, Serializable> result = new HashMap<QName, Serializable>();
|
||||
result.put(PROP1_QNAME_MANDATORY, TEST_VALUE_1);
|
||||
result.put(PROP2_QNAME_OPTIONAL, TEST_VALUE_2);
|
||||
result.put(PROP5_QNAME_MANDATORY, TEST_VALUE_3);
|
||||
result.put(ContentModel.PROP_CONTENT, CONTENT_DATA_TEXT);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the test model used by the tests
|
||||
*/
|
||||
private void createTestModel()
|
||||
{
|
||||
M2Model model = M2Model.createModel("test:nodeoperations");
|
||||
model.createNamespace(TEST_TYPE_NAMESPACE, "test");
|
||||
model.createImport(NamespaceService.DICTIONARY_MODEL_1_0_URI, NamespaceService.DICTIONARY_MODEL_PREFIX);
|
||||
model.createImport(NamespaceService.SYSTEM_MODEL_1_0_URI, NamespaceService.SYSTEM_MODEL_PREFIX);
|
||||
model.createImport(NamespaceService.CONTENT_MODEL_1_0_URI, NamespaceService.CONTENT_MODEL_PREFIX);
|
||||
|
||||
M2Type testType = model.createType("test:" + TEST_TYPE_QNAME.getLocalName());
|
||||
testType.setParentName("cm:" + ContentModel.TYPE_CONTENT.getLocalName());
|
||||
|
||||
M2Property prop1 = testType.createProperty("test:" + PROP1_QNAME_MANDATORY.getLocalName());
|
||||
prop1.setMandatory(true);
|
||||
prop1.setType("d:" + DataTypeDefinition.TEXT.getLocalName());
|
||||
prop1.setMultiValued(false);
|
||||
|
||||
M2Property prop2 = testType.createProperty("test:" + PROP2_QNAME_OPTIONAL.getLocalName());
|
||||
prop2.setMandatory(false);
|
||||
prop2.setType("d:" + DataTypeDefinition.TEXT.getLocalName());
|
||||
prop2.setMandatory(false);
|
||||
|
||||
M2Property propNodeRef = testType.createProperty("test:" + PROP_QNAME_MY_NODE_REF.getLocalName());
|
||||
propNodeRef.setMandatory(false);
|
||||
propNodeRef.setType("d:" + DataTypeDefinition.NODE_REF.getLocalName());
|
||||
propNodeRef.setMandatory(false);
|
||||
|
||||
M2Property propAnyNodeRef = testType.createProperty("test:" + PROP_QNAME_MY_ANY.getLocalName());
|
||||
propAnyNodeRef.setMandatory(false);
|
||||
propAnyNodeRef.setType("d:" + DataTypeDefinition.ANY.getLocalName());
|
||||
propAnyNodeRef.setMandatory(false);
|
||||
|
||||
M2ChildAssociation childAssoc = testType.createChildAssociation("test:" + TEST_CHILD_ASSOC_TYPE_QNAME.getLocalName());
|
||||
childAssoc.setTargetClassName("sys:base");
|
||||
childAssoc.setTargetMandatory(false);
|
||||
|
||||
M2Association assoc = testType.createAssociation("test:" + TEST_ASSOC_TYPE_QNAME.getLocalName());
|
||||
assoc.setTargetClassName("sys:base");
|
||||
assoc.setTargetMandatory(false);
|
||||
|
||||
M2Aspect testAspect = model.createAspect("test:" + TEST_ASPECT_QNAME.getLocalName());
|
||||
|
||||
M2Property prop3 = testAspect.createProperty("test:" + PROP3_QNAME_MANDATORY.getLocalName());
|
||||
prop3.setMandatory(true);
|
||||
prop3.setType("d:" + DataTypeDefinition.TEXT.getLocalName());
|
||||
prop3.setMultiValued(false);
|
||||
|
||||
M2Property prop4 = testAspect.createProperty("test:" + PROP4_QNAME_OPTIONAL.getLocalName());
|
||||
prop4.setMandatory(false);
|
||||
prop4.setType("d:" + DataTypeDefinition.TEXT.getLocalName());
|
||||
prop4.setMultiValued(false);
|
||||
|
||||
M2Aspect testMandatoryAspect = model.createAspect("test:" + TEST_MANDATORY_ASPECT_QNAME.getLocalName());
|
||||
M2Property prop5 = testMandatoryAspect.createProperty("test:" + PROP5_QNAME_MANDATORY.getLocalName());
|
||||
prop5.setType("d:" + DataTypeDefinition.TEXT.getLocalName());
|
||||
prop5.setMandatory(true);
|
||||
|
||||
testType.addMandatoryAspect("test:" + TEST_MANDATORY_ASPECT_QNAME.getLocalName());
|
||||
|
||||
dictionaryDAO.putModel(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test copy new node within store
|
||||
*/
|
||||
public void testCopyToNewNode()
|
||||
{
|
||||
// Copy to new node without copying children
|
||||
NodeRef copy = this.copyService.copy(
|
||||
this.sourceNodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}copyAssoc"));
|
||||
checkCopiedNode(this.sourceNodeRef, copy, true, true, false);
|
||||
|
||||
// Copy to new node, copying children
|
||||
NodeRef copy2 = this.copyService.copy(
|
||||
this.sourceNodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}copyAssoc"),
|
||||
true);
|
||||
checkCopiedNode(this.sourceNodeRef, copy2, true, true, true);
|
||||
|
||||
// Check that a copy of a copy works correctly
|
||||
NodeRef copyOfCopy = this.copyService.copy(
|
||||
copy,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}copyOfCopy"));
|
||||
checkCopiedNode(copy, copyOfCopy, true, true, false);
|
||||
|
||||
// TODO check copying from a versioned copy
|
||||
// TODO check copying from a lockable copy
|
||||
|
||||
// Check copying from a node with content
|
||||
ContentWriter contentWriter = this.contentService.getWriter(this.sourceNodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.putContent(SOME_CONTENT);
|
||||
NodeRef copyWithContent = this.copyService.copy(
|
||||
this.sourceNodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}copyWithContent"));
|
||||
checkCopiedNode(this.sourceNodeRef, copyWithContent, true, true, false);
|
||||
ContentReader contentReader = this.contentService.getReader(copyWithContent, ContentModel.PROP_CONTENT);
|
||||
assertNotNull(contentReader);
|
||||
assertEquals(SOME_CONTENT, contentReader.getContentString());
|
||||
|
||||
// TODO check copying to a different store
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
}
|
||||
|
||||
public void testCopyNodeWithRules()
|
||||
{
|
||||
// Create a new rule and add it to the source noderef
|
||||
Rule rule = this.ruleService.createRule(RuleType.INBOUND);
|
||||
|
||||
Map<String, Serializable> props = new HashMap<String, Serializable>(1);
|
||||
props.put(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
|
||||
Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME, props);
|
||||
rule.addAction(action);
|
||||
|
||||
ActionCondition actionCondition = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
|
||||
rule.addActionCondition(actionCondition);
|
||||
|
||||
this.ruleService.saveRule(this.sourceNodeRef, rule);
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
//System.out.println(" ------------------------------ ");
|
||||
|
||||
// Now copy the node that has rules associated with it
|
||||
NodeRef copy = this.copyService.copy(
|
||||
this.sourceNodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}withRulesCopy"),
|
||||
true);
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
|
||||
checkCopiedNode(this.sourceNodeRef, copy, true, true, true);
|
||||
|
||||
//assertTrue(this.configurableService.isConfigurable(copy));
|
||||
//assertNotNull(this.configurableService.getConfigurationFolder(copy));
|
||||
//assertFalse(this.configurableService.getConfigurationFolder(this.sourceNodeRef) == this.configurableService.getConfigurationFolder(copy));
|
||||
|
||||
assertTrue(this.nodeService.hasAspect(copy, RuleModel.ASPECT_RULES));
|
||||
assertTrue(this.ruleService.hasRules(copy));
|
||||
assertTrue(this.ruleService.rulesEnabled(copy));
|
||||
List<Rule> copiedRules = this.ruleService.getRules(copy);
|
||||
assertEquals(1, copiedRules.size());
|
||||
Rule copiedRule = copiedRules.get(0);
|
||||
assertFalse(rule.getId() == copiedRule.getId());
|
||||
assertEquals(rule.getAction(0).getActionDefinitionName(), copiedRule.getAction(0).getActionDefinitionName());
|
||||
|
||||
// Now copy the node without copying the children and check that the rules have been copied
|
||||
NodeRef copy2 = this.copyService.copy(
|
||||
this.sourceNodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}withRuleCopyNoChildren"),
|
||||
false);
|
||||
|
||||
// System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
|
||||
checkCopiedNode(this.sourceNodeRef, copy2, true, true, false);
|
||||
|
||||
//assertTrue(this.configurableService.isConfigurable(copy2));
|
||||
//assertNotNull(this.configurableService.getConfigurationFolder(copy2));
|
||||
//assertFalse(this.configurableService.getConfigurationFolder(this.sourceNodeRef) == this.configurableService.getConfigurationFolder(copy2));
|
||||
|
||||
assertTrue(this.nodeService.hasAspect(copy2, RuleModel.ASPECT_RULES));
|
||||
assertTrue(this.ruleService.hasRules(copy2));
|
||||
assertTrue(this.ruleService.rulesEnabled(copy2));
|
||||
List<Rule> copiedRules2 = this.ruleService.getRules(copy2);
|
||||
assertEquals(1, copiedRules.size());
|
||||
Rule copiedRule2 = copiedRules2.get(0);
|
||||
assertFalse(rule.getId() == copiedRule2.getId());
|
||||
assertEquals(rule.getAction(0).getActionDefinitionName(), copiedRule2.getAction(0).getActionDefinitionName());
|
||||
}
|
||||
|
||||
public void testCopyToExistingNode()
|
||||
{
|
||||
// Copy nodes within the same store
|
||||
this.copyService.copy(this.sourceNodeRef, this.destinationNodeRef);
|
||||
checkCopiedNode(this.sourceNodeRef, this.destinationNodeRef, false, true, false);
|
||||
|
||||
// TODO check copying from a copy
|
||||
// TODO check copying from a versioned copy
|
||||
// TODO check copying from a lockable copy
|
||||
// TODO check copying from a node with content
|
||||
|
||||
// TODO check copying nodes between stores
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a potentially recursive copy
|
||||
*/
|
||||
public void testRecursiveCopy()
|
||||
{
|
||||
// Need to create a potentially recursive node structure
|
||||
NodeRef nodeOne = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
NodeRef nodeTwo = this.nodeService.createNode(
|
||||
nodeOne,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
NodeRef nodeThree = this.nodeService.createNode(
|
||||
nodeTwo,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||
|
||||
// Issue a potentialy recursive copy
|
||||
this.copyService.copy(nodeOne, nodeThree, ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN, true);
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that realtive links between nodes are restored once the copy is completed
|
||||
*/
|
||||
public void testRelativeLinks()
|
||||
{
|
||||
QName nodeOneAssocName = QName.createQName("{test}nodeOne");
|
||||
QName nodeTwoAssocName = QName.createQName("{test}nodeTwo");
|
||||
QName nodeThreeAssocName = QName.createQName("{test}nodeThree");
|
||||
QName nodeFourAssocName = QName.createQName("{test}nodeFour");
|
||||
|
||||
NodeRef nodeOne = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
nodeOneAssocName,
|
||||
TEST_TYPE_QNAME).getChildRef();
|
||||
NodeRef nodeTwo = this.nodeService.createNode(
|
||||
nodeOne,
|
||||
TEST_CHILD_ASSOC_TYPE_QNAME,
|
||||
nodeTwoAssocName,
|
||||
TEST_TYPE_QNAME).getChildRef();
|
||||
NodeRef nodeThree = this.nodeService.createNode(
|
||||
nodeTwo,
|
||||
TEST_CHILD_ASSOC_TYPE_QNAME,
|
||||
nodeThreeAssocName,
|
||||
TEST_TYPE_QNAME).getChildRef();
|
||||
NodeRef nodeFour = this.nodeService.createNode(
|
||||
nodeOne,
|
||||
TEST_CHILD_ASSOC_TYPE_QNAME,
|
||||
nodeFourAssocName,
|
||||
TEST_TYPE_QNAME).getChildRef();
|
||||
this.nodeService.addChild(nodeFour, nodeThree, TEST_CHILD_ASSOC_TYPE_QNAME, TEST_CHILD_ASSOC_QNAME);
|
||||
this.nodeService.createAssociation(nodeTwo, nodeThree, TEST_ASSOC_TYPE_QNAME);
|
||||
this.nodeService.setProperty(nodeOne, PROP_QNAME_MY_NODE_REF, nodeThree);
|
||||
this.nodeService.setProperty(nodeOne, PROP_QNAME_MY_ANY, nodeThree);
|
||||
|
||||
// Make node one actionable with a rule to copy nodes into node two
|
||||
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
||||
params.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, nodeTwo);
|
||||
params.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, TEST_CHILD_ASSOC_TYPE_QNAME);
|
||||
params.put(MoveActionExecuter.PARAM_ASSOC_QNAME, QName.createQName("{test}ruleCopy"));
|
||||
Rule rule = this.ruleService.createRule(RuleType.INBOUND);
|
||||
ActionCondition condition = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
|
||||
rule.addActionCondition(condition);
|
||||
Action action = this.actionService.createAction(CopyActionExecuter.NAME, params);
|
||||
rule.addAction(action);
|
||||
this.ruleService.saveRule(nodeOne, rule);
|
||||
|
||||
// Do a deep copy
|
||||
NodeRef nodeOneCopy = this.copyService.copy(nodeOne, this.rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}copiedNodeOne"), true);
|
||||
NodeRef nodeTwoCopy = null;
|
||||
NodeRef nodeThreeCopy = null;
|
||||
NodeRef nodeFourCopy = null;
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
|
||||
List<ChildAssociationRef> nodeOneCopyChildren = this.nodeService.getChildAssocs(nodeOneCopy);
|
||||
assertNotNull(nodeOneCopyChildren);
|
||||
assertEquals(3, nodeOneCopyChildren.size());
|
||||
for (ChildAssociationRef nodeOneCopyChild : nodeOneCopyChildren)
|
||||
{
|
||||
if (nodeOneCopyChild.getQName().equals(nodeTwoAssocName) == true)
|
||||
{
|
||||
nodeTwoCopy = nodeOneCopyChild.getChildRef();
|
||||
|
||||
List<ChildAssociationRef> nodeTwoCopyChildren = this.nodeService.getChildAssocs(nodeTwoCopy);
|
||||
assertNotNull(nodeTwoCopyChildren);
|
||||
assertEquals(1, nodeTwoCopyChildren.size());
|
||||
for (ChildAssociationRef nodeTwoCopyChild : nodeTwoCopyChildren)
|
||||
{
|
||||
if (nodeTwoCopyChild.getQName().equals(nodeThreeAssocName) == true)
|
||||
{
|
||||
nodeThreeCopy = nodeTwoCopyChild.getChildRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nodeOneCopyChild.getQName().equals(nodeFourAssocName) == true)
|
||||
{
|
||||
nodeFourCopy = nodeOneCopyChild.getChildRef();
|
||||
}
|
||||
}
|
||||
assertNotNull(nodeTwoCopy);
|
||||
assertNotNull(nodeThreeCopy);
|
||||
assertNotNull(nodeFourCopy);
|
||||
|
||||
// Check the non primary child assoc
|
||||
List<ChildAssociationRef> children = this.nodeService.getChildAssocs(
|
||||
nodeFourCopy,
|
||||
RegexQNamePattern.MATCH_ALL,
|
||||
TEST_CHILD_ASSOC_QNAME);
|
||||
assertNotNull(children);
|
||||
assertEquals(1, children.size());
|
||||
ChildAssociationRef child = children.get(0);
|
||||
assertEquals(child.getChildRef(), nodeThreeCopy);
|
||||
|
||||
// Check the node ref property
|
||||
NodeRef nodeRef = (NodeRef)this.nodeService.getProperty(nodeOneCopy, PROP_QNAME_MY_NODE_REF);
|
||||
assertNotNull(nodeRef);
|
||||
assertEquals(nodeThreeCopy, nodeRef);
|
||||
|
||||
// Check the any property
|
||||
NodeRef anyNodeRef = (NodeRef)this.nodeService.getProperty(nodeOneCopy, PROP_QNAME_MY_ANY);
|
||||
assertNotNull(anyNodeRef);
|
||||
assertEquals(nodeThreeCopy, anyNodeRef);
|
||||
|
||||
// Check the target assoc
|
||||
List<AssociationRef> assocs = this.nodeService.getTargetAssocs(nodeTwoCopy, TEST_ASSOC_TYPE_QNAME);
|
||||
assertNotNull(assocs);
|
||||
assertEquals(1, assocs.size());
|
||||
AssociationRef assoc = assocs.get(0);
|
||||
assertEquals(assoc.getTargetRef(), nodeThreeCopy);
|
||||
|
||||
// Check that the rule parameter values have been made relative
|
||||
List<Rule> rules = this.ruleService.getRules(nodeOneCopy);
|
||||
assertNotNull(rules);
|
||||
assertEquals(1, rules.size());
|
||||
Rule copiedRule = rules.get(0);
|
||||
assertNotNull(copiedRule);
|
||||
List<Action> ruleActions = copiedRule.getActions();
|
||||
assertNotNull(ruleActions);
|
||||
assertEquals(1, ruleActions.size());
|
||||
Action ruleAction = ruleActions.get(0);
|
||||
NodeRef value = (NodeRef)ruleAction.getParameterValue(MoveActionExecuter.PARAM_DESTINATION_FOLDER);
|
||||
assertNotNull(value);
|
||||
assertEquals(nodeTwoCopy, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the copied node contains the state we are expecting
|
||||
*
|
||||
* @param sourceNodeRef the source node reference
|
||||
* @param destinationNodeRef the destination node reference
|
||||
*/
|
||||
private void checkCopiedNode(NodeRef sourceNodeRef, NodeRef destinationNodeRef, boolean newCopy, boolean sameStore, boolean copyChildren)
|
||||
{
|
||||
if (newCopy == true)
|
||||
{
|
||||
if (sameStore == true)
|
||||
{
|
||||
// Check that the copy aspect has been applied to the copy
|
||||
boolean hasCopyAspect = this.nodeService.hasAspect(destinationNodeRef, ContentModel.ASPECT_COPIEDFROM);
|
||||
assertTrue(hasCopyAspect);
|
||||
NodeRef copyNodeRef = (NodeRef)this.nodeService.getProperty(destinationNodeRef, ContentModel.PROP_COPY_REFERENCE);
|
||||
assertNotNull(copyNodeRef);
|
||||
assertEquals(sourceNodeRef, copyNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check that destiantion has the same id as the source
|
||||
assertEquals(sourceNodeRef.getId(), destinationNodeRef.getId());
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasTestAspect = this.nodeService.hasAspect(destinationNodeRef, TEST_ASPECT_QNAME);
|
||||
assertTrue(hasTestAspect);
|
||||
|
||||
// Check that all the correct properties have been copied
|
||||
Map<QName, Serializable> destinationProperties = this.nodeService.getProperties(destinationNodeRef);
|
||||
assertNotNull(destinationProperties);
|
||||
String value1 = (String)destinationProperties.get(PROP1_QNAME_MANDATORY);
|
||||
assertNotNull(value1);
|
||||
assertEquals(TEST_VALUE_1, value1);
|
||||
String value2 = (String)destinationProperties.get(PROP2_QNAME_OPTIONAL);
|
||||
assertNotNull(value2);
|
||||
assertEquals(TEST_VALUE_2, value2);
|
||||
String value3 = (String)destinationProperties.get(PROP3_QNAME_MANDATORY);
|
||||
assertNotNull(value3);
|
||||
assertEquals(TEST_VALUE_1, value3);
|
||||
String value4 = (String)destinationProperties.get(PROP4_QNAME_OPTIONAL);
|
||||
assertNotNull(value4);
|
||||
assertEquals(TEST_VALUE_2, value4);
|
||||
|
||||
// Check all the target associations have been copied
|
||||
List<AssociationRef> destinationTargets = this.nodeService.getTargetAssocs(destinationNodeRef, TEST_ASSOC_TYPE_QNAME);
|
||||
assertNotNull(destinationTargets);
|
||||
assertEquals(1, destinationTargets.size());
|
||||
AssociationRef nodeAssocRef = destinationTargets.get(0);
|
||||
assertNotNull(nodeAssocRef);
|
||||
assertEquals(this.targetNodeRef, nodeAssocRef.getTargetRef());
|
||||
|
||||
// Check all the child associations have been copied
|
||||
List<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(destinationNodeRef);
|
||||
assertNotNull(childAssocRefs);
|
||||
int expectedSize = 2;
|
||||
if (this.nodeService.hasAspect(destinationNodeRef, RuleModel.ASPECT_RULES) == true)
|
||||
{
|
||||
expectedSize = expectedSize + 1;
|
||||
}
|
||||
|
||||
assertEquals(expectedSize, childAssocRefs.size());
|
||||
for (ChildAssociationRef ref : childAssocRefs)
|
||||
{
|
||||
if (ref.getQName().equals(TEST_CHILD_ASSOC_QNAME2) == true)
|
||||
{
|
||||
// Since this child is non-primary in the source it will always be non-primary in the destination
|
||||
assertFalse(ref.isPrimary());
|
||||
assertEquals(this.nonPrimaryChildNodeRef, ref.getChildRef());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (copyChildren == false)
|
||||
{
|
||||
if (ref.getTypeQName().equals(RuleModel.ASSOC_RULE_FOLDER) == true)
|
||||
{
|
||||
assertTrue(ref.isPrimary());
|
||||
assertTrue(this.childNodeRef.equals(ref.getChildRef()) == false);
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFalse(ref.isPrimary());
|
||||
assertEquals(this.childNodeRef, ref.getChildRef());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assertTrue(ref.isPrimary());
|
||||
assertTrue(this.childNodeRef.equals(ref.getChildRef()) == false);
|
||||
|
||||
// TODO need to check that the copied child has all the correct details ..
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
source/java/org/alfresco/repo/copy/CopyServicePolicies.java
Normal file
72
source/java/org/alfresco/repo/copy/CopyServicePolicies.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.copy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.policy.ClassPolicy;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public interface CopyServicePolicies
|
||||
{
|
||||
/**
|
||||
* Policy invoked when a <b>node</b> is copied
|
||||
*/
|
||||
public interface OnCopyNodePolicy extends ClassPolicy
|
||||
{
|
||||
/**
|
||||
* @param classRef the type of node being copied
|
||||
* @param sourceNodeRef node being copied
|
||||
* @param destinationStoreRef the destination store reference
|
||||
* @param copyToNewNode indicates whether we are copying to a new node or not
|
||||
* @param copyDetails modifiable <b>node</b> details
|
||||
*/
|
||||
public void onCopyNode(
|
||||
QName classRef,
|
||||
NodeRef sourceNodeRef,
|
||||
StoreRef destinationStoreRef,
|
||||
boolean copyToNewNode,
|
||||
PolicyScope copyDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Policy invoked when the copy operation invoked on a <b>node</b> is complete.
|
||||
* <p>
|
||||
* The copy map contains all the nodes created during the copy, this helps to re-map
|
||||
* any potentially relative associations.
|
||||
*/
|
||||
public interface OnCopyCompletePolicy extends ClassPolicy
|
||||
{
|
||||
/**
|
||||
* @param classRef the type of the node that was copied
|
||||
* @param sourceNodeRef the origional node
|
||||
* @param destinationRef the destination node
|
||||
* @param copyMap a map containing all the nodes that have been created during the copy
|
||||
*/
|
||||
public void onCopyComplete(
|
||||
QName classRef,
|
||||
NodeRef sourceNodeRef,
|
||||
NodeRef destinationRef,
|
||||
Map<NodeRef, NodeRef> copyMap);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user