use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method removeAssociation.
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) throws InvalidNodeRefException {
// The node(s) involved may not be pending deletion
checkPendingDelete(sourceRef);
checkPendingDelete(targetRef);
Pair<Long, NodeRef> sourceNodePair = getNodePairNotNull(sourceRef);
Long sourceNodeId = sourceNodePair.getFirst();
Pair<Long, NodeRef> targetNodePair = getNodePairNotNull(targetRef);
Long targetNodeId = targetNodePair.getFirst();
AssociationRef assocRef = new AssociationRef(sourceRef, assocTypeQName, targetRef);
// Invoke policy behaviours
invokeBeforeDeleteAssociation(assocRef);
// delete it
int assocsDeleted = nodeDAO.removeNodeAssoc(sourceNodeId, targetNodeId, assocTypeQName);
if (assocsDeleted > 0) {
// Invoke policy behaviours
invokeOnDeleteAssociation(assocRef);
}
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method setChildAssociationIndex.
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public void setChildAssociationIndex(ChildAssociationRef childAssocRef, int index) {
// get nodes
Pair<Long, NodeRef> parentNodePair = getNodePairNotNull(childAssocRef.getParentRef());
Pair<Long, NodeRef> childNodePair = getNodePairNotNull(childAssocRef.getChildRef());
Long parentNodeId = parentNodePair.getFirst();
Long childNodeId = childNodePair.getFirst();
QName assocTypeQName = childAssocRef.getTypeQName();
QName assocQName = childAssocRef.getQName();
// set the index
int updated = nodeDAO.setChildAssocIndex(parentNodeId, childNodeId, assocTypeQName, assocQName, index);
if (updated < 1) {
throw new InvalidChildAssociationRefException("Unable to set child association index: \n" + " assoc: " + childAssocRef + "\n" + " index: " + index, childAssocRef);
}
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method moveNode.
/**
* Move Node
*
* Drops the old primary association and creates a new one
*/
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public ChildAssociationRef moveNode(NodeRef nodeToMoveRef, NodeRef newParentRef, QName assocTypeQName, QName assocQName) {
// The node(s) involved may not be pending deletion
checkPendingDelete(nodeToMoveRef);
checkPendingDelete(newParentRef);
Pair<Long, NodeRef> nodeToMovePair = getNodePairNotNull(nodeToMoveRef);
Pair<Long, NodeRef> parentNodePair = getNodePairNotNull(newParentRef);
Long nodeToMoveId = nodeToMovePair.getFirst();
NodeRef oldNodeToMoveRef = nodeToMovePair.getSecond();
Long parentNodeId = parentNodePair.getFirst();
NodeRef parentNodeRef = parentNodePair.getSecond();
StoreRef oldStoreRef = oldNodeToMoveRef.getStoreRef();
StoreRef newStoreRef = parentNodeRef.getStoreRef();
List<ChildAssociationRef> nodesToRestoreAssociationsFor = new ArrayList<ChildAssociationRef>();
// Get the primary parent association
Pair<Long, ChildAssociationRef> oldParentAssocPair = nodeDAO.getPrimaryParentAssoc(nodeToMoveId);
if (oldParentAssocPair == null) {
// The node doesn't have parent. Moving it is not possible.
throw new IllegalArgumentException("Node " + nodeToMoveId + " doesn't have a parent. Use 'addChild' instead of move.");
}
ChildAssociationRef oldParentAssocRef = oldParentAssocPair.getSecond();
boolean movingStore = !oldStoreRef.equals(newStoreRef);
if (movingStore) {
// Recursively find primary children of the node to move
// TODO: Use NodeHierarchyWalker
List<ChildAssociationRef> childAssocs = new LinkedList<ChildAssociationRef>();
Map<NodeRef, Long> oldChildNodeIds = new HashMap<NodeRef, Long>(97);
findNodeChildrenToMove(nodeToMoveId, newStoreRef, childAssocs, oldChildNodeIds);
// Invoke "Before Delete" policy behaviour
invokeBeforeDeleteNode(nodeToMoveRef);
// do the same to the children, preserving parents, types and qnames
for (ChildAssociationRef oldChildAssoc : childAssocs) {
// Fire before delete policy. Before create policy needs the new parent ref to exist, so will be fired later
invokeBeforeDeleteNode(oldChildAssoc.getChildRef());
}
// Now do the moving and remaining policy firing
Map<NodeRef, Pair<Long, NodeRef>> movedNodePairs = new HashMap<NodeRef, Pair<Long, NodeRef>>(childAssocs.size() * 2 + 2);
QName childNodeTypeQName = nodeDAO.getNodeType(nodeToMoveId);
Set<QName> childNodeAspectQNames = nodeDAO.getNodeAspects(nodeToMoveId);
// Fire before create immediately before moving with all parents in place
invokeBeforeCreateNode(newParentRef, assocTypeQName, assocQName, childNodeTypeQName);
// Move node under the new parent
Pair<Pair<Long, ChildAssociationRef>, Pair<Long, NodeRef>> moveNodeResult = nodeDAO.moveNode(nodeToMoveId, parentNodeId, assocTypeQName, assocQName);
Pair<Long, ChildAssociationRef> newParentAssocPair = moveNodeResult.getFirst();
movedNodePairs.put(nodeToMoveRef, moveNodeResult.getSecond());
ChildAssociationRef newParentAssocRef = newParentAssocPair.getSecond();
// Propagate timestamps
propagateTimeStamps(oldParentAssocRef);
propagateTimeStamps(newParentAssocRef);
// The Node changes NodeRefs, so this is really the deletion of the old node and creation
// of a node in a new store as far as the clients are concerned.
invokeOnDeleteNode(oldParentAssocRef, childNodeTypeQName, childNodeAspectQNames, true);
invokeOnCreateNode(newParentAssocRef);
// do the same to the children, preserving parents, types and qnames
for (ChildAssociationRef oldChildAssoc : childAssocs) {
NodeRef oldChildNodeRef = oldChildAssoc.getChildRef();
Long oldChildNodeId = oldChildNodeIds.get(oldChildNodeRef);
NodeRef oldParentNodeRef = oldChildAssoc.getParentRef();
Pair<Long, NodeRef> newParentNodePair = movedNodePairs.get(oldParentNodeRef);
Long newParentNodeId = newParentNodePair.getFirst();
childNodeTypeQName = nodeDAO.getNodeType(oldChildNodeId);
childNodeAspectQNames = nodeDAO.getNodeAspects(oldChildNodeId);
// Now that the new parent ref exists, invoke the before create policy
invokeBeforeCreateNode(newParentNodePair.getSecond(), oldChildAssoc.getTypeQName(), oldChildAssoc.getQName(), childNodeTypeQName);
// Move the node as this gives back the primary parent association
try {
moveNodeResult = nodeDAO.moveNode(oldChildNodeId, newParentNodeId, null, null);
} catch (NodeExistsException e) {
deleteNode(e.getNodePair().getSecond());
moveNodeResult = nodeDAO.moveNode(oldChildNodeId, newParentNodeId, null, null);
}
// Move the node as this gives back the primary parent association
newParentAssocPair = moveNodeResult.getFirst();
movedNodePairs.put(oldChildNodeRef, moveNodeResult.getSecond());
ChildAssociationRef newChildAssoc = newParentAssocPair.getSecond();
// Propagate timestamps
propagateTimeStamps(newChildAssoc);
// Fire node policies. This ensures that each node in the hierarchy gets a notification fired.
invokeOnDeleteNode(oldChildAssoc, childNodeTypeQName, childNodeAspectQNames, true);
invokeOnCreateNode(newChildAssoc);
// to be already moved when create association between nodes
if (hasAspect(newChildAssoc.getChildRef(), ContentModel.ASPECT_ARCHIVE_LOCKABLE)) {
nodesToRestoreAssociationsFor.add(newChildAssoc);
}
}
// invoke onRestoreNode for working copy nodes in order to restore original lock
for (ChildAssociationRef childAssoc : nodesToRestoreAssociationsFor) {
invokeOnRestoreNode(childAssoc);
}
return newParentAssocRef;
} else {
invokeBeforeMoveNode(oldParentAssocRef, newParentRef);
invokeBeforeDeleteChildAssociation(oldParentAssocRef);
// Move node under the new parent
Pair<Pair<Long, ChildAssociationRef>, Pair<Long, NodeRef>> moveNodeResult = nodeDAO.moveNode(nodeToMoveId, parentNodeId, assocTypeQName, assocQName);
Pair<Long, ChildAssociationRef> newParentAssocPair = moveNodeResult.getFirst();
ChildAssociationRef newParentAssocRef = newParentAssocPair.getSecond();
// Propagate timestamps (watch out for moves within the same folder)
if (!oldParentAssocRef.getParentRef().equals(newParentAssocRef.getParentRef())) {
propagateTimeStamps(oldParentAssocRef);
propagateTimeStamps(newParentAssocRef);
} else {
// Propagate timestamps for rename case, see ALF-10884
propagateTimeStamps(newParentAssocRef);
}
invokeOnCreateChildAssociation(newParentAssocRef, false);
invokeOnDeleteChildAssociation(oldParentAssocRef);
invokeOnMoveNode(oldParentAssocRef, newParentAssocRef);
// Done
return newParentAssocRef;
}
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method addChild.
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public List<ChildAssociationRef> addChild(Collection<NodeRef> parentRefs, NodeRef childRef, QName assocTypeQName, QName assocQName) {
// The node(s) involved may not be pending deletion
checkPendingDelete(childRef);
// Get the node's name, if present
Pair<Long, NodeRef> childNodePair = getNodePairNotNull(childRef);
Long childNodeId = childNodePair.getFirst();
Map<QName, Serializable> childNodeProperties = nodeDAO.getNodeProperties(childNodePair.getFirst());
String childNodeName = extractNameProperty(childNodeProperties);
if (childNodeName == null) {
childNodeName = childRef.getId();
}
List<ChildAssociationRef> childAssociationRefs = new ArrayList<ChildAssociationRef>(parentRefs.size());
List<Pair<Long, NodeRef>> parentNodePairs = new ArrayList<Pair<Long, NodeRef>>(parentRefs.size());
for (NodeRef parentRef : parentRefs) {
// The node(s) involved may not be pending deletion
checkPendingDelete(parentRef);
Pair<Long, NodeRef> parentNodePair = getNodePairNotNull(parentRef);
Long parentNodeId = parentNodePair.getFirst();
parentNodePairs.add(parentNodePair);
// make the association
Pair<Long, ChildAssociationRef> childAssocPair = nodeDAO.newChildAssoc(parentNodeId, childNodeId, assocTypeQName, assocQName, childNodeName);
childAssociationRefs.add(childAssocPair.getSecond());
}
// check that the child addition of the child has not created a cyclic relationship
nodeDAO.cycleCheck(childNodeId);
// Invoke policy behaviours
for (ChildAssociationRef childAssocRef : childAssociationRefs) {
invokeOnCreateChildAssociation(childAssocRef, false);
}
// The association may be sourced on an aspect, which may itself mandate further aspects
for (Pair<Long, NodeRef> parentNodePair : parentNodePairs) {
addAspectsAndPropertiesAssoc(parentNodePair, assocTypeQName, null, null, null, null, false);
}
return childAssociationRefs;
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method setAssociations.
@Override
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public void setAssociations(NodeRef sourceRef, QName assocTypeQName, List<NodeRef> targetRefs) {
// The node(s) involved may not be pending deletion
checkPendingDelete(sourceRef);
Pair<Long, NodeRef> sourceNodePair = getNodePairNotNull(sourceRef);
Long sourceNodeId = sourceNodePair.getFirst();
// First get the existing associations
Collection<Pair<Long, AssociationRef>> assocsBefore = nodeDAO.getTargetNodeAssocs(sourceNodeId, assocTypeQName);
Map<NodeRef, Long> targetRefsBefore = new HashMap<NodeRef, Long>(assocsBefore.size());
Map<NodeRef, Long> toRemoveMap = new HashMap<NodeRef, Long>(assocsBefore.size());
for (Pair<Long, AssociationRef> assocBeforePair : assocsBefore) {
Long id = assocBeforePair.getFirst();
NodeRef nodeRef = assocBeforePair.getSecond().getTargetRef();
targetRefsBefore.put(nodeRef, id);
toRemoveMap.put(nodeRef, id);
}
// Work out which associations need to be removed
toRemoveMap.keySet().removeAll(targetRefs);
// Fire policies for redundant assocs
for (NodeRef targetRef : toRemoveMap.keySet()) {
AssociationRef assocRef = new AssociationRef(sourceRef, assocTypeQName, targetRef);
invokeBeforeDeleteAssociation(assocRef);
}
// Remove reduncant assocs
List<Long> toRemoveIds = new ArrayList<Long>(toRemoveMap.values());
nodeDAO.removeNodeAssocs(toRemoveIds);
// Work out which associations need to be added
Set<NodeRef> toAdd = new HashSet<NodeRef>(targetRefs);
toAdd.removeAll(targetRefsBefore.keySet());
// Iterate over the desired result and create new or reset indexes
int assocIndex = 1;
for (NodeRef targetNodeRef : targetRefs) {
// The node(s) involved may not be pending deletion
checkPendingDelete(targetNodeRef);
Long id = targetRefsBefore.get(targetNodeRef);
// Is this an existing assoc?
if (id != null) {
// Update it
nodeDAO.setNodeAssocIndex(id, assocIndex);
} else {
Long targetNodeId = getNodePairNotNull(targetNodeRef).getFirst();
nodeDAO.newNodeAssoc(sourceNodeId, targetNodeId, assocTypeQName, assocIndex);
}
assocIndex++;
}
// Invoke policy behaviours
for (NodeRef targetNodeRef : toAdd) {
AssociationRef assocRef = new AssociationRef(sourceRef, assocTypeQName, targetNodeRef);
invokeOnCreateAssociation(assocRef);
}
}
Aggregations