diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/metadata-delegation-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/metadata-delegation-context.xml
deleted file mode 100644
index 106cf0cb90..0000000000
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/metadata-delegation-context.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${server.transaction.mode.default}
-
-
-
-
-
-
-
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService.attachDelegate=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService.detachDelegate=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService.getDefinedDelegations=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService.getDelegationFor=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService.getDelegationsFrom=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService.*=ACL_DENY
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${server.transaction.mode.default}
-
-
-
-
-
-
-
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.hasDelegateForAspect=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.getDelegateFor=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.getDelegateProperties=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.getDelegateProperty=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.hasAspectOnDelegate=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.getDelegations=ACL_ALLOW
- org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService.*=ACL_DENY
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/metadata-referral-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/metadata-referral-context.xml
new file mode 100644
index 0000000000..f5c7c81edb
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/metadata-referral-context.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService.attachReferrer=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService.detachReferrer=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService.getDefinedReferrals=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService.getReferralFor=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService.getAttachedReferralsFrom=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService.*=ACL_DENY
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.isReferringMetadata=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.getReferentNode=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.getReferredProperties=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.getReferredProperty=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.hasReferredAspect=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.getAttachedReferrals=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService.*=ACL_DENY
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml
index 921a34aaf0..e38c0e6e54 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml
@@ -267,8 +267,8 @@
-
-
+
+
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminService.java
deleted file mode 100644
index 0a49ce4d2c..0000000000
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminService.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.metadatadelegation;
-
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.ChainedDelegationUnsupported;
-
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.namespace.QName;
-
-import java.util.Set;
-
-/**
- * A service to manage the delegation of aspect metadata.
- * Using this service a node can be {@link #attachDelegate linked} to a delegate node for a configured set of aspects.
- * (Note that this delegate node must already exist within the database.)
- * Then any read request for relevant metadata such as hasAspect or getProperties can be delegated to the
- * linked node.
- *
- * For a link to be made, there must be a {@link #getDefinedDelegations() defined Delegation} already in the system.
- * This means that a peer-association type will have to have been declared and that a spring bean will have to have
- * defined which aspects are to be handled by this {@code Delegation}.
- *
- * @author Neil Mc Erlean
- * @since 3.0.a
- */
-public interface DelegationAdminService
-{
- /**
- * Creates a link between two nodes such that the first {@code nodeRef} can 'inherit' or reuse some aspect
- * metadata from another node - the {@code delegateNodeRef}.
- *
- * Note that links can currently only extend between two pairs of nodes and cannot be chained.
- *
- * @param nodeRef the node which is to inherit additional metadata.
- * @param delegateNodeRef the node which will provide the additional metadata.
- * @param assocType the type of the peer association which will link the two nodes.
- * @return a {@link Delegation} object which defines the link type.
- * @throws ChainedDelegationUnsupported if an attempt is made to attach nodes such that a chain would be made.
- */
- Delegation attachDelegate(NodeRef nodeRef, NodeRef delegateNodeRef, QName assocType);
-
- /**
- * Removes an existing metadata delegation link between two nodes.
- *
- * @param nodeRef the node which has been linked to a delegate.
- * @param assocType the type of the peer assocation forming the link.
- * @return the removed {@link Delegation}.
- */
- Delegation detachDelegate(NodeRef nodeRef, QName assocType);
-
- /**
- * Gets the set of defined {@link Delegation}s.
- *
- * @return the set of defined Delegations.
- */
- Set getDefinedDelegations();
-
- /**
- * Gets the {@link Delegation} which contains the specified {@code aspectName} if there is one.
- * Note that only one {@link Delegation} may declare that it handles any particular aspect.
- *
- * @param aspectName the name of the aspect whose {@link Delegation} is sought.
- * @return the {@link Delegation} which handles the specified aspect, if there is one.
- */
- Delegation getDelegationFor(QName aspectName);
-
- /**
- * Gets the set of {@link Delegation}s which are in effect from the specified {@code nodeRef}.
- * From these, you can retrieve the types of peer associations which are linked to the specified
- * {@code nodeRef} as well as the aspect types that are handled.
- *
- * @param nodeRef the NodeRef whose delegations are sought.
- * @return the set of {@link Delegation}s from the specified nodeRef.
- */
- Set getDelegationsFrom(NodeRef nodeRef);
-}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminServiceImpl.java
deleted file mode 100644
index 0a2463ba05..0000000000
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminServiceImpl.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.metadatadelegation;
-
-import static org.alfresco.util.collections.CollectionUtils.transform;
-
-import org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.ChainedDelegationUnsupported;
-import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.util.collections.Function;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Neil Mc Erlean
- * @since 3.0.a
- */
-public class DelegationAdminServiceImpl implements DelegationAdminService
-{
- private DelegationRegistry registry;
- private NodeService nodeService;
-
- public void setNodeService(NodeService service)
- {
- this.nodeService = service;
- }
-
- public void setDelegationRegistry(DelegationRegistry registry)
- {
- this.registry = registry;
- }
-
- @Override public Delegation attachDelegate(NodeRef nodeRef, NodeRef delegateNodeRef, QName assocType)
- {
- final Delegation delegation = getDelegationForAssociation(assocType);
-
- // Prevent the creation of chains of delegation from node A to B to C.
-
- // If any nodes are already delegating to nodeRef for the specified assoc, then we can't chain.
- final List existingDelegatorAssocs = nodeService.getSourceAssocs(nodeRef, assocType);
- if ( !existingDelegatorAssocs.isEmpty())
- {
- final List existingDelegators = transform(existingDelegatorAssocs,
- new Function()
- {
- @Override public NodeRef apply(AssociationRef assocRef)
- {
- return assocRef.getSourceRef();
- }
- });
- throw new ChainedDelegationUnsupported("Cannot attach delegate", existingDelegators);
- }
-
- // Likewise if this delegate node is already itself delegating elsewhere, we cannot chain.
- final List existingDelegateAssocs = nodeService.getTargetAssocs(delegateNodeRef, assocType);
- if ( !existingDelegateAssocs.isEmpty())
- {
- // If it's not empty, it should only have one value in it, but just in case...
- final List existingDelegates = transform(existingDelegateAssocs,
- new Function()
- {
- @Override public NodeRef apply(AssociationRef assocRef)
- {
- return assocRef.getTargetRef();
- }
- });
- throw new ChainedDelegationUnsupported("Cannot attach delegate", existingDelegates);
- }
-
- // OK. We're good to go. We're not making a chain here.
- nodeService.createAssociation(nodeRef, delegateNodeRef, assocType);
-
- return delegation;
- }
-
- private Delegation getDelegationForAssociation(QName assocType)
- {
- final Delegation delegation = registry.getDelegateForAssociation(assocType);
-
- if (delegation == null)
- {
- throw new IllegalArgumentException("No " + Delegation.class.getSimpleName() +
- " configured for assocType " + assocType);
- }
- return delegation;
- }
-
- @Override public Delegation detachDelegate(NodeRef nodeRef, QName assocType)
- {
- // Is the association there?
- final List assocs = nodeService.getTargetAssocs(nodeRef, assocType);
-
- if (assocs == null || assocs.isEmpty())
- {
- return null;
- }
- else
- {
- Delegation result = getDelegationForAssociation(assocType);
-
- // There should only be one such association... but we'll remove them all just in case
- for (AssociationRef assocRef : assocs)
- {
- nodeService.removeAssociation(nodeRef, assocRef.getTargetRef(), assocType);
- }
-
- return result;
- }
- }
-
- @Override public Delegation getDelegationFor(QName aspectName)
- {
- Delegation delegation = null;
-
- for (Delegation d : getDefinedDelegations())
- {
- if (d.getAspects().contains(aspectName))
- {
- delegation = d;
- break;
- }
- }
- return delegation;
- }
-
- @Override public Set getDelegationsFrom(NodeRef nodeRef)
- {
- final Set allDelegations = getDefinedDelegations();
-
- final Set result = new HashSet<>();
- for (Delegation d : allDelegations)
- {
- final QName assocType = d.getAssocType();
- if ( !nodeService.getTargetAssocs(nodeRef, assocType).isEmpty())
- {
- result.add(d);
- }
- }
-
- return result;
- }
-
- @Override public Set getDefinedDelegations()
- {
- return registry.getDelegations();
- }
-}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationException.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationException.java
deleted file mode 100644
index ea978abf7b..0000000000
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationException.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.metadatadelegation;
-
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.service.cmr.repository.NodeRef;
-
-import java.util.List;
-
-/**
- * Generic class for any runtime exceptions related to metadata delegates.
- *
- * @author Neil Mc Erlean
- * @since 3.0.a
- */
-public class DelegationException extends AlfrescoRuntimeException
-{
- public DelegationException(String msgId) { super(msgId); }
- public DelegationException(String msgId, Throwable cause) { super(msgId, cause); }
-
- public static class InvalidDelegation extends DelegationException
- {
- public InvalidDelegation(String msgId)
- {
- super(msgId);
- }
- }
-
- /** A Metadata Delegation already exists. */
- public static class DelegationAlreadyExists extends DelegationException
- {
- private final Delegation delegation;
-
- public DelegationAlreadyExists(String msgId, Delegation delegation)
- {
- super(msgId);
- this.delegation = delegation;
- }
- }
-
- /**
- * A {@link Delegation} has not been found.
- * Remember that a Delegation is the definition of a type of link.
- */
- public static class DelegationNotFound extends DelegationException
- {
- public DelegationNotFound(String msgId)
- {
- super(msgId);
- }
- }
-
- /**
- * A Delegate has not been found.
- * Remember that a Delegate is an instance of a link between two nodes.
- */
- public static class DelegateNotFound extends DelegationException
- {
- public DelegateNotFound(String msgId)
- {
- super(msgId);
- }
- }
-
- /**
- * Exception to report that we currently do not support chained delegation.
- */
- public static class ChainedDelegationUnsupported extends DelegationException
- {
- private final List nodesAlreadyDelegating;
-
- public ChainedDelegationUnsupported(String msgId, List nodesAlreadyDelegating)
- {
- super(msgId);
- this.nodesAlreadyDelegating = nodesAlreadyDelegating;
- }
-
- public List getNodesAlreadyDelegating()
- {
- return this.nodesAlreadyDelegating;
- }
-
- @Override public String toString()
- {
- StringBuilder msg = new StringBuilder();
- msg.append(this.getClass().getSimpleName()).append(" Already delegating from: ")
- .append(nodesAlreadyDelegating.toString());
- return msg.toString();
- }
- }
-}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationRegistry.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationRegistry.java
deleted file mode 100644
index 54133ee40b..0000000000
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationRegistry.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.metadatadelegation;
-
-import org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.DelegationAlreadyExists;
-import org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.InvalidDelegation;
-import org.alfresco.service.namespace.QName;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This is a registry of {@link Delegation delegations} which have been defined in the system.
- *
- * @author Neil Mc Erlean
- * @since 3.0.a
- */
-public class DelegationRegistry
-{
- private final Set delegations = new HashSet<>();
-
- public void register(Delegation delegation)
- {
- // Various validation steps to do here to ensure we get consistent, sensible Delegations registered.
- if (delegations.contains(delegation))
- {
- throw new DelegationAlreadyExists("Cannot register duplicate delegation", delegation);
- }
- for (Delegation existingDelegation : delegations)
- {
- if (existingDelegation.getAssocType().equals(delegation.getAssocType()))
- {
- throw new InvalidDelegation("Cannot register two delegations with the same assocType. " +
- "Existing: " + existingDelegation +
- " New: " + delegation);
- }
- // Yes this is a for loop inside a for loop but we're assuming these sets will not be large.
- for (QName existingAspect : existingDelegation.getAspects())
- {
- if (delegation.getAspects().contains(existingAspect))
- {
- throw new InvalidDelegation("Cannot register two delegations with the same aspect. " +
- "Existing: " + existingDelegation +
- " New: " + delegation);
- }
- }
- }
-
- this.delegations.add(delegation);
- }
-
- public Set getDelegations()
- {
- return Collections.unmodifiableSet(delegations);
- }
-
- public Delegation getDelegateForAssociation(QName assocType)
- {
- for (Delegation d : delegations)
- {
- if (d.getAssocType().equals(assocType))
- {
- return d;
- }
- }
- return null;
- }
-}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationService.java
deleted file mode 100644
index b4048761c0..0000000000
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationService.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.metadatadelegation;
-
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.DelegationNotFound;
-
-import org.alfresco.service.cmr.repository.InvalidNodeRefException;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.namespace.QName;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * This service provides read-only access to delegated metadata.
- * TODO complete.
- *
- * @author Neil Mc Erlean
- * @since 3.0.a
- */
-public interface DelegationService
-{
- /**
- * Checks if the specified nodeRef has an attached {@link Delegation} for the specified aspect.
- *
- * @param nodeRef the nodeRef which may or may not have a delegate node for the specified aspect.
- * @param aspectName the name of the aspect for which the node may or may not have delegation.
- * @return whether the node is delegating metadata reads for the specified aspect.
- * @throws InvalidNodeRefException if the supplied nodeRef does not exist.
- * @throws DelegationNotFound if no delegation for the specified aspect has been attached.
- */
- boolean hasDelegateForAspect(NodeRef nodeRef, QName aspectName);
-
- /**
- * Gets the delegate node for the specified aspect, if there is one.
- *
- * @param nodeRef the node with the delegate.
- * @param aspectName the aspect name.
- * @return the nodeRef of the delegate if there is one, else {@code null}.
- * @throws DelegationNotFound if no delegation for the specified aspect has been attached.
- */
- NodeRef getDelegateFor(NodeRef nodeRef, QName aspectName);
-
- /**
- * Gets all the property values from the delegate node for the specified aspect.
- *
- * @param nodeRef the node with the delegate.
- * @param aspectName the aspect name which holds the properties we want.
- * @return the property values as obtained from the delegate node.
- */
- Map getDelegateProperties(NodeRef nodeRef, QName aspectName);
-
- /**
- * Gets the specified property value from the delegate node.
- *
- * @param nodeRef the node with the delegate.
- * @param propertyName the property name which we want.
- * @return the property value as obtained from the delegate node.
- */
- Serializable getDelegateProperty(NodeRef nodeRef, QName propertyName);
-
- /**
- * Determines if a given aspect is present on a node's delegates.
- *
- * @param nodeRef the node for which a delegate is sought.
- * @param aspectName the aspect which is to be checked.
- * @return Returns true if the aspect has been applied to one of the given node's delegates,
- * otherwise false
- */
- boolean hasAspectOnDelegate(NodeRef nodeRef, QName aspectName);
-
- /**
- * Gets all {@link Delegation delegations} currently attached to the specified node.
- *
- * @param nodeRef the node whose delegations are sought.
- * @return Returns a map of all {@link Delegation delegations} by NodeRef for the specified nodeRef.
- */
- Map getDelegations(NodeRef nodeRef);
-}
-
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/Delegation.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/MetadataReferral.java
similarity index 63%
rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/Delegation.java
rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/MetadataReferral.java
index 05a2e3caef..2b739e6a23 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/Delegation.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/MetadataReferral.java
@@ -16,9 +16,9 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
-package org.alfresco.module.org_alfresco_module_rm.metadatadelegation;
+package org.alfresco.module.org_alfresco_module_rm.referredmetadata;
-import org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.InvalidDelegation;
+import org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.InvalidMetadataReferral;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
@@ -27,27 +27,29 @@ import java.util.Objects;
import java.util.Set;
/**
- * A Delegation is a definition of a {@link #aspects set of aspects} whose metadata are to be delegated.
- * Using a Delegation, you can attach a delegate node to any node and {@code hasAspect} and
- * {@code getPropert[y|ies]} calls can be delegated to the delegate node.
+ * A {@link MetadataReferral} is a definition of a {@link #aspects set of metadata} which are, in effect, shared
+ * between multiple nodes.
+ * Using a {@link MetadataReferral}, you can link two NodeRefs such that {@code hasAspect} and
+ * {@code getPropert[y|ies]} calls on one node can can be delegated to the other. In this way a defined set of
+ * metadata on one node can be made available for read access via another node.
*
* The connection between the nodes is made with a specified {@link #assocType peer association}.
*
- * Note that a Delegation is not an instance of a link between two nodes, but the definition of such a link.
+ * Note that a {@link MetadataReferral} is not an instance of a link between two nodes, but the definition of such a link.
*
* @author Neil Mc Erlean
- * @since 3.0.a
+ * @since 2.4.a
*/
-public class Delegation
+public class MetadataReferral
{
private DictionaryService dictionaryService;
- private DelegationRegistry delegationRegistry;
+ private ReferralRegistry referralRegistry;
private Set aspects;
private QName assocType;
- public Delegation()
+ public MetadataReferral()
{
- // Intentionally empty
+ // Intentionally empty.
}
public void setDictionaryService(DictionaryService service)
@@ -55,9 +57,9 @@ public class Delegation
this.dictionaryService = service;
}
- public void setDelegationRegistry(DelegationRegistry registry)
+ public void setReferralRegistry(ReferralRegistry registry)
{
- this.delegationRegistry = registry;
+ this.referralRegistry = registry;
}
public void setAssocType(QName assocType)
@@ -74,25 +76,25 @@ public class Delegation
{
if (this.assocType == null)
{
- throw new InvalidDelegation("Illegal null assocType");
+ throw new InvalidMetadataReferral("Illegal null assocType");
}
if (aspects == null || aspects.isEmpty())
{
- throw new InvalidDelegation("Illegal null or empty aspects set");
+ throw new InvalidMetadataReferral("Illegal null or empty aspects set");
}
if (dictionaryService.getAssociation(assocType) == null)
{
- throw new InvalidDelegation("Association not found: " + assocType);
+ throw new InvalidMetadataReferral("Association not found: " + assocType);
}
for (QName aspect : aspects)
{
if (dictionaryService.getAspect(aspect) == null)
{
- throw new InvalidDelegation("Aspect not found: " + aspect);
+ throw new InvalidMetadataReferral("Aspect not found: " + aspect);
}
}
- this.delegationRegistry.register(this);
+ this.referralRegistry.register(this);
}
/** Gets the type of the peer association linking the node to its delegate. */
@@ -101,7 +103,7 @@ public class Delegation
return assocType;
}
- /** Gets the set of aspects which are being delegated. */
+ /** Gets the set of aspects which are being referred. */
public Set getAspects()
{
return Collections.unmodifiableSet(aspects);
@@ -115,9 +117,9 @@ public class Delegation
@Override public boolean equals(Object other)
{
boolean result = false;
- if (other instanceof Delegation)
+ if (other instanceof MetadataReferral)
{
- Delegation that = (Delegation)other;
+ MetadataReferral that = (MetadataReferral)other;
result = this.aspects.equals(that.aspects) &&
this.assocType.equals(that.assocType);
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminService.java
new file mode 100644
index 0000000000..cafad45b0e
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.referredmetadata;
+
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.ChainedMetadataReferralUnsupported;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
+
+import java.util.Set;
+
+/**
+ * A service to manage the referral of aspect metadata.
+ * Using this service a node can be {@link #attachReferrer linked} to a referrer node for a specific set of aspects.
+ * (Note that this referrer node must already exist within the database.)
+ * Then any read request for relevant metadata such as hasAspect or getProperties can be delegated to the
+ * linked node.
+ *
+ * For a link to be made, there must be a {@link #getDefinedReferrals() defined MetadataReferral} already in the system.
+ * This means that a peer-association type will have to have been declared and that a spring bean will have to have
+ * defined which aspects are to be handled by this {@link MetadataReferral}.
+ *
+ * @author Neil Mc Erlean
+ * @since 2.4.a
+ */
+public interface ReferralAdminService
+{
+ /**
+ * Creates a link between two nodes such that the first {@code referrer} can 'inherit' or reuse some aspect
+ * metadata from another node - the {@code referrer}.
+ *
+ * Note that links can currently only extend between two pairs of nodes and cannot be chained.
+ *
+ * @param referrer the node which is to inherit additional metadata.
+ * @param referent the node which will provide the additional metadata.
+ * @param assocType the type of the peer association which will link the two nodes.
+ * @return a {@link MetadataReferral} object which defines the link type.
+ * @throws ChainedMetadataReferralUnsupported if an attempt is made to attach nodes such that a chain would be made.
+ */
+ // FIXME Remove assocType entirely from the API
+ MetadataReferral attachReferrer(NodeRef referrer, NodeRef referent, QName assocType);
+
+ /**
+ * Removes an existing metadata link between two nodes.
+ *
+ * @param referrer the node which has been linked to a metadata source.
+ * @param assocType the type of the peer association forming the link.
+ * @return the removed {@link MetadataReferral}.
+ */
+ MetadataReferral detachReferrer(NodeRef referrer, QName assocType);
+
+ /**
+ * Gets the set of defined {@link MetadataReferral}s.
+ *
+ * @return the set of defined {@link MetadataReferral}.
+ */
+ Set getDefinedReferrals();
+
+ /**
+ * Gets the {@link MetadataReferral} which contains the specified {@code aspectName} if there is one.
+ * Note that only one {@link MetadataReferral} may declare that it handles any particular aspect.
+ *
+ * @param aspectName the name of the aspect whose {@link MetadataReferral} is sought.
+ * @return the {@link MetadataReferral} which handles the specified aspect, if there is one.
+ */
+ MetadataReferral getReferralFor(QName aspectName);
+
+ /**
+ * Gets the set of {@link MetadataReferral}s which are currently applied from the specified {@code referrer}.
+ * From these, the types of peer associations which are linked to the specified
+ * {@code referrer} as well as the aspect types that are handled can be retrieved.
+ *
+ * @param referrer the NodeRef whose {@link MetadataReferral}s are sought.
+ * @return the set of {@link MetadataReferral}s from the specified referrer.
+ */
+ Set getAttachedReferralsFrom(NodeRef referrer);
+
+ /**
+ * Gets the {@link MetadataReferral} from the specified {@code referrer} for the specified {@code aspectName},
+ * if there is one.
+ *
+ * @param referrer the node whose {@link MetadataReferral} is sought.
+ * @param aspectName the aspect name for which a {@link MetadataReferral} is sought.
+ * @return the {@link MetadataReferral} which is attached to the specified node if there is one, else {@code null}.
+ */
+ MetadataReferral getAttachedReferralFrom(NodeRef referrer, QName aspectName);
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminServiceImpl.java
new file mode 100644
index 0000000000..117261b990
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminServiceImpl.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.referredmetadata;
+
+import static org.alfresco.util.collections.CollectionUtils.transform;
+
+import org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.ChainedMetadataReferralUnsupported;
+import org.alfresco.service.cmr.repository.AssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.collections.Function;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Neil Mc Erlean
+ * @since 2.4.a
+ */
+public class ReferralAdminServiceImpl implements ReferralAdminService
+{
+ private ReferralRegistry registry;
+ private NodeService nodeService;
+
+ public void setNodeService(NodeService service)
+ {
+ this.nodeService = service;
+ }
+
+ public void setReferralRegistry(ReferralRegistry registry)
+ {
+ this.registry = registry;
+ }
+
+ @Override public MetadataReferral attachReferrer(NodeRef referrer, NodeRef referent, QName assocType)
+ {
+ final MetadataReferral metadataReferral = getReferralForAssociation(assocType);
+
+ // Prevent the creation of chains of metadata linking from node A to B to C.
+
+ // If any nodes are already linked to referrer for the specified assoc, then we can't chain.
+ final List existingReferrerAssocs = nodeService.getSourceAssocs(referrer, assocType);
+ if ( !existingReferrerAssocs.isEmpty())
+ {
+ final List existingReferrers = transform(existingReferrerAssocs,
+ new Function()
+ {
+ @Override public NodeRef apply(AssociationRef assocRef)
+ {
+ return assocRef.getSourceRef();
+ }
+ });
+ throw new ChainedMetadataReferralUnsupported("Cannot attach referrer", existingReferrers);
+ }
+
+ // Likewise if this referent node is already itself linked elsewhere, we cannot chain.
+ final List existingReferentAssocs = nodeService.getTargetAssocs(referent, assocType);
+ if ( !existingReferentAssocs.isEmpty())
+ {
+ // If it's not empty, it should only have one value in it, but just in case...
+ final List existingReferents = transform(existingReferentAssocs,
+ new Function()
+ {
+ @Override public NodeRef apply(AssociationRef assocRef)
+ {
+ return assocRef.getTargetRef();
+ }
+ });
+ throw new ChainedMetadataReferralUnsupported("Cannot attach referent", existingReferents);
+ }
+
+ // OK. We're good to go. We're not making a chain here.
+ nodeService.createAssociation(referrer, referent, assocType);
+
+ return metadataReferral;
+ }
+
+ /** Gets the {@link MetadataReferral} which uses the specified {@code assocType}. */
+ private MetadataReferral getReferralForAssociation(QName assocType)
+ {
+ final MetadataReferral metadataReferral = registry.getReferralForAssociation(assocType);
+
+ if (metadataReferral == null)
+ {
+ throw new IllegalArgumentException("No " + MetadataReferral.class.getSimpleName() +
+ " configured for assocType " + assocType);
+ }
+ return metadataReferral;
+ }
+
+ @Override public MetadataReferral detachReferrer(NodeRef referrer, QName assocType)
+ {
+ // Is the association there?
+ final List assocs = nodeService.getTargetAssocs(referrer, assocType);
+
+ if (assocs == null || assocs.isEmpty())
+ {
+ return null;
+ }
+ else
+ {
+ MetadataReferral result = getReferralForAssociation(assocType);
+
+ // There should only be one such association... but we'll remove them all just in case
+ for (AssociationRef assocRef : assocs)
+ {
+ nodeService.removeAssociation(referrer, assocRef.getTargetRef(), assocType);
+ }
+
+ return result;
+ }
+ }
+
+ @Override public MetadataReferral getReferralFor(QName aspectName)
+ {
+ MetadataReferral metadataReferral = null;
+
+ for (MetadataReferral d : getDefinedReferrals())
+ {
+ if (d.getAspects().contains(aspectName))
+ {
+ metadataReferral = d;
+ break;
+ }
+ }
+ return metadataReferral;
+ }
+
+ @Override public Set getAttachedReferralsFrom(NodeRef referrer)
+ {
+ final Set allMetadataReferrals = getDefinedReferrals();
+
+ final Set result = new HashSet<>();
+ for (MetadataReferral d : allMetadataReferrals)
+ {
+ final QName assocType = d.getAssocType();
+ if ( !nodeService.getTargetAssocs(referrer, assocType).isEmpty())
+ {
+ result.add(d);
+ }
+ }
+
+ return result;
+ }
+
+ @Override public MetadataReferral getAttachedReferralFrom(NodeRef referrer, QName aspectName)
+ {
+ final Set allMetadataReferrals = getAttachedReferralsFrom(referrer);
+
+ for (MetadataReferral d : allMetadataReferrals)
+ {
+ if (d.getAspects().contains(aspectName)) return d;
+ }
+ return null;
+ }
+
+ @Override public Set getDefinedReferrals()
+ {
+ return registry.getMetadataReferrals();
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralRegistry.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralRegistry.java
new file mode 100644
index 0000000000..2dacba8d45
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralRegistry.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.referredmetadata;
+
+import org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.MetadataReferralAlreadyExists;
+import org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.InvalidMetadataReferral;
+import org.alfresco.service.namespace.QName;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This is a registry of {@link MetadataReferral}s which have been defined in the system.
+ *
+ * @author Neil Mc Erlean
+ * @since 2.4.a
+ */
+public class ReferralRegistry
+{
+ private final Set metadataReferrals = new HashSet<>();
+
+ public void register(MetadataReferral metadataReferral)
+ {
+ // Various validation steps to do here to ensure we get consistent, sensible referrals registered.
+ if (metadataReferrals.contains(metadataReferral))
+ {
+ throw new MetadataReferralAlreadyExists("Cannot register duplicate referral", metadataReferral);
+ }
+ for (MetadataReferral existingMetadataReferral : metadataReferrals)
+ {
+ if (existingMetadataReferral.getAssocType().equals(metadataReferral.getAssocType()))
+ {
+ throw new InvalidMetadataReferral("Cannot register two referrals with the same assocType. " +
+ "Existing: " + existingMetadataReferral +
+ " New: " + metadataReferral);
+ }
+ // Yes this is a for loop inside a for loop but we're assuming these sets will not be large.
+ for (QName existingAspect : existingMetadataReferral.getAspects())
+ {
+ if (metadataReferral.getAspects().contains(existingAspect))
+ {
+ throw new InvalidMetadataReferral("Cannot register two referrals with the same aspect. " +
+ "Existing: " + existingMetadataReferral +
+ " New: " + metadataReferral);
+ }
+ }
+ }
+
+ this.metadataReferrals.add(metadataReferral);
+ }
+
+ public Set getMetadataReferrals()
+ {
+ return Collections.unmodifiableSet(metadataReferrals);
+ }
+
+ /**
+ * Gets the {@link MetadataReferral} which is defined to use the specified {@code assocType}.
+ *
+ * @param assocType the peer association type whose {@link MetadataReferral} is sought.
+ * @return the {@link MetadataReferral} defined to use the specified {@code assocType} if there is one, else {@code null}.
+ */
+ public MetadataReferral getReferralForAssociation(QName assocType)
+ {
+ for (MetadataReferral d : metadataReferrals)
+ {
+ if (d.getAssocType().equals(assocType))
+ {
+ return d;
+ }
+ }
+ return null;
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataException.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataException.java
new file mode 100644
index 0000000000..83cbb83ed1
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataException.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.referredmetadata;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+import java.util.List;
+
+/**
+ * Generic class for any runtime exceptions related to metadata referrals.
+ *
+ * @author Neil Mc Erlean
+ * @since 2.4.a
+ */
+public class ReferredMetadataException extends AlfrescoRuntimeException
+{
+ public ReferredMetadataException(String msgId) { super(msgId); }
+ public ReferredMetadataException(String msgId, Throwable cause) { super(msgId, cause); }
+
+ /** This exception may be thrown when a {@link MetadataReferral} was incorrectly initialised. */
+ public static class InvalidMetadataReferral extends ReferredMetadataException
+ {
+ public InvalidMetadataReferral(String msgId)
+ {
+ super(msgId);
+ }
+ }
+
+ /** This exception may be thrown when a {@link MetadataReferral} already exists. */
+ public static class MetadataReferralAlreadyExists extends ReferredMetadataException
+ {
+ private final MetadataReferral metadataReferral;
+
+ public MetadataReferralAlreadyExists(String msgId, MetadataReferral metadataReferral)
+ {
+ super(msgId);
+ this.metadataReferral = metadataReferral;
+ }
+ }
+
+ /** A {@link MetadataReferral} has not been found. */
+ public static class MetadataReferralNotFound extends ReferredMetadataException
+ {
+ public MetadataReferralNotFound(String msgId)
+ {
+ super(msgId);
+ }
+ }
+
+ /** A referent Node has not been found. */
+ public static class ReferentNodeNotFound extends ReferredMetadataException
+ {
+ public ReferentNodeNotFound(String msgId)
+ {
+ super(msgId);
+ }
+ }
+
+ /** Exception to report that chains of metadata referral are not currently supported. */
+ public static class ChainedMetadataReferralUnsupported extends ReferredMetadataException
+ {
+ private final List existingReferrers;
+
+ public ChainedMetadataReferralUnsupported(String msgId, List existingReferrers)
+ {
+ super(msgId);
+ this.existingReferrers = existingReferrers;
+ }
+
+ public List getExistingReferrers()
+ {
+ return this.existingReferrers;
+ }
+
+ @Override public String toString()
+ {
+ StringBuilder msg = new StringBuilder();
+ msg.append(this.getClass().getSimpleName()).append(" Already referring from: ")
+ .append(existingReferrers.toString());
+ return msg.toString();
+ }
+ }
+
+ /** Exception to report that metadata referral is not supported for metadata defined on content types. */
+ public static class TypeMetadataReferralUnsupported extends ReferredMetadataException
+ {
+ public TypeMetadataReferralUnsupported(String msgId)
+ {
+ super(msgId);
+ }
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataService.java
new file mode 100644
index 0000000000..8e18c2bcf7
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataService.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.referredmetadata;
+
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.MetadataReferralNotFound;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.TypeMetadataReferralUnsupported;
+
+import org.alfresco.service.cmr.repository.InvalidNodeRefException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * This service provides read-only access to linked metadata.
+ * TODO complete! Include definition of referent etc or link to package.html
+ *
+ * @author Neil Mc Erlean
+ * @since 2.4.a
+ */
+public interface ReferredMetadataService
+{
+ /**
+ * Checks if the specified referrer has an attached {@link MetadataReferral} for the specified aspect.
+ *
+ * @param potentialReferrer the referrer which may or may not be linked to a referent node.
+ * @param aspectName the name of the aspect.
+ * @return whether the node is linked to a referent node for the specified aspect.
+ * @throws InvalidNodeRefException if the supplied referrer does not exist.
+ * @throws MetadataReferralNotFound if no {@link MetadataReferral} is defined for the specified aspect.
+ */
+ boolean isReferringMetadata(NodeRef potentialReferrer, QName aspectName);
+
+ /**
+ * Gets the referent node for the specified aspect, if there is one.
+ *
+ * @param referrer the node whose referent is sought.
+ * @param aspectName the aspect name.
+ * @return the referent of the provided referrer if there is one, else {@code null}.
+ * @throws InvalidNodeRefException if the supplied referrer does not exist.
+ * @throws MetadataReferralNotFound if no {@link MetadataReferral} is defined for the specified aspect.
+ */
+ NodeRef getReferentNode(NodeRef referrer, QName aspectName);
+
+ /**
+ * Gets all the property values from the referent node for the specified aspect.
+ *
+ * @param referrer the referring node.
+ * @param aspectName the aspect name which holds the properties we want.
+ * @return the property values as obtained from the referent node.
+ */
+ Map getReferredProperties(NodeRef referrer, QName aspectName);
+
+ /**
+ * Gets the specified property value from the referent node.
+ *
+ * @param referrer the referring node.
+ * @param propertyName the property name whose value is sought.
+ * @return the property value as obtained from the referent node.
+ * @throws IllegalArgumentException if the specified property is not defined.
+ * @throws TypeMetadataReferralUnsupported if the specified property is not defined on an aspect.
+ */
+ Serializable getReferredProperty(NodeRef referrer, QName propertyName);
+
+ /**
+ * Determines if the specified aspect is present on a node's referent.
+ *
+ * @param referrer the referring node.
+ * @param aspectName the aspect which is to be checked on the referent node.
+ * @return Returns true if the aspect has been applied to the referent node,
+ * otherwise false
+ */
+ boolean hasReferredAspect(NodeRef referrer, QName aspectName);
+
+ /**
+ * Gets all {@link MetadataReferral referrals} currently attached to the specified node.
+ *
+ * @param potentialReferrer the node whose attached {@link MetadataReferral referrals} are sought.
+ * @return Returns a map of all attached {@link MetadataReferral referrals} for the specified nodeRef.
+ * The map has the form {@code (key, value) = (MetadataReferral, referent Node for that Referral)}
+ * The map may be empty but will not be {@code null}.
+ */
+ Map getAttachedReferrals(NodeRef potentialReferrer);
+}
+
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataServiceImpl.java
similarity index 51%
rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationServiceImpl.java
rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataServiceImpl.java
index 3b7190c7d5..add2c367c2 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataServiceImpl.java
@@ -16,10 +16,11 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
-package org.alfresco.module.org_alfresco_module_rm.metadatadelegation;
+package org.alfresco.module.org_alfresco_module_rm.referredmetadata;
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.DelegateNotFound;
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.DelegationNotFound;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.MetadataReferralNotFound;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.ReferentNodeNotFound;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.TypeMetadataReferralUnsupported;
import static org.alfresco.util.collections.CollectionUtils.filterKeys;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
@@ -40,17 +41,17 @@ import java.util.Set;
/**
* @author Neil Mc Erlean
- * @since 3.0.a
+ * @since 2.4.a
*/
-public class DelegationServiceImpl implements DelegationService
+public class ReferredMetadataServiceImpl implements ReferredMetadataService
{
- private DelegationAdminService delegationAdminService;
- private DictionaryService dictionaryService;
- private NodeService nodeService;
+ private ReferralAdminService referralAdminService;
+ private DictionaryService dictionaryService;
+ private NodeService nodeService;
- public void setDelegationAdminService(DelegationAdminService service)
+ public void setReferralAdminService(ReferralAdminService service)
{
- this.delegationAdminService = service;
+ this.referralAdminService = service;
}
public void setDictionaryService(DictionaryService service)
@@ -63,54 +64,60 @@ public class DelegationServiceImpl implements DelegationService
this.nodeService = service;
}
- @Override public boolean hasDelegateForAspect(NodeRef nodeRef, QName aspectName)
+ @Override public boolean isReferringMetadata(NodeRef potentialReferrer, QName aspectName)
{
- final Delegation delegation = delegationAdminService.getDelegationFor(aspectName);
-
- if ( !nodeService.exists(nodeRef))
+ if ( !nodeService.exists(potentialReferrer))
{
- throw new InvalidNodeRefException(nodeRef);
+ throw new InvalidNodeRefException(potentialReferrer);
}
- else if (delegation == null)
+
+ final MetadataReferral metadataReferral = referralAdminService.getReferralFor(aspectName);
+
+ if (metadataReferral == null)
{
- throw new DelegationNotFound("No delegation found for aspect: " + aspectName);
+ throw new MetadataReferralNotFound("No defined referral found for aspect: " + aspectName);
}
else
{
- final List targetAssocs = nodeService.getTargetAssocs(nodeRef, delegation.getAssocType());
+ final List targetAssocs = nodeService.getTargetAssocs(potentialReferrer, metadataReferral.getAssocType());
return !targetAssocs.isEmpty();
}
}
- @Override public NodeRef getDelegateFor(NodeRef nodeRef, QName aspectName)
+ @Override public NodeRef getReferentNode(NodeRef referrer, QName aspectName)
{
- final Delegation d = delegationAdminService.getDelegationFor(aspectName);
+ if ( !nodeService.exists(referrer))
+ {
+ throw new InvalidNodeRefException(referrer);
+ }
+
+ final MetadataReferral d = referralAdminService.getReferralFor(aspectName);
if (d == null)
{
- throw new DelegationNotFound("No delegation found for aspect: " + aspectName);
+ throw new MetadataReferralNotFound("No defined referral found for aspect: " + aspectName);
}
else
{
final QName assocType = d.getAssocType();
- final List assocs = nodeService.getTargetAssocs(nodeRef, assocType);
+ final List assocs = nodeService.getTargetAssocs(referrer, assocType);
return assocs.isEmpty() ? null : assocs.get(0).getTargetRef();
}
}
- @Override public Map getDelegateProperties(NodeRef nodeRef, final QName aspectName)
+ @Override public Map getReferredProperties(NodeRef referrer, final QName aspectName)
{
- final NodeRef delegateNode = getDelegateFor(nodeRef, aspectName);
+ final NodeRef referentNode = getReferentNode(referrer, aspectName);
- if (delegateNode == null)
+ if (referentNode == null)
{
- throw new DelegateNotFound("No delegate node found for " + nodeRef + " " + aspectName);
+ throw new ReferentNodeNotFound("No referent node found for " + referrer + " " + aspectName);
}
else
{
- Map allProps = nodeService.getProperties(delegateNode);
- Map aspectProps = filterKeys(allProps,
+ final Map allProps = nodeService.getProperties(referentNode);
+ final Map aspectProps = filterKeys(allProps,
new Function()
{
@Override public Boolean apply(QName propName)
@@ -125,7 +132,7 @@ public class DelegationServiceImpl implements DelegationService
}
}
- @Override public Serializable getDelegateProperty(NodeRef nodeRef, QName propertyName)
+ @Override public Serializable getReferredProperty(NodeRef referrer, QName propertyName)
{
final PropertyDefinition propDefn = dictionaryService.getProperty(propertyName);
@@ -141,38 +148,38 @@ public class DelegationServiceImpl implements DelegationService
msg.append("Property '").append(propertyName).append("' is not defined on an aspect: ")
.append(aspectDefn.getName());
- throw new IllegalArgumentException(msg.toString());
+ throw new TypeMetadataReferralUnsupported(msg.toString());
}
- Map allPropValues = getDelegateProperties(nodeRef, aspectDefn.getName());
+ final Map allPropValues = getReferredProperties(referrer, aspectDefn.getName());
return allPropValues.get(propertyName);
}
- @Override public boolean hasAspectOnDelegate(NodeRef nodeRef, QName aspectName)
+ @Override public boolean hasReferredAspect(NodeRef referrer, QName aspectName)
{
- final NodeRef delegateNode = getDelegateFor(nodeRef, aspectName);
+ final NodeRef referentNode = getReferentNode(referrer, aspectName);
- if (delegateNode == null)
+ if (referentNode == null)
{
- throw new DelegateNotFound("No delegate node found for " + nodeRef + " " + aspectName);
+ throw new ReferentNodeNotFound("No referent node found for " + referrer + " " + aspectName);
}
else
{
- return nodeService.hasAspect(delegateNode, aspectName);
+ return nodeService.hasAspect(referentNode, aspectName);
}
}
- @Override public Map getDelegations(NodeRef nodeRef)
+ @Override public Map getAttachedReferrals(NodeRef potentialReferrer)
{
- Set delegations = delegationAdminService.getDelegationsFrom(nodeRef);
+ Set metadataReferrals = referralAdminService.getAttachedReferralsFrom(potentialReferrer);
- Map result = new HashMap<>();
- for (Delegation d : delegations)
+ Map result = new HashMap<>();
+ for (MetadataReferral mr : metadataReferrals)
{
- // We need only use the first aspect to get the Delegation object
- if (!d.getAspects().isEmpty())
+ // We need only use the first aspect to get the MetadataReferral object
+ if (!mr.getAspects().isEmpty())
{
- result.put(d, getDelegateFor(nodeRef, d.getAspects().iterator().next()));
+ result.put(mr, getReferentNode(potentialReferrer, mr.getAspects().iterator().next()));
}
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/package-info.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/package-info.java
similarity index 53%
rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/package-info.java
rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/package-info.java
index b35ca04e74..7a1a00ae73 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/package-info.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/package-info.java
@@ -17,30 +17,31 @@
* along with Alfresco. If not, see .
*/
/**
- * This package contains the types that deliver the Metadata Delegation feature.
- * Metadata delegation allows read-only aspect metadata for any given Alfresco node to
- * be sourced from another node, the delegate.
+ * This package contains the types that deliver the Metadata Referral feature.
+ * Metadata referral allows node metadata to be shared between multiple Alfresco nodes.
*
* In this way nodes can 'inherit' some of their metadata from another node which may
* have benefits when more than one node is required to share some of the same metadata.
*
- * Multiple nodes may share the same delegate node and one node may be linked to multiple
- * delegates.
+ * Only aspect metadata can be shared and it is only shared as read-only data to the other nodes.
+ * The node which contains the metadata values is the 'referent' node and any nodes which have been
+ * linked to the referent and share the metadata are known as referrers.
*
- * The linking of nodes to their metadata delegates is done with Alfresco peer associations.
+ * Multiple nodes may share the same referent node and one node may be linked to multiple referrers.
+ *
+ * The linking of nodes to their metadata referents is done with Alfresco peer associations.
* Association types must be declared in an Alfresco content model in the normal way.
* Spring configuration is used to assign each association type a set of aspects which will
- * be available from the delegate via the association.
+ * be available from the referent via the association.
*
- * See {@link org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationAdminService}
- * for details on how to create and destroy delegation links between nodes.
+ * See {@link org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralAdminService}
+ * for details on how to create and destroy metadata links between nodes.
*
- * The read-only access to delegated metadat is made available via the
- * See {@link org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationService}
+ * See {@link org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataService}
* for details on how the data access is performed.
*
- * See {@link org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationRegistry}
- * for details on what {@link org.alfresco.module.org_alfresco_module_rm.metadatadelegation.Delegation}s
+ * See {@link org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferralRegistry}
+ * for details on what {@link org.alfresco.module.org_alfresco_module_rm.referredmetadata.MetadataReferral}s
* are defined in the system.
*/
-package org.alfresco.module.org_alfresco_module_rm.metadatadelegation;
\ No newline at end of file
+package org.alfresco.module.org_alfresco_module_rm.referredmetadata;
\ No newline at end of file
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationServiceImplUnitTest.java
deleted file mode 100644
index b28fae5de4..0000000000
--- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationServiceImplUnitTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.metadatadelegation;
-
-import static java.util.Collections.emptyMap;
-import static java.util.Arrays.asList;
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.DelegateNotFound;
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.DelegationNotFound;
-import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.expectedException;
-import static org.alfresco.module.org_alfresco_module_rm.test.util.FPUtils.asSet;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.when;
-
-import org.alfresco.service.cmr.dictionary.ClassDefinition;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.dictionary.PropertyDefinition;
-import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.repository.StoreRef;
-import org.alfresco.service.namespace.QName;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Unit tests for {@link DelegationServiceImpl}.
- *
- * @author Neil Mc Erlean
- * @since 3.0.a
- */
-public class DelegationServiceImplUnitTest
-{
- @InjectMocks private final DelegationServiceImpl delegationService = new DelegationServiceImpl();
-
- @Mock DictionaryService mockDictionaryService;
- @Mock NodeService mockNodeService;
- @Mock DelegationAdminServiceImpl mockDelegationAdminService;
-
- /** This node has a delegate node. */
- private final NodeRef nodeWithDelegate = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "nodeWithDelegate");
- /** This is the delgate for {@link #nodeWithDelegate}. */
- private final NodeRef delegateNode = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "delegateNode");
- /** This node has no delegate node. */
- private final NodeRef nodeWithoutDelegate = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "nodeWithoutDelegate");
-
- /** The type of the peer association that links the delegate to its source. */
- private final QName delegateAssocType = QName.createQName("test", "delegateAssocType");
- /** The instance of the association between {@link #nodeWithDelegate} and {@link #delegateNode}. */
- private final AssociationRef delegateAssocRef = new AssociationRef(nodeWithDelegate, delegateAssocType, delegateNode);
-
- /** Name of an aspect that has been delegated. */
- private final QName delegatedAspect1 = QName.createQName("test", "delegatedAspect1");
- /** Name of an aspect that has been delegated. */
- private final QName delegatedAspect2 = QName.createQName("test", "delegatedAspect2");
- /** Name of a content class (a type in this case) that has not been delegated.
- * N.B. Types can't be delegated currently. */
- private final QName undelegatedType = QName.createQName("test", "undelegatedType");
-
- private final QName delegatedProp = QName.createQName("test", "delegatedProp");
- private final Serializable delegatedPropValue = "hello";
- private final QName undelegatedProp = QName.createQName("test", "undelegatedProp");
-
- private final Delegation delegate = new Delegation()
- {{
- this.setAssocType(delegateAssocType);
- this.setAspects(asSet(delegatedAspect1, delegatedAspect2));
- }};
-
- @Before public void setUp()
- {
- MockitoAnnotations.initMocks(this);
-
- final PropertyDefinition aspectProp = mock(PropertyDefinition.class);
- final ClassDefinition aspectDefn = mock(ClassDefinition.class);
- when(aspectDefn.getName()).thenReturn(delegatedAspect1);
- when(aspectProp.getContainerClass()).thenReturn(aspectDefn);
- when(aspectDefn.isAspect()).thenReturn(true);
-
- final PropertyDefinition typeProp = mock(PropertyDefinition.class);
- final ClassDefinition typeDefn = mock(ClassDefinition.class);
- when(typeDefn.getName()).thenReturn(undelegatedType);
- when(typeProp.getContainerClass()).thenReturn(typeDefn);
- when(typeDefn.isAspect()).thenReturn(false);
-
- when(mockDictionaryService.getProperty(delegatedProp)).thenReturn(aspectProp);
-
- when(mockDelegationAdminService.getDelegationsFrom(nodeWithDelegate)).thenReturn(asSet(delegate));
- for (QName delegatedAspect : asSet(delegatedAspect1, delegatedAspect2))
- {
- when(mockDelegationAdminService.getDelegationFor(delegatedAspect)).thenReturn(delegate);
- when(mockNodeService.hasAspect(delegateNode, delegatedAspect)).thenReturn(true);
- }
- when(mockNodeService.getSourceAssocs(delegateNode, delegateAssocType)).thenReturn(asList(delegateAssocRef));
- when(mockNodeService.getTargetAssocs(nodeWithDelegate, delegateAssocType)).thenReturn(asList(delegateAssocRef));
- when(mockNodeService.exists(any(NodeRef.class))).thenReturn(true);
- when(mockNodeService.getProperties(delegateNode))
- .thenReturn(new HashMap()
- {{
- this.put(delegatedProp, delegatedPropValue);
- }});
- }
-
- @Test public void hasDelegateForAspect()
- {
- assertTrue(delegationService.hasDelegateForAspect(nodeWithDelegate, delegatedAspect1));
- expectedException(DelegationNotFound.class, () -> delegationService.hasDelegateForAspect(nodeWithoutDelegate, undelegatedType));
- assertFalse(delegationService.hasDelegateForAspect(nodeWithoutDelegate, delegatedAspect1));
- }
-
- @Test public void getDelegateFor()
- {
- assertEquals(delegateNode, delegationService.getDelegateFor(nodeWithDelegate, delegatedAspect1));
- expectedException(DelegationNotFound.class, () ->
- {
- delegationService.getDelegateFor(nodeWithDelegate, undelegatedType);
- return null;
- });
- assertNull(delegationService.getDelegateFor(nodeWithoutDelegate, delegatedAspect1));
- }
-
- @Test public void getDelegateProperties()
- {
- final Map expectedProps = new HashMap<>();
- expectedProps.put(delegatedProp, delegatedPropValue);
-
- assertEquals(expectedProps, delegationService.getDelegateProperties(nodeWithDelegate, delegatedAspect1));
-
- expectedException(DelegationNotFound.class,
- () -> delegationService.getDelegateProperties(nodeWithDelegate, undelegatedType));
-
- expectedException(DelegateNotFound.class,
- () -> delegationService.getDelegateProperties(nodeWithoutDelegate, delegatedAspect1));
- }
-
- @Test public void getDelegateProperty()
- {
- assertEquals(delegatedPropValue, delegationService.getDelegateProperty(nodeWithDelegate, delegatedProp));
-
- expectedException(IllegalArgumentException.class,
- () -> delegationService.getDelegateProperty(nodeWithDelegate, undelegatedProp));
-
- expectedException(DelegationNotFound.class,
- () -> delegationService.getDelegateProperties(nodeWithoutDelegate, delegatedProp));
- }
-
- @Test public void hasAspectOnDelegate()
- {
- assertTrue(delegationService.hasAspectOnDelegate(nodeWithDelegate, delegatedAspect1));
-
- expectedException(DelegationNotFound.class,
- () -> delegationService.hasAspectOnDelegate(nodeWithDelegate, undelegatedType));
-
- expectedException(DelegateNotFound.class,
- () -> delegationService.hasAspectOnDelegate(nodeWithoutDelegate, delegatedAspect1));
- }
-
- @Test public void getDelegations()
- {
- final Map expectedDelegations = new HashMap<>();
- expectedDelegations.put(delegate, delegateNode);
-
- assertEquals(expectedDelegations, delegationService.getDelegations(nodeWithDelegate));
- assertEquals(emptyMap(), delegationService.getDelegations(nodeWithoutDelegate));
- }
-}
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/MetadataReferralUnitTest.java
similarity index 67%
rename from rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationUnitTest.java
rename to rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/MetadataReferralUnitTest.java
index d63e6409d4..847f64f0d1 100644
--- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationUnitTest.java
+++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/MetadataReferralUnitTest.java
@@ -16,10 +16,10 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
-package org.alfresco.module.org_alfresco_module_rm.metadatadelegation;
+package org.alfresco.module.org_alfresco_module_rm.referredmetadata;
import static java.util.Collections.emptySet;
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.InvalidDelegation;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.InvalidMetadataReferral;
import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.expectedException;
import static org.alfresco.module.org_alfresco_module_rm.test.util.FPUtils.asListFrom;
import static org.alfresco.module.org_alfresco_module_rm.test.util.FPUtils.asSet;
@@ -41,17 +41,17 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
/**
- * Unit tests for {@link Delegation}.
+ * Unit tests for {@link MetadataReferral}.
*
* @author Neil Mc Erlean
* @since 3.0.a
*/
-public class DelegationUnitTest
+public class MetadataReferralUnitTest
{
@Mock DictionaryService mockDictionaryService;
@Mock NodeService mockNodeService;
- private final DelegationAdminServiceImpl metadataDelegationService = new DelegationAdminServiceImpl();
+ private final ReferralAdminServiceImpl referralAdminService = new ReferralAdminServiceImpl();
private final NodeRef node1 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "node1");
private final NodeRef node2 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "node2");
@@ -63,66 +63,66 @@ public class DelegationUnitTest
{
MockitoAnnotations.initMocks(this);
- metadataDelegationService.setNodeService(mockNodeService);
+ referralAdminService.setNodeService(mockNodeService);
}
- @Test public void nullOrEmptyDelegatesAreForbidden()
+ @Test public void nullOrEmptyReferralsAreForbidden()
{
- List invalidDelegations = asListFrom(() -> new Delegation(),
+ List invalidMetadataReferrals = asListFrom(() -> new MetadataReferral(),
() -> {
- Delegation d = new Delegation();
- d.setAssocType(assoc1);
- d.setAspects(null);
- d.setDictionaryService(mockDictionaryService);
- return d;
+ MetadataReferral mr = new MetadataReferral();
+ mr.setAssocType(assoc1);
+ mr.setAspects(null);
+ mr.setDictionaryService(mockDictionaryService);
+ return mr;
},
() -> {
- Delegation d = new Delegation();
- d.setAssocType(assoc1);
- d.setAspects(emptySet());
- d.setDictionaryService(mockDictionaryService);
- return d;
+ MetadataReferral mr = new MetadataReferral();
+ mr.setAssocType(assoc1);
+ mr.setAspects(emptySet());
+ mr.setDictionaryService(mockDictionaryService);
+ return mr;
},
() -> {
- Delegation d = new Delegation();
- d.setAssocType(null);
- d.setAspects(asSet(aspect1, aspect2));
- d.setDictionaryService(mockDictionaryService);
- return d;
+ MetadataReferral mr = new MetadataReferral();
+ mr.setAssocType(null);
+ mr.setAspects(asSet(aspect1, aspect2));
+ mr.setDictionaryService(mockDictionaryService);
+ return mr;
});
- invalidDelegations.stream()
- .forEach(d -> expectedException(InvalidDelegation.class, () -> {
- d.validateAndRegister();
+ invalidMetadataReferrals.stream()
+ .forEach(mr -> expectedException(InvalidMetadataReferral.class, () -> {
+ mr.validateAndRegister();
return null;
}
));
}
- @Test(expected=InvalidDelegation.class)
- public void delegateMustHaveAssocThatExists()
+ @Test(expected=InvalidMetadataReferral.class)
+ public void referralMustHaveAssocThatExists()
{
when(mockDictionaryService.getAssociation(assoc1)).thenReturn(null);
when(mockDictionaryService.getAspect(aspect1)).thenReturn(mock(AspectDefinition.class));
- Delegation d = new Delegation();
- d.setAssocType(assoc1);
- d.setAspects(asSet(aspect1));
- d.setDictionaryService(mockDictionaryService);
- d.validateAndRegister();
+ MetadataReferral mr = new MetadataReferral();
+ mr.setAssocType(assoc1);
+ mr.setAspects(asSet(aspect1));
+ mr.setDictionaryService(mockDictionaryService);
+ mr.validateAndRegister();
}
- @Test(expected=InvalidDelegation.class)
- public void delegateMustHaveAspectsAllOfWhichExist()
+ @Test(expected=InvalidMetadataReferral.class)
+ public void referralMustHaveAspectsAllOfWhichExist()
{
when(mockDictionaryService.getAssociation(assoc1)).thenReturn(mock(AssociationDefinition.class));
when(mockDictionaryService.getAspect(aspect1)).thenReturn(mock(AspectDefinition.class));
when(mockDictionaryService.getAspect(aspect2)).thenReturn(null);
- Delegation d = new Delegation();
- d.setAssocType(assoc1);
- d.setAspects(asSet(aspect1, aspect2));
- d.setDictionaryService(mockDictionaryService);
- d.validateAndRegister();
+ MetadataReferral mr = new MetadataReferral();
+ mr.setAssocType(assoc1);
+ mr.setAspects(asSet(aspect1, aspect2));
+ mr.setDictionaryService(mockDictionaryService);
+ mr.validateAndRegister();
}
}
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminServiceImplUnitTest.java
similarity index 60%
rename from rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminServiceImplUnitTest.java
rename to rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminServiceImplUnitTest.java
index 1cd6a81caf..6e31f011df 100644
--- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/metadatadelegation/DelegationAdminServiceImplUnitTest.java
+++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferralAdminServiceImplUnitTest.java
@@ -16,10 +16,10 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
-package org.alfresco.module.org_alfresco_module_rm.metadatadelegation;
+package org.alfresco.module.org_alfresco_module_rm.referredmetadata;
import static java.util.Arrays.asList;
-import static org.alfresco.module.org_alfresco_module_rm.metadatadelegation.DelegationException.ChainedDelegationUnsupported;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.ChainedMetadataReferralUnsupported;
import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.expectedException;
import static org.alfresco.module.org_alfresco_module_rm.test.util.FPUtils.asSet;
import static org.junit.Assert.assertEquals;
@@ -40,37 +40,37 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/**
- * Unit tests for {@link DelegationAdminServiceImpl}.
+ * Unit tests for {@link ReferralAdminServiceImpl}.
*
* @author Neil Mc Erlean
- * @since 3.0.a
+ * @since 2.4.a
*/
-public class DelegationAdminServiceImplUnitTest
+public class ReferralAdminServiceImplUnitTest
{
- @InjectMocks private final DelegationAdminServiceImpl delegationAdminService = new DelegationAdminServiceImpl();
+ @InjectMocks private final ReferralAdminServiceImpl referralAdminService = new ReferralAdminServiceImpl();
- @Mock DictionaryService mockDictionaryService;
- @Mock NodeService mockNodeService;
- @Mock DelegationRegistry mockRegistry;
- @Mock DelegationServiceImpl mockDelegationService;
+ @Mock DictionaryService mockDictionaryService;
+ @Mock NodeService mockNodeService;
+ @Mock ReferralRegistry mockRegistry;
+ @Mock ReferredMetadataServiceImpl mockReferredMetadataService;
private final NodeRef node1 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "node1");
private final NodeRef node2 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "node2");
private final NodeRef node3 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "node3");
private final QName assoc1 = QName.createQName("test", "assoc1");
- private final QName assoc2 = QName.createQName("test", "assoc2");
-
private final QName aspect1 = QName.createQName("test", "aspect1");
private final QName aspect2 = QName.createQName("test", "aspect2");
+
+ private final QName assoc2 = QName.createQName("test", "assoc2");
private final QName aspect3 = QName.createQName("test", "aspect3");
- private final Delegation delegate1 = new Delegation()
+ private final MetadataReferral referral1 = new MetadataReferral()
{{
this.setAssocType(assoc1);
this.setAspects(asSet(aspect1, aspect2));
}};
- private final Delegation delegate2 = new Delegation()
+ private final MetadataReferral referral2 = new MetadataReferral()
{{
this.setAssocType(assoc2);
this.setAspects(asSet(aspect3));
@@ -80,61 +80,61 @@ public class DelegationAdminServiceImplUnitTest
{
MockitoAnnotations.initMocks(this);
- when(mockRegistry.getDelegations()).thenReturn(asSet(delegate1, delegate2));
+ when(mockRegistry.getMetadataReferrals()).thenReturn(asSet(referral1, referral2));
}
@Test(expected=IllegalArgumentException.class)
- public void attachingDelegateWithNoAssociationConfiguredShouldFail()
+ public void attachingReferrerWithNoAssociationConfiguredShouldFail()
{
- delegationAdminService.attachDelegate(node1, node2, assoc1);
+ referralAdminService.attachReferrer(node2, node1, assoc1);
}
@Test public void attachDetach()
{
- when(mockRegistry.getDelegateForAssociation(assoc1)).thenReturn(delegate1);
+ when(mockRegistry.getReferralForAssociation(assoc1)).thenReturn(referral1);
// attach
- Delegation d = attachDelegate(node1, node2, assoc1);
+ MetadataReferral d = attachReferrer(node1, node2, assoc1);
// validate
assertEquals(assoc1, d.getAssocType());
assertEquals(asSet(aspect1, aspect2), d.getAspects());
- assertTrue(mockDelegationService.hasDelegateForAspect(node1, aspect1));
- assertFalse(mockDelegationService.hasDelegateForAspect(node1, aspect3));
+ assertTrue(mockReferredMetadataService.isReferringMetadata(node1, aspect1));
+ assertFalse(mockReferredMetadataService.isReferringMetadata(node1, aspect3));
// detach
- assertEquals(d, delegationAdminService.detachDelegate(node1, assoc1));
+ assertEquals(d, referralAdminService.detachReferrer(node1, assoc1));
}
- private Delegation attachDelegate(NodeRef from, NodeRef to, QName assocType)
+ private MetadataReferral attachReferrer(NodeRef referrer, NodeRef referent, QName assocType)
{
- Delegation d = delegationAdminService.attachDelegate(from, to, assocType);
- when(mockNodeService.getSourceAssocs(to, assocType)).thenReturn(asList(new AssociationRef(from, assocType, to)));
- when(mockNodeService.getTargetAssocs(from, assocType)).thenReturn(asList(new AssociationRef(from, assocType, to)));
+ MetadataReferral d = referralAdminService.attachReferrer(referrer, referent, assocType);
+ when(mockNodeService.getSourceAssocs(referent, assocType)).thenReturn(asList(new AssociationRef(referrer, assocType, referent)));
+ when(mockNodeService.getTargetAssocs(referrer, assocType)).thenReturn(asList(new AssociationRef(referrer, assocType, referent)));
for (QName aspect : d.getAspects())
{
- when(mockDelegationService.hasDelegateForAspect(from, aspect)).thenReturn(true);
+ when(mockReferredMetadataService.isReferringMetadata(referrer, aspect)).thenReturn(true);
}
return d;
}
@Test public void chainsOfDelegationShouldBePrevented()
{
- when(mockRegistry.getDelegateForAssociation(assoc1)).thenReturn(delegate1);
+ when(mockRegistry.getReferralForAssociation(assoc1)).thenReturn(referral1);
// The node already has a delegation in place: node1 -> node2. We're trying to add to the
// end of the chain: node2 -> node3
when(mockNodeService.getSourceAssocs(node2, assoc1)).thenReturn(asList(new AssociationRef(node1, assoc1, node2)));
when(mockNodeService.getTargetAssocs(node1, assoc1)).thenReturn(asList(new AssociationRef(node1, assoc1, node2)));
- expectedException(ChainedDelegationUnsupported.class, () -> {
- delegationAdminService.attachDelegate(node2, node3, assoc1);
+ expectedException(ChainedMetadataReferralUnsupported.class, () -> {
+ referralAdminService.attachReferrer(node2, node3, assoc1);
return null;
});
// Now try to add to the start of the chain: node3 -> node1
- expectedException(ChainedDelegationUnsupported.class, () -> {
- delegationAdminService.attachDelegate(node3, node1, assoc1);
+ expectedException(ChainedMetadataReferralUnsupported.class, () -> {
+ referralAdminService.attachReferrer(node3, node1, assoc1);
return null;
});
}
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataServiceImplUnitTest.java
new file mode 100644
index 0000000000..e04a96d087
--- /dev/null
+++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/referredmetadata/ReferredMetadataServiceImplUnitTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2005-2015 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.module.org_alfresco_module_rm.referredmetadata;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Arrays.asList;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.ReferentNodeNotFound;
+import static org.alfresco.module.org_alfresco_module_rm.referredmetadata.ReferredMetadataException.MetadataReferralNotFound;
+import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.expectedException;
+import static org.alfresco.module.org_alfresco_module_rm.test.util.FPUtils.asSet;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+import org.alfresco.service.cmr.dictionary.ClassDefinition;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.PropertyDefinition;
+import org.alfresco.service.cmr.repository.AssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.namespace.QName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link ReferredMetadataServiceImpl}.
+ *
+ * @author Neil Mc Erlean
+ * @since 3.0.a
+ */
+public class ReferredMetadataServiceImplUnitTest
+{
+ @InjectMocks private final ReferredMetadataServiceImpl referredMetadataService = new ReferredMetadataServiceImpl();
+
+ @Mock DictionaryService mockDictionaryService;
+ @Mock NodeService mockNodeService;
+ @Mock ReferralAdminServiceImpl mockReferralAdminService;
+
+ /** This node has a referent node. */
+ private final NodeRef referringNode = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "referringNode");
+ /** This is the referent for {@link #referringNode}. */
+ private final NodeRef referentNode = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "referentNode");
+ /** This node has no referent node. */
+ private final NodeRef nodeWithoutReferent = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "nodeWithoutReferent");
+
+ /** The type of the peer association that links the referringNode to its source. */
+ private final QName referralAssocType = QName.createQName("test", "referralAssocType");
+ /** The instance of the association between {@link #referringNode} and {@link #referentNode}. */
+ private final AssociationRef attachedReferralAssocRef = new AssociationRef(referringNode, referralAssocType, referentNode);
+
+ /** Name of an aspect that has been referred. */
+ private final QName referredAspect1 = QName.createQName("test", "referredAspect1");
+ /** Name of an aspect that has been referred. */
+ private final QName referredAspect2 = QName.createQName("test", "referredAspect2");
+ /** Name of a content class (a type in this case) that has not been referred.
+ * N.B. Types can't be referred currently. */
+ private final QName unreferredType = QName.createQName("test", "unreferredType");
+
+ private final QName referredProp = QName.createQName("test", "referredProp");
+ private final Serializable referredPropValue = "hello";
+ private final QName unreferredProp = QName.createQName("test", "unreferredProp");
+
+ private final MetadataReferral referral = new MetadataReferral()
+ {{
+ this.setAssocType(referralAssocType);
+ this.setAspects(asSet(referredAspect1, referredAspect2));
+ }};
+
+ @Before public void setUp()
+ {
+ MockitoAnnotations.initMocks(this);
+
+ final PropertyDefinition aspectProp = mock(PropertyDefinition.class);
+ final ClassDefinition aspectDefn = mock(ClassDefinition.class);
+ when(aspectDefn.getName()).thenReturn(referredAspect1);
+ when(aspectProp.getContainerClass()).thenReturn(aspectDefn);
+ when(aspectDefn.isAspect()).thenReturn(true);
+
+ final PropertyDefinition typeProp = mock(PropertyDefinition.class);
+ final ClassDefinition typeDefn = mock(ClassDefinition.class);
+ when(typeDefn.getName()).thenReturn(unreferredType);
+ when(typeProp.getContainerClass()).thenReturn(typeDefn);
+ when(typeDefn.isAspect()).thenReturn(false);
+
+ when(mockDictionaryService.getProperty(referredProp)).thenReturn(aspectProp);
+
+ when(mockReferralAdminService.getAttachedReferralsFrom(referringNode)).thenReturn(asSet(referral));
+ for (QName referredAspect : asSet(referredAspect1, referredAspect2))
+ {
+ when(mockReferralAdminService.getReferralFor(referredAspect)).thenReturn(referral);
+ when(mockNodeService.hasAspect(referentNode, referredAspect)).thenReturn(true);
+ }
+ when(mockNodeService.getSourceAssocs(referentNode, referralAssocType)).thenReturn(asList(attachedReferralAssocRef));
+ when(mockNodeService.getTargetAssocs(referringNode, referralAssocType)).thenReturn(asList(attachedReferralAssocRef));
+ when(mockNodeService.exists(any(NodeRef.class))).thenReturn(true);
+ when(mockNodeService.getProperties(referentNode))
+ .thenReturn(new HashMap()
+ {{
+ this.put(referredProp, referredPropValue);
+ }});
+ }
+
+ @Test public void isReferringMetadata()
+ {
+ assertTrue(referredMetadataService.isReferringMetadata(referringNode, referredAspect1));
+ expectedException(MetadataReferralNotFound.class,
+ () -> referredMetadataService.isReferringMetadata(nodeWithoutReferent, unreferredType));
+ assertFalse(referredMetadataService.isReferringMetadata(nodeWithoutReferent, referredAspect1));
+ }
+
+ @Test public void getReferentNode()
+ {
+ assertEquals(referentNode, referredMetadataService.getReferentNode(referringNode, referredAspect1));
+ expectedException(MetadataReferralNotFound.class,
+ () -> {
+ referredMetadataService.getReferentNode(referringNode, unreferredType);
+ return null;
+ });
+ assertNull(referredMetadataService.getReferentNode(nodeWithoutReferent, referredAspect1));
+ }
+
+ @Test public void getReferredProperties()
+ {
+ final Map expectedProps = new HashMap<>();
+ expectedProps.put(referredProp, referredPropValue);
+
+ assertEquals(expectedProps, referredMetadataService.getReferredProperties(referringNode, referredAspect1));
+
+ expectedException(MetadataReferralNotFound.class,
+ () -> referredMetadataService.getReferredProperties(referringNode, unreferredType));
+
+ expectedException(ReferentNodeNotFound.class,
+ () -> referredMetadataService.getReferredProperties(nodeWithoutReferent, referredAspect1));
+ }
+
+ @Test public void getReferredProperty()
+ {
+ assertEquals(referredPropValue, referredMetadataService.getReferredProperty(referringNode, referredProp));
+
+ expectedException(IllegalArgumentException.class,
+ () -> referredMetadataService.getReferredProperty(referringNode, unreferredProp));
+
+ expectedException(MetadataReferralNotFound.class,
+ () -> referredMetadataService.getReferredProperties(nodeWithoutReferent, referredProp));
+ }
+
+ @Test public void hasReferredAspect()
+ {
+ assertTrue(referredMetadataService.hasReferredAspect(referringNode, referredAspect1));
+
+ expectedException(MetadataReferralNotFound.class,
+ () -> referredMetadataService.hasReferredAspect(referringNode, unreferredType));
+
+ expectedException(ReferentNodeNotFound.class,
+ () -> referredMetadataService.hasReferredAspect(nodeWithoutReferent, referredAspect1));
+ }
+
+ @Test public void getAttachedReferrals()
+ {
+ final Map expectedReferrals = new HashMap<>();
+ expectedReferrals.put(referral, referentNode);
+
+ assertEquals(expectedReferrals, referredMetadataService.getAttachedReferrals(referringNode));
+ assertEquals(emptyMap(), referredMetadataService.getAttachedReferrals(nodeWithoutReferent));
+ }
+}