/* * #%L * Alfresco Records Management Module * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * - * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * - * 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 <http://www.gnu.org/licenses/>. * #L% */ package org.alfresco.module.org_alfresco_module_rm.relationship; import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_FROZEN; import static org.alfresco.util.ParameterCheck.mandatory; import static org.alfresco.util.ParameterCheck.mandatoryString; import static org.apache.commons.lang.StringUtils.isBlank; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.BeforeCreateReference; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.BeforeRemoveReference; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.OnCreateReference; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.OnRemoveReference; import org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminBase; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.util.PoliciesUtil; import org.alfresco.repo.dictionary.M2Aspect; import org.alfresco.repo.dictionary.M2ClassAssociation; import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; 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.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.GUID; /** * The relationship service implementation * * @author Tuna Aksoy * @since 2.3 */ public class RelationshipServiceImpl extends RecordsManagementAdminBase implements RelationshipService { /** Policy component */ private PolicyComponent policyComponent; /** * Gets the policy component instance * * @return The policy component instance */ private PolicyComponent getPolicyComponent() { return this.policyComponent; } /** * Sets the policy component instance * * @param policyComponent The policy component instance */ public void setPolicyComponent(PolicyComponent policyComponent) { this.policyComponent = policyComponent; } /** Policy delegates */ private ClassPolicyDelegate<BeforeCreateReference> beforeCreateReferenceDelegate; private ClassPolicyDelegate<OnCreateReference> onCreateReferenceDelegate; private ClassPolicyDelegate<BeforeRemoveReference> beforeRemoveReferenceDelegate; private ClassPolicyDelegate<OnRemoveReference> onRemoveReferenceDelegate; /** * Initialisation method */ public void init() { // Register the various policies beforeCreateReferenceDelegate = getPolicyComponent().registerClassPolicy(BeforeCreateReference.class); onCreateReferenceDelegate = getPolicyComponent().registerClassPolicy(OnCreateReference.class); beforeRemoveReferenceDelegate = getPolicyComponent().registerClassPolicy(BeforeRemoveReference.class); onRemoveReferenceDelegate = getPolicyComponent().registerClassPolicy(OnRemoveReference.class); } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipDefinitions() */ @Override public Set<RelationshipDefinition> getRelationshipDefinitions() { Set<RelationshipDefinition> relationshipDefinitions = new HashSet<RelationshipDefinition>(); Set<Entry<QName, AssociationDefinition>> associationsEntrySet = getCustomAssociations().entrySet(); for (Map.Entry<QName, AssociationDefinition> associationEntry : associationsEntrySet) { AssociationDefinition associationDefinition = associationEntry.getValue(); RelationshipDefinition relationshipDefinition = createRelationshipDefinition(associationDefinition); if (relationshipDefinition != null) { relationshipDefinitions.add(relationshipDefinition); } } return relationshipDefinitions; } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipDefinition(java.lang.String) */ @Override public RelationshipDefinition getRelationshipDefinition(String uniqueName) { mandatoryString("uniqueName", uniqueName); RelationshipDefinition relationshipDefinition = null; AssociationDefinition associationDefinition = getAssociationDefinition(uniqueName); if (associationDefinition != null) { relationshipDefinition = createRelationshipDefinition(associationDefinition); } return relationshipDefinition; } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#createRelationshipDefinition(org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipDisplayName) */ @Override public RelationshipDefinition createRelationshipDefinition(RelationshipDisplayName displayName) { mandatory("displayName", displayName); String title; RelationshipType type = determineRelationshipTypeFromDisplayName(displayName); switch (type) { case BIDIRECTIONAL: title = displayName.getSourceText(); break; case PARENTCHILD: String sourceText = displayName.getSourceText(); String targetText = displayName.getTargetText(); title = composeAssociationDefinitionTitle(sourceText, targetText); break; default: StringBuilder sb = new StringBuilder(); sb.append("Unsupported relationship type: '") .append(type.toString()) .append("'."); throw new AlfrescoRuntimeException(sb.toString()); } // If this title is already taken... if (existsTitle(title)) { StringBuilder sb = new StringBuilder(); sb.append("Cannot create a relationship definition for the display name: '") .append(displayName.toString()) .append("' as there is already a relationship definition with this display name."); throw new AlfrescoRuntimeException(sb.toString()); } // Defaults to RM_CUSTOM_URI NodeRef modelRef = getCustomModelRef(""); M2Model deserializedModel = readCustomContentModel(modelRef); String customAspectName = ASPECT_CUSTOM_ASSOCIATIONS.toPrefixString(getNamespaceService()); M2Aspect customAssocsAspect = deserializedModel.getAspect(customAspectName); if (customAssocsAspect == null) { StringBuilder sb = new StringBuilder(); sb.append("The aspect: '") .append(customAspectName) .append("' is undefined."); throw new AlfrescoRuntimeException(sb.toString()); } QName relationshipDefinitionQName = generateRelationshipDefinitionQNameFor(title); String generatedShortQName = relationshipDefinitionQName.toPrefixString(getNamespaceService()); M2ClassAssociation customAssoc = customAssocsAspect.getAssociation(generatedShortQName); if (customAssoc != null) { StringBuilder sb = new StringBuilder(); sb.append("The association: '") .append(customAssoc.getName()) .append("' already exists."); throw new AlfrescoRuntimeException(sb.toString()); } M2ClassAssociation newAssoc; switch (type) { case BIDIRECTIONAL: newAssoc = customAssocsAspect.createAssociation(generatedShortQName); break; case PARENTCHILD: newAssoc = customAssocsAspect.createChildAssociation(generatedShortQName); break; default: StringBuilder sb = new StringBuilder(); sb.append("Unsupported relationship type: '") .append(type.toString()) .append("'."); throw new AlfrescoRuntimeException(sb.toString()); } newAssoc.setSourceMandatory(false); newAssoc.setTargetMandatory(false); // MOB-1573 newAssoc.setSourceMany(true); newAssoc.setTargetMany(true); newAssoc.setTitle(title); newAssoc.setTargetClassName(RecordsManagementModel.ASPECT_RECORD.toPrefixString(getNamespaceService())); writeCustomContentModel(modelRef, deserializedModel); return new RelationshipDefinitionImpl(relationshipDefinitionQName.getLocalName(), type, displayName); } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#updateReleationshipDefinition(java.lang.String) */ @Override public RelationshipDefinition updateRelationshipDefinition(String uniqueName, RelationshipDisplayName displayName) { mandatoryString("uniqueName", uniqueName); RelationshipDefinition relationshipDefinition = getRelationshipDefinition(uniqueName); if (relationshipDefinition == null) { StringBuilder sb = new StringBuilder(); sb.append("The relationship definition for the unique name '") .append(uniqueName) .append("' was not found."); throw new AlfrescoRuntimeException(sb.toString()); } String title; RelationshipType type = relationshipDefinition.getType(); switch (type) { case BIDIRECTIONAL: title = displayName.getSourceText(); if (isBlank(title)) { StringBuilder sb = new StringBuilder(); sb.append("Label text '") .append(title) .append(" cannot be blank."); throw new AlfrescoRuntimeException(sb.toString()); } break; case PARENTCHILD: String sourceText = displayName.getSourceText(); String targetText = displayName.getTargetText(); if (isBlank(sourceText) || isBlank(targetText)) { StringBuilder sb = new StringBuilder(); sb.append("Neither source text '") .append(sourceText) .append("' nor target text '") .append(targetText) .append(" can be blank."); throw new AlfrescoRuntimeException(sb.toString()); } title = composeAssociationDefinitionTitle(sourceText, targetText); break; default: StringBuilder sb = new StringBuilder(); sb.append("Unsupported relationship type: '") .append(type.toString()) .append("'."); throw new AlfrescoRuntimeException(sb.toString()); } if (existsTitle(title)) { StringBuilder sb = new StringBuilder(); sb.append("Cannot update the relationship definition as '") .append(title) .append("' already exists."); throw new AlfrescoRuntimeException(sb.toString()); } QName associationDefinitionQName = getAssociationDefinitionName(uniqueName); QName updatedAssociationDefinitionQName = persistUpdatedAssocTitle(associationDefinitionQName, title); RelationshipDefinition updatedRelationshipDefinition = getRelationshipDefinition(updatedAssociationDefinitionQName.getLocalName()); if (updatedRelationshipDefinition == null) { throw new AlfrescoRuntimeException("The relationship definition could not be updated successfully."); } return updatedRelationshipDefinition; } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#removeRelationshipDefinition(java.lang.String) */ @Override public boolean removeRelationshipDefinition(String uniqueName) { mandatoryString("uniqueName", uniqueName); throw new UnsupportedOperationException("It is not possible to remove a relationship."); } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#existsRelationshipDefinition(java.lang.String) */ @Override public boolean existsRelationshipDefinition(String uniqueName) { mandatoryString("uniqueName", uniqueName); boolean exists = false; RelationshipDefinition relationshipDefinition = getRelationshipDefinition(uniqueName); if (relationshipDefinition != null) { exists = true; } return exists; } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipsFrom(org.alfresco.service.cmr.repository.NodeRef) */ @Override public Set<Relationship> getRelationshipsFrom(NodeRef nodeRef) { return getRelationshipsFrom(nodeRef, null); } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipsFrom(org.alfresco.service.cmr.repository.NodeRef, String) */ @Override public Set<Relationship> getRelationshipsFrom(NodeRef nodeRef, String nameFilter) { mandatory("nodeRef", nodeRef); Set<Relationship> relationships = new HashSet<Relationship>(); List<AssociationRef> customReferencesFrom = getNodeService().getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); relationships.addAll(generateRelationshipFromAssociationRef(customReferencesFrom, nameFilter)); List<ChildAssociationRef> customChildReferences = getNodeService().getChildAssocs(nodeRef); relationships.addAll(generateRelationshipFromParentChildAssociationRef(customChildReferences, nameFilter)); return relationships; } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipsTo(org.alfresco.service.cmr.repository.NodeRef) */ @Override public Set<Relationship> getRelationshipsTo(NodeRef nodeRef) { return getRelationshipsTo(nodeRef, null); } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipsTo(org.alfresco.service.cmr.repository.NodeRef, String) */ @Override public Set<Relationship> getRelationshipsTo(NodeRef nodeRef, String nameFilter) { mandatory("nodeRef", nodeRef); Set<Relationship> relationships = new HashSet<Relationship>(); List<AssociationRef> customReferencesTo = getNodeService().getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); relationships.addAll(generateRelationshipFromAssociationRef(customReferencesTo, nameFilter)); List<ChildAssociationRef> customParentReferences = getNodeService().getParentAssocs(nodeRef); relationships.addAll(generateRelationshipFromParentChildAssociationRef(customParentReferences, nameFilter)); return relationships; } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#addRelationship(java.lang.String, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) */ @Override public void addRelationship(String uniqueName, NodeRef source, NodeRef target) { mandatoryString("uniqueName", uniqueName); mandatory("source", source); mandatory("target", target); // check the source node exists if (!getNodeService().exists(source)) { throw new AlfrescoRuntimeException("Can't create relationship '" + uniqueName + "', because source node doesn't exist."); } // check the target node exists if (!getNodeService().exists(target)) { throw new AlfrescoRuntimeException("Can't create relationship " + uniqueName + ", because target node doesn't exist."); } if (getNodeService().hasAspect(target, ASPECT_FROZEN)) { StringBuilder sb = new StringBuilder(); sb.append("Relationship cannot be created as the target '"). append(getNodeService().getProperty(target, ContentModel.PROP_NAME)). append("' is in a hold."); throw new AlfrescoRuntimeException(sb.toString()); } // Check that the association definition for the given unique name exists. AssociationDefinition associationDefinition = getAssociationDefinition(uniqueName); if (associationDefinition == null) { StringBuilder sb = new StringBuilder(); sb.append("No association definition found for '"). append(uniqueName). append("'."); throw new IllegalArgumentException(sb.toString()); } // Get the association definition name QName associationDefinitionName = associationDefinition.getName(); // Check if an instance of this association already exists in the same direction boolean associationAlreadyExists = associationExists(associationDefinition, source, target); if (associationAlreadyExists) { StringBuilder sb = new StringBuilder(); sb.append("Association '"). append(associationDefinitionName.getLocalName()). append("' already exists from '"). append(source). append("' to '"). append(target). append("'."); throw new AlfrescoRuntimeException(sb.toString()); } // Invoke before create reference policy invokeBeforeCreateReference(source, target, associationDefinitionName); if (associationDefinition.isChild()) { getNodeService().addChild(source, target, associationDefinitionName, associationDefinitionName); } else { getNodeService().createAssociation(source, target, associationDefinitionName); } // Invoke on create reference policy invokeOnCreateReference(source, target, associationDefinitionName); } /** * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#removeRelationship(java.lang.String, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) */ @Override public void removeRelationship(String uniqueName, NodeRef source, NodeRef target) { mandatoryString("uniqueName", uniqueName); mandatory("source", source); mandatory("target", target); // Check that the association definition for the given unique name exists. AssociationDefinition associationDefinition = getAssociationDefinition(uniqueName); if (associationDefinition == null) { StringBuilder sb = new StringBuilder(); sb.append("No association definition found for '"). append(uniqueName). append("'."); throw new IllegalArgumentException(sb.toString()); } // Get the association definition name final QName associationDefinitionName = associationDefinition.getName(); final NodeRef targetNode = target; final NodeRef sourceNode = source; invokeBeforeRemoveReference(sourceNode, targetNode, associationDefinitionName); if (associationDefinition.isChild()) { AuthenticationUtil.runAsSystem(new RunAsWork<Void>() { @Override public Void doWork() { List<ChildAssociationRef> children = getNodeService().getChildAssocs(sourceNode); for (ChildAssociationRef chRef : children) { if (associationDefinitionName.equals(chRef.getTypeQName()) && chRef.getChildRef().equals(targetNode)) { getNodeService().removeChildAssociation(chRef); } } return null; } }); } else { getNodeService().removeAssociation(source, targetNode, associationDefinitionName); } invokeOnRemoveReference(source, targetNode, associationDefinitionName); } /** * Creates the relationship definition from the association definition * * @param associationDefinition The association definition * @return The relationship definition if <code>associationDefinition</code> exists, <code>null</code> otherwise */ private RelationshipDefinition createRelationshipDefinition(AssociationDefinition associationDefinition) { RelationshipDefinition relationshipDefinition = null; if (associationDefinition != null) { String uniqueName = associationDefinition.getName().getLocalName(); RelationshipType type = getRelationshipType(associationDefinition); String title = associationDefinition.getTitle(getDictionaryService()); RelationshipDisplayName displayName = getRelationshipDisplayName(type, title); relationshipDefinition = new RelationshipDefinitionImpl(uniqueName, type, displayName); } return relationshipDefinition; } /** * Gets the relationship type from the association definition * * @param associationDefinition The association definition * @return The type of the relationship definition */ private RelationshipType getRelationshipType(AssociationDefinition associationDefinition) { RelationshipType type; if (associationDefinition instanceof ChildAssociationDefinition) { type = RelationshipType.PARENTCHILD; } else { type = RelationshipType.BIDIRECTIONAL; } return type; } /** * Gets the relationship display name of the relationship definition * * @param type The type of the relationship definition * @param title The title of the association definition * @return The relationship display name of the relationship definition */ private RelationshipDisplayName getRelationshipDisplayName(RelationshipType type, String title) { String sourceText = null; String targetText = null; switch (type) { case BIDIRECTIONAL: sourceText = title; targetText = title; break; case PARENTCHILD: String[] sourceAndTarget = splitAssociationDefinitionTitle(title); sourceText = sourceAndTarget[0]; targetText = sourceAndTarget[1]; break; default: StringBuilder sb = new StringBuilder(); sb.append("Unsupported relationship type: '") .append(type.toString()) .append("'."); throw new AlfrescoRuntimeException(sb.toString()); } return new RelationshipDisplayName(sourceText, targetText); } /** * Generates relationships from the given association references * * @param associationRefs Association references * @return Relationships generated from the given association references */ private Set<Relationship> generateRelationshipFromAssociationRef(List<AssociationRef> associationRefs, String nameFilter) { Set<Relationship> relationships = new HashSet<Relationship>(); for (AssociationRef associationRef : associationRefs) { String uniqueName = associationRef.getTypeQName().getLocalName(); if (existsRelationshipDefinition(uniqueName) && (nameFilter == null || uniqueName.equals(nameFilter))) { NodeRef from = associationRef.getSourceRef(); NodeRef to = associationRef.getTargetRef(); relationships.add(new RelationshipImpl(uniqueName, from, to)); } } return relationships; } /** * Generates relationships from the given child association references * * @param childAssociationRefs Child association references * @return Relationships generated from the given child association references */ private Set<Relationship> generateRelationshipFromParentChildAssociationRef(List<ChildAssociationRef> childAssociationRefs, String nameFilter) { Set<Relationship> relationships = new HashSet<Relationship>(); for (ChildAssociationRef childAssociationRef : childAssociationRefs) { String uniqueName = childAssociationRef.getQName().getLocalName(); if (existsRelationshipDefinition(uniqueName)&& (nameFilter == null || uniqueName.equals(nameFilter))) { NodeRef from = childAssociationRef.getParentRef(); NodeRef to = childAssociationRef.getChildRef(); relationships.add(new RelationshipImpl(uniqueName, from, to)); } } return relationships; } /** * Determines the relationship type from the display name * * @param displayName The display name of the relationship * @return The relationship type from the display name */ private RelationshipType determineRelationshipTypeFromDisplayName(RelationshipDisplayName displayName) { RelationshipType relationshipType; String sourceText = displayName.getSourceText(); String targetText = displayName.getTargetText(); String errorMsg = "Relationship type could not be determined from the display name. It is neither biderectional nor parent/child relationship"; if (isBlank(sourceText) || isBlank(targetText)) { throw new AlfrescoRuntimeException(errorMsg); } if (sourceText.equals(targetText)) { relationshipType = RelationshipType.BIDIRECTIONAL; } else { relationshipType = RelationshipType.PARENTCHILD; } return relationshipType; } /** * Invoke before create reference policy * * @param source The source node reference * @param target The target node reference * @param associationDefinitionName The association definition name */ private void invokeBeforeCreateReference(NodeRef source, NodeRef target, QName associationDefinitionName) { // Get QNames to invoke against Set<QName> qnames = PoliciesUtil.getTypeAndAspectQNames(getNodeService(), source); // Execute policy for node type and aspects BeforeCreateReference policy = beforeCreateReferenceDelegate.get(qnames); policy.beforeCreateReference(source, target, associationDefinitionName); } /** * Invoke on create reference policy * * @param source The source node reference * @param target The target node reference * @param associationDefinitionName The association definition name */ private void invokeOnCreateReference(NodeRef source, NodeRef target, QName associationDefinitionName) { // Get QNames to invoke against Set<QName> qnames = PoliciesUtil.getTypeAndAspectQNames(getNodeService(), source); // Execute policy for node type and aspects OnCreateReference policy = onCreateReferenceDelegate.get(qnames); policy.onCreateReference(source, target, associationDefinitionName); } /** * Invoke before remove reference policy * * @param source The source node reference * @param target The target node reference * @param associationDefinitionName The association definition name */ private void invokeBeforeRemoveReference(NodeRef source, NodeRef target, QName associationDefinitionName) { // Get QNames to invoke against Set<QName> qnames = PoliciesUtil.getTypeAndAspectQNames(getNodeService(), source); // Execute policy for node type and aspects BeforeRemoveReference policy = beforeRemoveReferenceDelegate.get(qnames); policy.beforeRemoveReference(source, target, associationDefinitionName); } /** * Invoke on remove reference policy * * @param source The source node reference * @param target The target node reference * @param associationDefinitionName The association definition name */ private void invokeOnRemoveReference(NodeRef source, NodeRef target, QName associationDefinitionName) { // Get QNames to invoke against Set<QName> qnames = PoliciesUtil.getTypeAndAspectQNames(getNodeService(), source); // Execute policy for node type and aspects OnRemoveReference policy = onRemoveReferenceDelegate.get(qnames); policy.onRemoveReference(source, target, associationDefinitionName); } /** * Check if an instance of the association already exists from the given * source node reference to the given target node reference * * @param associationDefinition The association definition * @param source The source node reference * @param target The target node reference * @return <code>true</code> if an association already exists, <code>false</code> otherwise */ private boolean associationExists(AssociationDefinition associationDefinition, NodeRef source, NodeRef target) { boolean associationAlreadyExists = false; QName associationDefinitionName = associationDefinition.getName(); if (associationDefinition.isChild()) { List<ChildAssociationRef> childAssocs = getNodeService().getChildAssocs(source, associationDefinitionName, associationDefinitionName); for (ChildAssociationRef chAssRef : childAssocs) { if (chAssRef.getChildRef().equals(target)) { associationAlreadyExists = true; } } } else { List<AssociationRef> assocs = getNodeService().getTargetAssocs(source, associationDefinitionName); for (AssociationRef assRef : assocs) { if (assRef.getTargetRef().equals(target)) { associationAlreadyExists = true; } } } return associationAlreadyExists; } /** * Gets the association definition for the given unique name * * @param uniqueName The unique name * @return The association definition for the given unique name if exists, <code>null</code> otherwise */ private AssociationDefinition getAssociationDefinition(String uniqueName) { AssociationDefinition associationDefinition = null; Set<Entry<QName, AssociationDefinition>> associationsEntrySet = getCustomAssociations().entrySet(); for (Map.Entry<QName, AssociationDefinition> associationEntry : associationsEntrySet) { String localName = associationEntry.getKey().getLocalName(); if (uniqueName.equals(localName)) { associationDefinition = associationEntry.getValue(); break; } } return associationDefinition; } /** * Gets the qualified name of the association definition for the given unique name * * @param uniqueName The unique name * @return The qualified name of the association definition for the given unique name */ private QName getAssociationDefinitionName(String uniqueName) { AssociationDefinition associationDefinition = getAssociationDefinition(uniqueName); if (associationDefinition == null) { StringBuilder sb = new StringBuilder(); sb.append("The qualified name for '") .append(uniqueName) .append("' was not found."); throw new AlfrescoRuntimeException(sb.toString()); } return associationDefinition.getName(); } /** * This method writes the specified String into the association's title property. * For RM custom properties and references, Title is used to store the identifier. * * NOTE: Currently RMC custom associations only * @param associationDefinitionQName Qualified name for the association definition * @param newTitle The new title * @return Qualified name for the association definition */ private QName persistUpdatedAssocTitle(QName associationDefinitionQName, String newTitle) { mandatory("associationDefinitionQName", associationDefinitionQName); AssociationDefinition assocDefn = getDictionaryService().getAssociation(associationDefinitionQName); if (assocDefn == null) { StringBuilder sb = new StringBuilder(); sb.append("Cannot find the association definiton for '"). append(associationDefinitionQName.getLocalName()). append("'."); throw new AlfrescoRuntimeException(sb.toString()); } // defaults to RM_CUSTOM_URI NodeRef modelRef = getCustomModelRef(""); M2Model deserializedModel = readCustomContentModel(modelRef); String customAspectName = ASPECT_CUSTOM_ASSOCIATIONS.toPrefixString(getNamespaceService()); M2Aspect customAssocsAspect = deserializedModel.getAspect(customAspectName); for (M2ClassAssociation assoc : customAssocsAspect.getAssociations()) { if (associationDefinitionQName.toPrefixString(getNamespaceService()).equals(assoc.getName()) && newTitle != null) { assoc.setTitle(newTitle); } } writeCustomContentModel(modelRef, deserializedModel); if (logger.isInfoEnabled()) { logger.info("persistUpdatedAssocTitle: " + associationDefinitionQName + "=" + newTitle + " to aspect: " + customAspectName); } return associationDefinitionQName; } /** * Generates a qualified name for the given relationship definition unique name * * @param uniqueName The unique name of the relationship definition * @return The qualified name of relationship definition */ private QName generateRelationshipDefinitionQNameFor(String uniqueName) { mandatoryString("uniqueName", uniqueName); QName existingQName = null; Set<QName> customAssociationsQNames = getCustomAssociations().keySet(); for (QName customAssociationsQName : customAssociationsQNames) { if (uniqueName.equals(customAssociationsQName.getLocalName())) { existingQName = customAssociationsQName; } } if (existingQName != null) { StringBuilder sb = new StringBuilder(); sb.append("Cannot create qualified name for given unique name '"). append(uniqueName). append("' as it already exists."); throw new AlfrescoRuntimeException(sb.toString()); } return QName.createQName(RM_CUSTOM_PREFIX, GUID.generate(), getNamespaceService()); } }