use of org.alfresco.repo.domain.node.NodeExistsException in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method archiveHierarchyImpl.
/**
* Archive (direct copy) a node hierarchy
*
* @param walker the node hierarchy to archive
* @param archiveStoreRef StoreRef
*/
private void archiveHierarchyImpl(NodeHierarchyWalker walker, StoreRef archiveStoreRef) {
// Start with the node we are archiving to
Pair<Long, NodeRef> archiveStoreRootNodePair = nodeDAO.getRootNode(archiveStoreRef);
// Work through the hierarchy from the top down and archive all the nodes
boolean firstNode = true;
Map<Long, Pair<Long, NodeRef>> archiveRecord = new HashMap<Long, Pair<Long, NodeRef>>(walker.getNodes(false).size() * 2);
for (VisitedNode node : walker.getNodes(false)) {
// Get node metadata
Map<QName, Serializable> archiveProperties = nodeDAO.getNodeProperties(node.id);
Set<QName> archiveAspects = nodeDAO.getNodeAspects(node.id);
// The first node gets special treatment as it contains the archival details
ChildAssociationRef archivePrimaryParentAssocRef = null;
final Pair<Long, NodeRef> archiveParentNodePair;
if (firstNode) {
// Attach top-level archival details
ChildAssociationRef primaryParentAssocRef = node.primaryParentAssocPair.getSecond();
archiveAspects.add(ContentModel.ASPECT_ARCHIVED);
archiveProperties.put(ContentModel.PROP_ARCHIVED_BY, AuthenticationUtil.getFullyAuthenticatedUser());
archiveProperties.put(ContentModel.PROP_ARCHIVED_DATE, new Date());
archiveProperties.put(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC, primaryParentAssocRef);
Serializable originalOwner = archiveProperties.get(ContentModel.PROP_OWNER);
archiveProperties.put(ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER, originalOwner != null ? originalOwner : OwnableService.NO_OWNER);
// change the node ownership
archiveAspects.add(ContentModel.ASPECT_OWNABLE);
archiveProperties.put(ContentModel.PROP_OWNER, AuthenticationUtil.getFullyAuthenticatedUser());
// Create new primary association
archivePrimaryParentAssocRef = new ChildAssociationRef(ContentModel.ASSOC_CHILDREN, archiveStoreRootNodePair.getSecond(), NodeArchiveService.QNAME_ARCHIVED_ITEM, new NodeRef(archiveStoreRef, node.nodeRef.getId()), true, -1);
archiveParentNodePair = archiveStoreRootNodePair;
} else {
ChildAssociationRef primaryParentAssocRef = node.primaryParentAssocPair.getSecond();
NodeRef parentNodeRef = primaryParentAssocRef.getParentRef();
// Look it up
VisitedNode parentNode = walker.getNode(parentNodeRef);
if (parentNode == null) {
throw new IllegalStateException("Expected that a child has a visited primary parent: " + primaryParentAssocRef);
}
// This needs to have been mapped to a new parent
archiveParentNodePair = archiveRecord.get(parentNode.id);
if (archiveParentNodePair == null) {
throw new IllegalStateException("Expected to have archived primary parent: " + primaryParentAssocRef);
}
// Build the primary association details
archivePrimaryParentAssocRef = new ChildAssociationRef(primaryParentAssocRef.getTypeQName(), archiveParentNodePair.getSecond(), primaryParentAssocRef.getQName(), new NodeRef(archiveStoreRef, node.nodeRef.getId()), true, primaryParentAssocRef.getNthSibling());
}
// Invoke behaviours
invokeBeforeCreateNode(archivePrimaryParentAssocRef.getParentRef(), archivePrimaryParentAssocRef.getTypeQName(), archivePrimaryParentAssocRef.getQName(), node.nodeType);
// Create a new node
boolean attempted = false;
Node archiveNode = null;
while (true) {
try {
ChildAssocEntity archiveChildAssocEntity = nodeDAO.newNode(archiveParentNodePair.getFirst(), archivePrimaryParentAssocRef.getTypeQName(), archivePrimaryParentAssocRef.getQName(), archiveStoreRef, node.nodeRef.getId(), node.nodeType, (Locale) archiveProperties.get(ContentModel.PROP_LOCALE), (String) archiveProperties.get(ContentModel.PROP_NAME), archiveProperties);
archiveNode = archiveChildAssocEntity.getChildNode();
// Store the archive mapping for this node
archiveRecord.put(node.id, archiveNode.getNodePair());
break;
} catch (NodeExistsException e) {
if (!attempted) {
// There is a conflict, so delete the currently-archived node
NodeRef conflictingNodeRef = e.getNodePair().getSecond();
deleteNode(conflictingNodeRef);
attempted = true;
} else {
throw e;
}
}
}
// Carry any explicit permissions over to the new node
Set<AccessPermission> originalNodePermissions = permissionService.getAllSetPermissions(node.nodeRef);
for (AccessPermission originalPermission : originalNodePermissions) {
if (originalPermission.isInherited()) {
// Ignore inherited permissions
continue;
}
NodeRef archiveNodeRef = archiveNode.getNodeRef();
permissionService.setPermission(archiveNodeRef, originalPermission.getAuthority(), originalPermission.getPermission(), originalPermission.getAccessStatus() == AccessStatus.ALLOWED);
}
// Check if it inherits permissions or not
if (!permissionService.getInheritParentPermissions(node.nodeRef)) {
permissionService.setInheritParentPermissions(archiveNode.getNodeRef(), false);
}
// Add properties and aspects
Long archiveNodeId = archiveNode.getId();
NodeRef archiveNodeRef = archiveNode.getNodeRef();
nodeDAO.addNodeAspects(archiveNodeId, archiveAspects);
nodeDAO.addNodeProperties(archiveNodeId, archiveProperties);
// username is linked to the document
if (firstNode) {
// Attach archiveRoot aspect to root
// TODO: In time, this can be moved into a patch
Long archiveStoreRootNodeId = archiveStoreRootNodePair.getFirst();
NodeRef archiveStoreRootNodeRef = archiveStoreRootNodePair.getSecond();
if (!nodeDAO.hasNodeAspect(archiveStoreRootNodeId, ContentModel.ASPECT_ARCHIVE_ROOT)) {
addAspect(archiveStoreRootNodeRef, ContentModel.ASPECT_ARCHIVE_ROOT, null);
}
// Ensure that the user has a folder for archival
String username = AuthenticationUtil.getFullyAuthenticatedUser();
if (username == null) {
username = AuthenticationUtil.getAdminUserName();
}
Pair<Long, ChildAssociationRef> userArchiveAssocPair = nodeDAO.getChildAssoc(archiveStoreRootNodeId, ContentModel.ASSOC_ARCHIVE_USER_LINK, username);
NodeRef userArchiveNodeRef = null;
if (userArchiveAssocPair == null) {
// User has no node entry. Create a new one.
QName archiveUserAssocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(username));
Map<QName, Serializable> userArchiveNodeProps = Collections.singletonMap(ContentModel.PROP_NAME, (Serializable) username);
userArchiveNodeRef = createNode(archiveStoreRootNodeRef, ContentModel.ASSOC_ARCHIVE_USER_LINK, archiveUserAssocQName, ContentModel.TYPE_ARCHIVE_USER, userArchiveNodeProps).getChildRef();
} else {
userArchiveNodeRef = userArchiveAssocPair.getSecond().getChildRef();
}
// Link user node to archived item via secondary child association
String archiveNodeName = (String) archiveProperties.get(ContentModel.PROP_NAME);
if (archiveNodeName == null) {
archiveNodeName = archiveNodeRef.getId();
}
QName archiveAssocQName = QName.createQNameWithValidLocalName(NamespaceService.SYSTEM_MODEL_1_0_URI, archiveNodeName);
addChild(userArchiveNodeRef, archiveNodeRef, ContentModel.ASSOC_ARCHIVED_LINK, archiveAssocQName);
}
// Invoke behaviours
invokeOnCreateNode(archivePrimaryParentAssocRef);
firstNode = false;
}
}
use of org.alfresco.repo.domain.node.NodeExistsException 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;
}
}
Aggregations