use of org.alfresco.service.cmr.dictionary.AssociationDefinition in project alfresco-repository by Alfresco.
the class PolicyComponentImpl method bindAssociationBehaviour.
/* (non-Javadoc)
* @see org.alfresco.repo.policy.PolicyComponent#bindAssociationBehaviour(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.policy.Behaviour)
*/
public BehaviourDefinition<ClassFeatureBehaviourBinding> bindAssociationBehaviour(QName policy, QName className, QName assocName, Behaviour behaviour) {
// Validate arguments
ParameterCheck.mandatory("Policy", policy);
ParameterCheck.mandatory("Class Reference", className);
ParameterCheck.mandatory("Association Reference", assocName);
ParameterCheck.mandatory("Behaviour", behaviour);
// Validate Binding
AssociationDefinition assocDefinition = dictionary.getAssociation(assocName);
if (assocDefinition == null) {
throw new IllegalArgumentException("Association " + assocName + " of class " + className + " has not been defined in the data dictionary");
}
// Create behaviour definition and bind to policy
ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, assocName);
BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour);
getAssociationBehaviourIndex(policy).putClassBehaviour(definition);
if (logger.isInfoEnabled())
logger.info("Bound " + behaviour + " to policy " + policy + " for association " + assocName + " of class " + className);
return definition;
}
use of org.alfresco.service.cmr.dictionary.AssociationDefinition in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method removeAspect.
@Override
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public void removeAspect(NodeRef nodeRef, QName aspectTypeQName) throws InvalidNodeRefException, InvalidAspectException {
// Don't allow spoofed aspect(s) to be removed
if (aspectTypeQName.equals(ContentModel.ASPECT_PENDING_DELETE)) {
throw new IllegalArgumentException("The aspect is reserved for system use: " + aspectTypeQName);
}
/*
* Note: Aspect and property removal is resilient to missing dictionary definitions
*/
// get the node
final Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef);
final Long nodeId = nodePair.getFirst();
boolean hadAspect = nodeDAO.hasNodeAspect(nodeId, aspectTypeQName);
// Invoke policy behaviours
invokeBeforeUpdateNode(nodeRef);
if (hadAspect) {
invokeBeforeRemoveAspect(nodeRef, aspectTypeQName);
nodeDAO.removeNodeAspects(nodeId, Collections.singleton(aspectTypeQName));
}
AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName);
boolean updated = false;
if (aspectDef != null) {
// Remove default properties
Map<QName, PropertyDefinition> propertyDefs = aspectDef.getProperties();
Set<QName> propertyToRemoveQNames = propertyDefs.keySet();
nodeDAO.removeNodeProperties(nodeId, propertyToRemoveQNames);
// Remove child associations
// We have to iterate over the associations and remove all those between the parent and child
final List<Pair<Long, ChildAssociationRef>> assocsToDelete = new ArrayList<Pair<Long, ChildAssociationRef>>(5);
final List<Pair<Long, NodeRef>> nodesToDelete = new ArrayList<Pair<Long, NodeRef>>(5);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
public boolean preLoadNodes() {
return true;
}
@Override
public boolean orderResults() {
return false;
}
public boolean handle(Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) {
if (isPendingDelete(parentNodePair.getSecond()) || isPendingDelete(childNodePair.getSecond())) {
if (logger.isTraceEnabled()) {
logger.trace("Aspect-triggered association removal: " + "Ignoring child associations where one of the nodes is pending delete: " + childAssocPair);
}
return true;
}
// have to delete the child node directly and with full archival.
if (childAssocPair.getSecond().isPrimary()) {
nodesToDelete.add(childNodePair);
} else {
assocsToDelete.add(childAssocPair);
}
// More results
return true;
}
public void done() {
}
};
// Get all the QNames to remove
Set<QName> assocTypeQNamesToRemove = new HashSet<QName>(aspectDef.getChildAssociations().keySet());
nodeDAO.getChildAssocs(nodeId, assocTypeQNamesToRemove, callback);
// Delete all the collected associations
for (Pair<Long, ChildAssociationRef> assocPair : assocsToDelete) {
updated = true;
Long assocId = assocPair.getFirst();
ChildAssociationRef assocRef = assocPair.getSecond();
// delete the association instance - it is not primary
invokeBeforeDeleteChildAssociation(assocRef);
nodeDAO.deleteChildAssoc(assocId);
invokeOnDeleteChildAssociation(assocRef);
}
// Cascade-delete any nodes that were attached to primary associations
for (Pair<Long, NodeRef> childNodePair : nodesToDelete) {
NodeRef childNodeRef = childNodePair.getSecond();
this.deleteNode(childNodeRef);
}
// Gather peer associations to delete
Map<QName, AssociationDefinition> nodeAssocDefs = aspectDef.getAssociations();
List<Long> nodeAssocIdsToRemove = new ArrayList<Long>(13);
List<AssociationRef> assocRefsRemoved = new ArrayList<AssociationRef>(13);
for (Map.Entry<QName, AssociationDefinition> entry : nodeAssocDefs.entrySet()) {
if (isPendingDelete(nodeRef)) {
if (logger.isTraceEnabled()) {
logger.trace("Aspect-triggered association removal: " + "Ignoring peer associations where one of the nodes is pending delete: " + nodeRef);
}
continue;
}
if (entry.getValue().isChild()) {
// Not interested in child assocs
continue;
}
QName assocTypeQName = entry.getKey();
Collection<Pair<Long, AssociationRef>> targetAssocRefs = nodeDAO.getTargetNodeAssocs(nodeId, assocTypeQName);
for (Pair<Long, AssociationRef> assocPair : targetAssocRefs) {
if (isPendingDelete(assocPair.getSecond().getTargetRef())) {
if (logger.isTraceEnabled()) {
logger.trace("Aspect-triggered association removal: " + "Ignoring peer associations where one of the nodes is pending delete: " + assocPair);
}
continue;
}
nodeAssocIdsToRemove.add(assocPair.getFirst());
assocRefsRemoved.add(assocPair.getSecond());
}
// MNT-9580: Daisy chained cm:original associations are cascade-deleted when the first original is deleted
// As a side-effect of the investigation of MNT-9446, it was dicovered that inbound associations (ones pointing *to* this aspect)
// were also being removed. This is incorrect because the aspect being removed here has no say over who points at it.
// Therefore, do not remove inbound associations because we only define outbound associations on types and aspects.
// Integrity checking will ensure that the correct behaviours are in place to maintain model integrity.
}
// Now delete peer associations
int assocsDeleted = nodeDAO.removeNodeAssocs(nodeAssocIdsToRemove);
for (AssociationRef assocRefRemoved : assocRefsRemoved) {
invokeOnDeleteAssociation(assocRefRemoved);
}
updated = updated || assocsDeleted > 0;
}
// Invoke policy behaviours
if (updated) {
invokeOnUpdateNode(nodeRef);
}
if (hadAspect) {
invokeOnRemoveAspect(nodeRef, aspectTypeQName);
}
}
use of org.alfresco.service.cmr.dictionary.AssociationDefinition in project alfresco-repository by Alfresco.
the class AssocSourceTypeIntegrityEvent method checkIntegrity.
public void checkIntegrity(List<IntegrityRecord> eventResults) {
QName assocTypeQName = getTypeQName();
NodeRef sourceNodeRef = getNodeRef();
// if the node is gone then the check is irrelevant
QName sourceNodeTypeQName = getNodeType(sourceNodeRef);
if (sourceNodeTypeQName == null) {
// target or source is missing
if (logger.isDebugEnabled()) {
logger.debug("Ignoring integrity check - node gone: \n" + " event: " + this);
}
return;
}
// get the association def
AssociationDefinition assocDef = getAssocDef(eventResults, assocTypeQName);
// the association definition must exist
if (assocDef == null) {
IntegrityRecord result = new IntegrityRecord("Association type does not exist: \n" + " Source Node: " + sourceNodeRef + "\n" + " Source Node Type: " + sourceNodeTypeQName + "\n" + " Association Type: " + assocTypeQName);
eventResults.add(result);
return;
}
// perform required checks
checkSourceType(eventResults, assocDef, sourceNodeRef, sourceNodeTypeQName);
}
use of org.alfresco.service.cmr.dictionary.AssociationDefinition in project alfresco-repository by Alfresco.
the class AssocTargetRoleIntegrityEvent method checkIntegrity.
public void checkIntegrity(List<IntegrityRecord> eventResults) {
QName assocTypeQName = getTypeQName();
QName assocQName = getQName();
NodeRef sourceNodeRef = getNodeRef();
// get the association def
AssociationDefinition assocDef = getAssocDef(eventResults, assocTypeQName);
// the association definition must exist
if (assocDef == null) {
IntegrityRecord result = new IntegrityRecord("Association type does not exist: \n" + " Association Type: " + assocTypeQName);
eventResults.add(result);
return;
}
// check that we are dealing with child associations
if (assocQName == null) {
throw new IllegalArgumentException("The association qualified name must be supplied");
}
if (!assocDef.isChild()) {
throw new UnsupportedOperationException("This operation is only relevant to child associations");
}
ChildAssociationDefinition childAssocDef = (ChildAssociationDefinition) assocDef;
// perform required checks
checkAssocQNameRegex(eventResults, childAssocDef, assocQName, sourceNodeRef);
}
use of org.alfresco.service.cmr.dictionary.AssociationDefinition in project alfresco-repository by Alfresco.
the class AssocTargetTypeIntegrityEvent method checkIntegrity.
public void checkIntegrity(List<IntegrityRecord> eventResults) {
QName assocTypeQName = getTypeQName();
NodeRef targetNodeRef = getNodeRef();
// if the node is gone then the check is irrelevant
QName targetNodeTypeQName = getNodeType(targetNodeRef);
if (targetNodeTypeQName == null) {
// target or source is missing
if (logger.isDebugEnabled()) {
logger.debug("Ignoring integrity check - node gone: \n" + " event: " + this);
}
return;
}
// get the association def
AssociationDefinition assocDef = getAssocDef(eventResults, assocTypeQName);
// the association definition must exist
if (assocDef == null) {
IntegrityRecord result = new IntegrityRecord("Association type does not exist: \n" + " Target Node: " + targetNodeRef + "\n" + " Target Node Type: " + targetNodeTypeQName + "\n" + " Association Type: " + assocTypeQName);
eventResults.add(result);
return;
}
// perform required checks
checkTargetType(eventResults, assocDef, targetNodeRef, targetNodeTypeQName);
}
Aggregations