mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merge pull request #1462 from Alfresco/feature/ACS-3377_UpdateRuleOrder
ACS-3377 Update rule order.
This commit is contained in:
@@ -59,6 +59,16 @@ public interface RuleSets
|
||||
*/
|
||||
RuleSet getRuleSetById(String folderNodeId, String ruleSetId, List<String> includes);
|
||||
|
||||
/**
|
||||
* Update a rule set - for example to reorder the rules within it.
|
||||
*
|
||||
* @param folderNodeId Folder node ID
|
||||
* @param ruleSet The updated rule set.
|
||||
* @param includes List of fields to include in the response.
|
||||
* @return The updated rule set from the server.
|
||||
*/
|
||||
RuleSet updateRuleSet(String folderNodeId, RuleSet ruleSet, List<String> includes);
|
||||
|
||||
/**
|
||||
* Link a rule set to a folder
|
||||
*/
|
||||
|
@@ -148,7 +148,7 @@ public class RuleSetLoader
|
||||
);
|
||||
}
|
||||
|
||||
private List<String> loadRuleIds(NodeRef folderNodeRef)
|
||||
public List<String> loadRuleIds(NodeRef folderNodeRef)
|
||||
{
|
||||
return ruleService.getRules(folderNodeRef, false).stream()
|
||||
.map(org.alfresco.service.cmr.rule.Rule::getNodeRef)
|
||||
|
@@ -28,8 +28,14 @@ package org.alfresco.rest.api.impl.rules;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.alfresco.util.collections.CollectionUtils.isEmpty;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.repo.rule.RuntimeRuleService;
|
||||
@@ -41,7 +47,6 @@ import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.ListPage;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.AspectMissingException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
@@ -80,6 +85,43 @@ public class RuleSetsImpl implements RuleSets
|
||||
return ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuleSet updateRuleSet(String folderNodeId, RuleSet ruleSet, List<String> includes)
|
||||
{
|
||||
// Editing the order of the rules doesn't require permission to edit the rule set itself.
|
||||
NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
|
||||
NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSet.getId(), folderNode);
|
||||
|
||||
RuleSet returnedRuleSet = ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
|
||||
|
||||
// Currently the only field that can be updated is ruleIds to reorder the rules.
|
||||
List<String> suppliedRuleIds = ruleSet.getRuleIds();
|
||||
if (!isEmpty(suppliedRuleIds))
|
||||
{
|
||||
// Check there are no duplicate rule ids in the request.
|
||||
Set<String> suppliedRuleIdSet = new HashSet<>(suppliedRuleIds);
|
||||
|
||||
// Check that the set of rule ids hasn't changed.
|
||||
Set<String> existingRuleIds = new HashSet<>(ruleSetLoader.loadRuleIds(folderNode));
|
||||
if (suppliedRuleIdSet.size() != suppliedRuleIds.size() || !suppliedRuleIdSet.equals(existingRuleIds))
|
||||
{
|
||||
throw new InvalidArgumentException("Unexpected set of rule ids - received " + suppliedRuleIds + " but expected " + existingRuleIds);
|
||||
}
|
||||
|
||||
IntStream.range(0, suppliedRuleIds.size()).forEach(index ->
|
||||
{
|
||||
NodeRef ruleNode = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, suppliedRuleIds.get(index));
|
||||
ruleService.setRulePosition(folderNode, ruleNode, index);
|
||||
});
|
||||
if (includes.contains(RuleSetLoader.RULE_IDS))
|
||||
{
|
||||
returnedRuleSet.setRuleIds(suppliedRuleIds);
|
||||
}
|
||||
}
|
||||
|
||||
return returnedRuleSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuleSetLink linkToRuleSet(String folderNodeId, String linkToNodeId)
|
||||
{
|
||||
|
@@ -28,8 +28,6 @@ package org.alfresco.rest.api.nodes;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.RuleSets;
|
||||
import org.alfresco.rest.api.model.rules.RuleSet;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
@@ -37,7 +35,6 @@ import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundE
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
@@ -50,6 +47,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
@RelationshipResource(name = "rule-sets", entityResource = NodesEntityResource.class, title = "Folder node rule sets")
|
||||
public class NodeRuleSetsRelation implements RelationshipResourceAction.Read<RuleSet>,
|
||||
RelationshipResourceAction.ReadById<RuleSet>,
|
||||
RelationshipResourceAction.Update<RuleSet>,
|
||||
InitializingBean
|
||||
{
|
||||
private RuleSets ruleSets;
|
||||
@@ -106,4 +104,20 @@ public class NodeRuleSetsRelation implements RelationshipResourceAction.Read<Rul
|
||||
{
|
||||
this.ruleSets = ruleSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule set, in particular this is useful for reordering rules in a rule set.
|
||||
* <p>
|
||||
* - PUT /nodes/{folderNodeId}/rule-sets/{ruleSetId}
|
||||
*
|
||||
* @param folderNodeId The id for the folder.
|
||||
* @param ruleSet The updated rule set.
|
||||
* @param parameters Contains information about which fields to include in the response.
|
||||
* @return The updated rule set.
|
||||
*/
|
||||
@Override
|
||||
public RuleSet update(String folderNodeId, RuleSet ruleSet, Parameters parameters)
|
||||
{
|
||||
return ruleSets.updateRuleSet(folderNodeId, ruleSet, parameters.getInclude());
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ package org.alfresco.rest.api.impl.rules;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.RULE_IDS;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
@@ -46,7 +47,6 @@ import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.AspectMissingException;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
@@ -329,4 +329,126 @@ public class RuleSetsImplTest extends TestCase
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateRuleSet()
|
||||
{
|
||||
given(ruleSetMock.getId()).willReturn(RULE_SET_ID);
|
||||
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
RuleSet ruleSetResponse = mock(RuleSet.class);
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, emptyList())).willReturn(ruleSetResponse);
|
||||
|
||||
//when
|
||||
RuleSet ruleSet = ruleSets.updateRuleSet(FOLDER_ID, ruleSetMock, emptyList());
|
||||
|
||||
assertEquals("Unexpected rule set returned.", ruleSetResponse, ruleSet);
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE);
|
||||
then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE, FOLDER_NODE, emptyList());
|
||||
}
|
||||
|
||||
/** Simulate rules being reordered from [RuleA, RuleB] to [RuleB, RuleA]. */
|
||||
@Test
|
||||
public void testUpdateRuleSet_reorderRules()
|
||||
{
|
||||
List<String> dbOrder = List.of("RuleA", "RuleB");
|
||||
List<String> newOrder = List.of("RuleB", "RuleA");
|
||||
List<String> includes = List.of(RULE_IDS);
|
||||
|
||||
RuleSet dbRuleSet = mock(RuleSet.class);
|
||||
RuleSet requestRuleSet = mock(RuleSet.class);
|
||||
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
|
||||
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
|
||||
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
|
||||
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
|
||||
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
|
||||
//when
|
||||
RuleSet ruleSet = ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes);
|
||||
|
||||
assertEquals("Unexpected rule set returned.", dbRuleSet, ruleSet);
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE);
|
||||
then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes);
|
||||
then(dbRuleSet).should().setRuleIds(newOrder);
|
||||
}
|
||||
|
||||
/** Check that we can't remove a rule by updating the rule set. */
|
||||
@Test
|
||||
public void testUpdateRuleSet_tryToChangeSetOfRuleIds()
|
||||
{
|
||||
List<String> dbOrder = List.of("RuleA", "RuleB");
|
||||
List<String> newOrder = List.of("RuleA");
|
||||
List<String> includes = List.of(RULE_IDS);
|
||||
|
||||
RuleSet dbRuleSet = mock(RuleSet.class);
|
||||
RuleSet requestRuleSet = mock(RuleSet.class);
|
||||
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
|
||||
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
|
||||
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
|
||||
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
|
||||
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
|
||||
//when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
|
||||
() -> ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes)
|
||||
);
|
||||
}
|
||||
|
||||
/** Check that we can't include a rule twice in a rule set. */
|
||||
@Test
|
||||
public void testUpdateRuleSet_DuplicateRuleId()
|
||||
{
|
||||
List<String> dbOrder = List.of("RuleA", "RuleB");
|
||||
List<String> newOrder = List.of("RuleA", "RuleB", "RuleA");
|
||||
List<String> includes = List.of(RULE_IDS);
|
||||
|
||||
RuleSet dbRuleSet = mock(RuleSet.class);
|
||||
RuleSet requestRuleSet = mock(RuleSet.class);
|
||||
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
|
||||
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
|
||||
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
|
||||
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
|
||||
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
|
||||
//when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
|
||||
() -> ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes)
|
||||
);
|
||||
}
|
||||
|
||||
/** Check that we can update the rule ids without returning them. */
|
||||
@Test
|
||||
public void testUpdateRuleSet_dontIncludeRuleIds()
|
||||
{
|
||||
List<String> dbOrder = List.of("RuleA", "RuleB");
|
||||
List<String> newOrder = List.of("RuleB", "RuleA");
|
||||
List<String> includes = emptyList();
|
||||
|
||||
RuleSet dbRuleSet = mock(RuleSet.class);
|
||||
RuleSet requestRuleSet = mock(RuleSet.class);
|
||||
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
|
||||
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
|
||||
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
|
||||
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
|
||||
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
|
||||
//when
|
||||
RuleSet ruleSet = ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes);
|
||||
|
||||
// Expect the DB rule set to be returned, but no extra fields to be populated.
|
||||
assertEquals("Unexpected rule set returned.", dbRuleSet, ruleSet);
|
||||
then(dbRuleSet).shouldHaveNoInteractions();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user