mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
ACS-3280 Get inherited rule sets. [tas] (#1323)
* ACS-3280 Get inherited rule sets. [tas] This needs to work the exact same way as get inherited rules. * ACS-3280 Replace LinkedList with ArrayList. * ACS-3280 Don't return duplicated rule sets when there are links.
This commit is contained in:
@@ -35,6 +35,7 @@ import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestRuleSetModel;
|
||||
import org.alfresco.rest.model.RestRuleSetModelsCollection;
|
||||
import org.alfresco.rest.model.RestRuleSettingsModel;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
@@ -51,6 +52,8 @@ public class GetRuleSetsTests extends RestTest
|
||||
private UserModel user;
|
||||
private SiteModel site;
|
||||
private FolderModel ruleFolder;
|
||||
private FolderModel inheritingChildFolder;
|
||||
private FolderModel notInheritingChildFolder;
|
||||
private RestRuleModel rule;
|
||||
private String ruleSetId;
|
||||
|
||||
@@ -62,6 +65,14 @@ public class GetRuleSetsTests extends RestTest
|
||||
site = dataSite.usingUser(user).createPublicRandomSite();
|
||||
ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
|
||||
STEP("Create two children of the folder - one that inherits rules and one that doesn't");
|
||||
inheritingChildFolder = dataContent.usingUser(user).usingResource(ruleFolder).createFolder();
|
||||
notInheritingChildFolder = dataContent.usingUser(user).usingResource(ruleFolder).createFolder();
|
||||
RestRuleSettingsModel doesntInherit = new RestRuleSettingsModel();
|
||||
doesntInherit.setValue(false);
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(notInheritingChildFolder)
|
||||
.usingIsInheritanceEnabledRuleSetting().updateSetting(doesntInherit);
|
||||
|
||||
STEP("Create a rule in the folder.");
|
||||
RestRuleModel ruleModel = createRuleModel("ruleName");
|
||||
rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
@@ -133,7 +144,7 @@ public class GetRuleSetsTests extends RestTest
|
||||
|
||||
/** Check we can get the reason that a rule set is included in the list. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetsAndInclusionType()
|
||||
public void getRuleSetsAndOwnedInclusionType()
|
||||
{
|
||||
STEP("Get the rule sets and inclusion type");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
|
||||
@@ -148,6 +159,36 @@ public class GetRuleSetsTests extends RestTest
|
||||
ruleSets.assertThat().entriesListCountIs(1);
|
||||
}
|
||||
|
||||
/** Check we can tell that a rule set has been inherited. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetsAndInheritedInclusionType()
|
||||
{
|
||||
STEP("Get the rule sets and inclusion type");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
|
||||
.usingNode(inheritingChildFolder)
|
||||
.include("inclusionType")
|
||||
.getListOfRuleSets();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
ruleSets.getEntries().get(0).onModel()
|
||||
.assertThat().field("inclusionType").is("inherited")
|
||||
.assertThat().field("id").is(ruleSetId);
|
||||
ruleSets.assertThat().entriesListCountIs(1);
|
||||
}
|
||||
|
||||
/** Check that a rule set is not inherited if inheriting is disabled. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetsWithoutInheriting()
|
||||
{
|
||||
STEP("Get the rule sets and inclusion type");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
|
||||
.usingNode(notInheritingChildFolder)
|
||||
.getListOfRuleSets();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
ruleSets.assertThat().entriesListCountIs(0);
|
||||
}
|
||||
|
||||
/** Check we can get a rule set by its id. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
public void getRuleSetById()
|
||||
|
@@ -29,7 +29,7 @@ package org.alfresco.rest.api.impl.rules;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.repo.rule.RuntimeRuleService;
|
||||
@@ -59,10 +59,13 @@ public class RuleSetsImpl implements RuleSets
|
||||
{
|
||||
NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
|
||||
|
||||
NodeRef ruleSetNode = ruleService.getRuleSetNode(folderNode);
|
||||
List<RuleSet> ruleSets = Optional.ofNullable(ruleSetNode)
|
||||
List<RuleSet> ruleSets = ruleService.getNodesSupplyingRuleSets(folderNode)
|
||||
.stream()
|
||||
.map(ruleService::getRuleSetNode)
|
||||
.filter(Objects::nonNull)
|
||||
.map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, folderNode, includes))
|
||||
.stream().collect(toList());
|
||||
.distinct()
|
||||
.collect(toList());
|
||||
|
||||
return ListPage.of(ruleSets, paging);
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -101,6 +102,8 @@ public class RuleSetsImplTest extends TestCase
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
|
||||
given(ruleServiceMock.getRuleSetNode(FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(FOLDER_NODE));
|
||||
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, INCLUDES)).willReturn(ruleSetMock);
|
||||
}
|
||||
|
||||
@@ -113,6 +116,7 @@ public class RuleSetsImplTest extends TestCase
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
|
||||
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
@@ -133,6 +137,7 @@ public class RuleSetsImplTest extends TestCase
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
|
||||
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
@@ -140,6 +145,62 @@ public class RuleSetsImplTest extends TestCase
|
||||
assertEquals(PAGING, actual.getPaging());
|
||||
}
|
||||
|
||||
/** Check that a folder with a parent and grandparent can inherit rule sets from the grandparent, even if the parent has no rules. */
|
||||
@Test
|
||||
public void testGetInheritedRuleSets()
|
||||
{
|
||||
// Simulate a parent node without a rule set.
|
||||
NodeRef parentNode = new NodeRef("parent://node/");
|
||||
// Simulate a grandparent node providing a rule set.
|
||||
NodeRef grandparentNode = new NodeRef("grandparent://node/");
|
||||
RuleSet grandparentRuleSet = mock(RuleSet.class);
|
||||
NodeRef grandparentRuleSetNode = new NodeRef("grandparent://rule-set/");
|
||||
given(ruleServiceMock.getRuleSetNode(grandparentNode)).willReturn(grandparentRuleSetNode);
|
||||
given(ruleSetLoaderMock.loadRuleSet(grandparentRuleSetNode, FOLDER_NODE, INCLUDES)).willReturn(grandparentRuleSet);
|
||||
// These should be returned with the highest in hierarchy first.
|
||||
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(grandparentNode, parentNode, FOLDER_NODE));
|
||||
|
||||
// Call the method under test.
|
||||
CollectionWithPagingInfo<RuleSet> actual = ruleSets.getRuleSets(FOLDER_ID, INCLUDES, PAGING);
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
|
||||
then(ruleServiceMock).should().getRuleSetNode(grandparentNode);
|
||||
then(ruleServiceMock).should().getRuleSetNode(parentNode);
|
||||
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
Collection<RuleSet> expected = List.of(grandparentRuleSet, ruleSetMock);
|
||||
assertEquals(expected, actual.getCollection());
|
||||
assertEquals(PAGING, actual.getPaging());
|
||||
}
|
||||
|
||||
/** When getting rule sets then only the first instance of each rule set should be included (ancestor first). */
|
||||
@Test
|
||||
public void testGetDuplicateRuleSets()
|
||||
{
|
||||
// Simulate a grandparent, parent and child with the grandparent linking to the child's rule set.
|
||||
NodeRef grandparentNode = new NodeRef("grandparent://node/");
|
||||
given(ruleServiceMock.getRuleSetNode(grandparentNode)).willReturn(RULE_SET_NODE);
|
||||
NodeRef parentNode = new NodeRef("parent://node/");
|
||||
RuleSet parentRuleSet = mock(RuleSet.class);
|
||||
NodeRef parentRuleSetNode = new NodeRef("parent://rule-set/");
|
||||
given(ruleServiceMock.getRuleSetNode(parentNode)).willReturn(parentRuleSetNode);
|
||||
given(ruleSetLoaderMock.loadRuleSet(parentRuleSetNode, FOLDER_NODE, INCLUDES)).willReturn(parentRuleSet);
|
||||
// These should be returned with the highest in hierarchy first.
|
||||
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(grandparentNode, parentNode, FOLDER_NODE));
|
||||
|
||||
// Call the method under test.
|
||||
CollectionWithPagingInfo<RuleSet> actual = ruleSets.getRuleSets(FOLDER_ID, INCLUDES, PAGING);
|
||||
|
||||
// The grandparent's linked rule set should be first and only appear once.
|
||||
Collection<RuleSet> expected = List.of(ruleSetMock, parentRuleSet);
|
||||
assertEquals(expected, actual.getCollection());
|
||||
assertEquals(PAGING, actual.getPaging());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRuleSetById()
|
||||
{
|
||||
|
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.repo.rule;
|
||||
|
||||
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -479,7 +481,7 @@ public class RuleServiceImpl
|
||||
// Node has gone or is not the correct type
|
||||
return rules;
|
||||
}
|
||||
if (includeInherited == true && runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_IGNORE_INHERITED_RULES) == false)
|
||||
if (includeInherited && !runtimeNodeService.hasAspect(nodeRef, ASPECT_IGNORE_INHERITED_RULES))
|
||||
{
|
||||
// Get any inherited rules
|
||||
for (Rule rule : getInheritedRules(nodeRef, ruleTypeName, null))
|
||||
@@ -598,6 +600,49 @@ public class RuleServiceImpl
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
@Experimental
|
||||
public List<NodeRef> getNodesSupplyingRuleSets(NodeRef nodeRef)
|
||||
{
|
||||
return getNodesSupplyingRuleSets(nodeRef, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the folder hierarchy find all the folder nodes that could supply rules by inheritance.
|
||||
* <p>
|
||||
* The order of nodes returned by this methods has to match the order used by {@link #getInheritedRules}.
|
||||
*
|
||||
* @param nodeRef The starting node ref.
|
||||
* @param visitedNodeRefs All the visited node refs (will be modified).
|
||||
* @return A list of node refs, starting with the first parent of the first parent of ... and ending with the object generated by the
|
||||
* given node ref.
|
||||
*/
|
||||
private List<NodeRef> getNodesSupplyingRuleSets(NodeRef nodeRef, List<NodeRef> visitedNodeRefs)
|
||||
{
|
||||
List<NodeRef> returnList = new ArrayList<>();
|
||||
// This check prevents stack over flow when we have a cyclic node graph
|
||||
if (!visitedNodeRefs.contains(nodeRef))
|
||||
{
|
||||
visitedNodeRefs.add(nodeRef);
|
||||
if (!runtimeNodeService.hasAspect(nodeRef, ASPECT_IGNORE_INHERITED_RULES))
|
||||
{
|
||||
List<ChildAssociationRef> parents = runtimeNodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef parent : parents)
|
||||
{
|
||||
// We are not interested in following potentially massive person group membership trees!
|
||||
if (!IGNORE_PARENT_ASSOC_TYPES.contains(parent.getTypeQName()))
|
||||
{
|
||||
// Update visitedNodeRefs with all the ancestors.
|
||||
returnList.addAll(getNodesSupplyingRuleSets(parent.getParentRef(), visitedNodeRefs));
|
||||
}
|
||||
}
|
||||
}
|
||||
returnList.add(nodeRef);
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inherited rules for a given node reference
|
||||
*
|
||||
|
@@ -216,6 +216,17 @@ public interface RuleService
|
||||
@Auditable(parameters = {"nodeRef"})
|
||||
public int countRules(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Traverse the folder hierarchy find all the folder nodes that could supply rules by inheritance.
|
||||
*
|
||||
* @param nodeRef The starting node ref.
|
||||
* @return A list of node refs, starting with the first parent of the first parent of ... and ending with the object generated by the
|
||||
* given node ref.
|
||||
*/
|
||||
@Auditable (parameters = { "nodeRef" })
|
||||
@Experimental
|
||||
List<NodeRef> getNodesSupplyingRuleSets(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Get the rule given its node reference
|
||||
*
|
||||
|
@@ -25,7 +25,12 @@
|
||||
*/
|
||||
package org.alfresco.repo.rule;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
|
||||
import static org.alfresco.model.ContentModel.ASSOC_MEMBER;
|
||||
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
|
||||
import static org.alfresco.repo.rule.RuleModel.ASSOC_ACTION;
|
||||
import static org.alfresco.repo.rule.RuleModel.ASSOC_RULE_FOLDER;
|
||||
import static org.alfresco.repo.rule.RuleModel.TYPE_RULE;
|
||||
@@ -33,6 +38,7 @@ import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
|
||||
import static org.alfresco.service.cmr.security.AccessStatus.DENIED;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
@@ -47,8 +53,13 @@ import static org.mockito.MockitoAnnotations.openMocks;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.RuntimeActionService;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
@@ -61,6 +72,7 @@ import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.rule.RuleServiceException;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -356,4 +368,174 @@ public class RuleServiceImplUnitTest
|
||||
{
|
||||
return new ChildAssociationRef(null, parentRef, null, childRef, isPrimary, 1);
|
||||
}
|
||||
|
||||
/** Check that a straight chain of nodes is traversed correctly. */
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_chain()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,B", "B,C", "C,D", "D,E");
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("E"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("A,B,C,D,E", nodeNames);
|
||||
}
|
||||
|
||||
/** Check that ordered parents are returned in the correct order. */
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_multipleParents()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,E", "B,E", "C,E", "D,E");
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("E"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("A,B,C,D,E", nodeNames);
|
||||
}
|
||||
|
||||
/** Check that the ASPECT_IGNORE_INHERITED_RULES aspect breaks the chain. */
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_brokenChain()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,B", "B,C", "C,D", "D,E");
|
||||
given(runtimeNodeService.hasAspect(nodes.get("C"), ASPECT_IGNORE_INHERITED_RULES)).willReturn(true);
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("E"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("C,D,E", nodeNames);
|
||||
}
|
||||
|
||||
/** Check that the user group hierarchy is not traversed. */
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_userGroupHierarchy()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,B", "B,C", "C,D", "D,E");
|
||||
// Replace the B,C association with a user group membership association.
|
||||
ChildAssociationRef memberAssoc = new ChildAssociationRef(ASSOC_MEMBER, nodes.get("B"), ContentModel.TYPE_FOLDER, nodes.get("C"));
|
||||
given(runtimeNodeService.getParentAssocs(nodes.get("C"))).willReturn(List.of(memberAssoc));
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("E"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("C,D,E", nodeNames);
|
||||
}
|
||||
|
||||
/** Check that a cycle doesn't cause a problem. */
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_infiniteCycle()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,B", "B,C", "C,A");
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("C"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("A,B,C", nodeNames);
|
||||
}
|
||||
|
||||
/** Check that a diamond of nodes is traversed correctly. */
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_diamond()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,B", "A,C", "B,D", "C,D");
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("D"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("A,B,C,D", nodeNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that hierarchy of nodes is traversed correctly. Parent-child associations are created in alphabetical order.
|
||||
* <pre>
|
||||
* A
|
||||
* /|\
|
||||
* B C D
|
||||
* | |\|
|
||||
* E | F
|
||||
* \|/
|
||||
* G
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_alphabetical()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("A,B", "A,C", "A,D", "B,E", "C,F", "C,G", "D,F", "E,G", "F,G");
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("G"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("A,C,B,E,D,F,G", nodeNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that hierarchy of nodes is traversed correctly. Parent-child associations are created in reverse alphabetical order.
|
||||
* <pre>
|
||||
* A
|
||||
* /|\
|
||||
* B C D
|
||||
* | |\|
|
||||
* E | F
|
||||
* \|/
|
||||
* G
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
public void testGetNodesSupplyingRuleSets_reversedAssociationOrder()
|
||||
{
|
||||
Map<String, NodeRef> nodes = createParentChildHierarchy("F,G", "E,G", "D,F", "C,G", "C,F", "B,E", "A,D", "A,C", "A,B");
|
||||
|
||||
List<NodeRef> actual = ruleService.getNodesSupplyingRuleSets(nodes.get("G"));
|
||||
|
||||
Map<NodeRef, String> invertedMap = MapUtils.invertMap(nodes);
|
||||
String nodeNames = actual.stream().map(invertedMap::get).collect(joining(","));
|
||||
|
||||
assertEquals("A,D,C,F,B,E,G", nodeNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mock hierarchy of nodes using the supplied parent child associations.
|
||||
*
|
||||
* @param parentChildAssociations A list of strings of the form "Parent,Child". Associations will be created in this order.
|
||||
* @return A map from the node name to the new NodeRef object.
|
||||
*/
|
||||
private Map<String, NodeRef> createParentChildHierarchy(String... parentChildAssociations)
|
||||
{
|
||||
// Find all the node names mentioned.
|
||||
Set<String> nodeNames = new HashSet<>();
|
||||
List.of(parentChildAssociations).forEach(parentChildAssociation -> {
|
||||
String[] parentChildPair = parentChildAssociation.split(",");
|
||||
nodeNames.addAll(List.of(parentChildPair));
|
||||
});
|
||||
// Create the NodeRefs.
|
||||
Map<String, NodeRef> nodeRefMap = nodeNames.stream().collect(
|
||||
Collectors.toMap(nodeName -> nodeName, nodeName -> new NodeRef("node://" + nodeName + "/")));
|
||||
// Mock the associations.
|
||||
nodeNames.forEach(nodeName -> {
|
||||
NodeRef nodeRef = nodeRefMap.get(nodeName);
|
||||
List<ChildAssociationRef> parentAssocs = List.of(parentChildAssociations)
|
||||
.stream()
|
||||
.filter(assoc -> assoc.endsWith(nodeName))
|
||||
.map(assoc -> assoc.split(",")[0])
|
||||
.map(nodeRefMap::get)
|
||||
.map(parentRef -> new ChildAssociationRef(ASSOC_CONTAINS, parentRef, ContentModel.TYPE_FOLDER, nodeRef))
|
||||
.collect(toList());
|
||||
given(runtimeNodeService.getParentAssocs(nodeRef)).willReturn(parentAssocs);
|
||||
});
|
||||
return nodeRefMap;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user