/* * Copyright (C) 2005-2010 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.repo.domain.node; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Object to keep hold of a node and it's parent associations. * * @author David Ward * @author Derek Hulley * @since 3.4 */ /* package */ class ParentAssocsInfo implements Serializable { private static final long serialVersionUID = -2167221525380802365L; private static final Log logger = LogFactory.getLog(ParentAssocsInfo.class); private static Set warnedDuplicateParents = new HashSet(3); private final boolean isRoot; private final boolean isStoreRoot; private final Long primaryAssocId; private final Map parentAssocsById; /** * Constructor to provide clean initial version of a Node's parent association */ ParentAssocsInfo(boolean isRoot, boolean isStoreRoot, ChildAssocEntity parent) { this(isRoot, isStoreRoot, Collections.singletonList(parent)); } /** * Constructor to provide clean initial version of a Node's parent associations */ ParentAssocsInfo(boolean isRoot, boolean isStoreRoot, List parents) { this.isRoot = isRoot; this.isStoreRoot = isStoreRoot; Long primaryAssocId = null; // Build map of child associations Map parentAssocsById = new HashMap(5); for (ChildAssocEntity parentAssoc : parents) { Long parentAssocId = parentAssoc.getId(); // Populate the results parentAssocsById.put(parentAssocId, parentAssoc); // Primary if (parentAssoc.isPrimary()) { if (primaryAssocId == null) { primaryAssocId = parentAssocId; } else { // Warn about the duplicates synchronized (warnedDuplicateParents) { Long childNodeId = parentAssoc.getChildNode().getId(); boolean added = warnedDuplicateParents.add(childNodeId); if (added) { logger.warn( "Multiple primary associations: \n" + " Node: " + childNodeId + "\n" + " Associations: " + parents); } } } } } this.primaryAssocId = primaryAssocId; // Protect the map from accidental modification this.parentAssocsById = Collections.unmodifiableMap(parentAssocsById); } /** * Private constructor used to copy existing values. */ private ParentAssocsInfo( boolean isRoot, boolean isStoreRoot, Map parentAssocsById, Long primaryAssocId) { this.isRoot = isRoot; this.isStoreRoot = isStoreRoot; this.parentAssocsById = Collections.unmodifiableMap(parentAssocsById); this.primaryAssocId = primaryAssocId; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ParentAssocsInfo ") .append("[isRoot=").append(isRoot) .append(", isStoreRoot=").append(isStoreRoot) .append(", parentAssocsById=").append(parentAssocsById) .append(", primaryAssocId=").append(primaryAssocId) .append("]"); return builder.toString(); } public boolean isRoot() { return isRoot; } public boolean isStoreRoot() { return isStoreRoot; } public Map getParentAssocs() { return parentAssocsById; } public ChildAssocEntity getPrimaryParentAssoc() { return (primaryAssocId != null) ? parentAssocsById.get(primaryAssocId) : null; } public ParentAssocsInfo changeIsRoot(boolean isRoot) { return new ParentAssocsInfo(isRoot, this.isRoot, parentAssocsById, primaryAssocId); } public ParentAssocsInfo changeIsStoreRoot(boolean isStoreRoot) { return new ParentAssocsInfo(this.isRoot, isStoreRoot, parentAssocsById, primaryAssocId); } public ParentAssocsInfo addAssoc(Long assocId, ChildAssocEntity parentAssoc) { Map parentAssocs = new HashMap(parentAssocsById); parentAssocs.put(parentAssoc.getId(), parentAssoc); return new ParentAssocsInfo(isRoot, isStoreRoot, parentAssocs, primaryAssocId); } public ParentAssocsInfo removeAssoc(Long assocId) { Map parentAssocs = new HashMap(parentAssocsById); parentAssocs.remove(assocId); return new ParentAssocsInfo(isRoot, isStoreRoot, parentAssocs, primaryAssocId); } }