/* * Copyright (C) 2009-2010 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * As a special exception to the terms and conditions of version 2.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have received a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.transfer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestHeader; import org.alfresco.repo.transfer.manifest.TransferManifestNodeHelper; import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; import org.alfresco.repo.transfer.manifest.TransferManifestProcessor; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.RegexQNamePattern; /** * @author brian * */ public class RepoSecondaryManifestProcessorImpl implements TransferManifestProcessor { private NodeService nodeService; private CorrespondingNodeResolver nodeResolver; private String transferId; /** * @param transferId */ public RepoSecondaryManifestProcessorImpl(String transferId) { this.transferId = transferId; } /* * (non-Javadoc) * * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#endTransferManifest() */ public void endTransferManifest() { // TODO Auto-generated method stub } /** * */ public void processTransferManifestNode(TransferManifestDeletedNode node) { } /* * (non-Javadoc) * * @see * org.alfresco.repo.transfer.manifest.TransferManifestProcessor#processTransferManifestNode(org.alfresco.repo.transfer * .manifest.TransferManifestNode) */ public void processTransferManifestNode(TransferManifestNormalNode node) { NodeRef correspondingNodeRef = nodeResolver.resolveCorrespondingNode(node.getNodeRef(), TransferManifestNodeHelper.getPrimaryParentAssoc(node), node.getParentPath()).resolvedChild; if (correspondingNodeRef == null) { correspondingNodeRef = node.getNodeRef(); } //Process parent assocs... List requiredAssocs = node.getParentAssocs(); List currentAssocs = nodeService.getParentAssocs(correspondingNodeRef); processParentChildAssociations(requiredAssocs, currentAssocs, correspondingNodeRef, false); //Process child assocs... requiredAssocs = node.getChildAssocs(); currentAssocs = nodeService.getChildAssocs(correspondingNodeRef); processParentChildAssociations(requiredAssocs, currentAssocs, correspondingNodeRef, true); //Process "target" peer associations (associations *from* this node) List requiredPeerAssocs = node.getTargetAssocs(); List currentPeerAssocs = nodeService.getTargetAssocs(correspondingNodeRef, RegexQNamePattern.MATCH_ALL); processPeerAssociations(requiredPeerAssocs, currentPeerAssocs, correspondingNodeRef, true); //Process "source" peer associations (associations *to* this node) requiredPeerAssocs = node.getSourceAssocs(); currentPeerAssocs = nodeService.getSourceAssocs(correspondingNodeRef, RegexQNamePattern.MATCH_ALL); processPeerAssociations(requiredPeerAssocs, currentPeerAssocs, correspondingNodeRef, true); } /** * @param requiredAssocs * @param currentAssocs * @param correspondingNodeRef * @param isSource */ private void processPeerAssociations(List requiredAssocs, List currentAssocs, NodeRef nodeRef, boolean isSource) { if (requiredAssocs == null) { requiredAssocs = new ArrayList(); } if (currentAssocs == null) { currentAssocs = new ArrayList(); } List assocsToAdd = new ArrayList(); List assocsToRemove = new ArrayList(); Map currentAssocMap = new HashMap(); for (AssociationRef currentAssoc : currentAssocs) { NodeRef otherNode = isSource ? currentAssoc.getTargetRef() : currentAssoc.getSourceRef(); currentAssocMap.put(otherNode, currentAssoc); } for (AssociationRef requiredAssoc : requiredAssocs) { NodeRef otherNode = isSource ? requiredAssoc.getTargetRef() : requiredAssoc.getSourceRef(); AssociationRef existingAssociation = currentAssocMap.remove(otherNode); if (existingAssociation != null) { //We already have an association with the required node. //Check whether it is correct if (!existingAssociation.getTypeQName().equals(requiredAssoc.getTypeQName())) { //No, the existing one doesn't match the required one assocsToRemove.add(existingAssociation); assocsToAdd.add(requiredAssoc); } } else { //We don't have an existing association with this required node //Check that the required node exists in this repo, and record it for adding //if it does if (nodeService.exists(otherNode)) { assocsToAdd.add(requiredAssoc); } } } //Once we get here, any entries remaining in currentParentMap are associations that need to be deleted. assocsToRemove.addAll(currentAssocMap.values()); //Deal with associations to be removed for (AssociationRef assocToRemove : assocsToRemove) { nodeService.removeAssociation(assocToRemove.getSourceRef(), assocToRemove.getTargetRef(), assocToRemove.getTypeQName()); } //Deal with associations to be added for (AssociationRef assocToAdd : assocsToAdd) { NodeRef source = isSource ? nodeRef : assocToAdd.getSourceRef(); NodeRef target = isSource ? assocToAdd.getTargetRef() : nodeRef; nodeService.createAssociation(source, target, assocToAdd.getTypeQName()); } } private void processParentChildAssociations(List requiredAssocs, List currentAssocs, NodeRef nodeRef, boolean isParent) { if (requiredAssocs == null) { requiredAssocs = new ArrayList(); } if (currentAssocs == null) { currentAssocs = new ArrayList(); } List assocsToAdd = new ArrayList(); List assocsToRemove = new ArrayList(); Map currentAssocMap = new HashMap(); for (ChildAssociationRef currentAssoc : currentAssocs) { if (!currentAssoc.isPrimary()) { NodeRef key = isParent ? currentAssoc.getChildRef() : currentAssoc.getParentRef(); currentAssocMap.put(key, currentAssoc); } } for (ChildAssociationRef requiredAssoc : requiredAssocs) { // We skip the primary parent, since this has already been handled if (!requiredAssoc.isPrimary()) { NodeRef otherNode = isParent ? requiredAssoc.getChildRef() : requiredAssoc.getParentRef(); ChildAssociationRef existingAssociation = currentAssocMap.remove(otherNode); if (existingAssociation != null) { //We already have an association with the required parent. //Check whether it is correct if (!existingAssociation.getQName().equals(requiredAssoc.getQName()) || !existingAssociation.getTypeQName().equals(requiredAssoc.getTypeQName())) { //No, the existing one doesn't match the required one assocsToRemove.add(existingAssociation); assocsToAdd.add(requiredAssoc); } } else { //We don't have an existing association with this required parent //Check that the requiredParent exists in this repo, and record it for adding //if it does if (nodeService.exists(otherNode)) { assocsToAdd.add(requiredAssoc); } } } } //Once we get here, any entries remaining in currentParentMap are associations that need to be deleted. assocsToRemove.addAll(currentAssocMap.values()); //Deal with associations to be removed for (ChildAssociationRef assocToRemove : assocsToRemove) { nodeService.removeChildAssociation(assocToRemove); } //Deal with associations to be added for (ChildAssociationRef assocToAdd : assocsToAdd) { NodeRef parent = isParent ? nodeRef : assocToAdd.getParentRef(); NodeRef child = isParent ? assocToAdd.getChildRef() : nodeRef; nodeService.addChild(parent, child, assocToAdd.getTypeQName(), assocToAdd.getQName()); } } /* * (non-Javadoc) * * @see * org.alfresco.repo.transfer.manifest.TransferManifestProcessor#processTransferManifiestHeader(org.alfresco.repo * .transfer.manifest.TransferManifestHeader) */ public void processTransferManifiestHeader(TransferManifestHeader header) { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#startTransferManifest() */ public void startTransferManifest() { // TODO Auto-generated method stub } /** * @param nodeService * the nodeService to set */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } /** * @param nodeResolver * the nodeResolver to set */ public void setNodeResolver(CorrespondingNodeResolver nodeResolver) { this.nodeResolver = nodeResolver; } }