ACS-3509 Rule mappers refactor pt2 (#1428)

* ACS-3509: Fixes and refactors for rule mappers pt 2.

* ACS-3509: Rule Condition mappings refactor + tests.
This commit is contained in:
Maciej Pichura
2022-09-22 08:10:59 +02:00
committed by GitHub
parent e0d52f98ae
commit 9c8f98c12f
19 changed files with 555 additions and 569 deletions

View File

@@ -0,0 +1,151 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.mapper.rules;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.ConditionOperator;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.apache.commons.collections.CollectionUtils;
@Experimental
public class RestRuleCompositeConditionModelMapper implements RestModelMapper<CompositeCondition, ActionCondition>
{
private final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper;
public RestRuleCompositeConditionModelMapper(
RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
{
this.simpleConditionMapper = simpleConditionMapper;
}
/**
* Converts Action conditions (service POJO) list to composite condition (REST model).
*
* @param actionConditions - list of {@link ActionCondition} service POJOs
* @return {@link CompositeCondition} REST model
*/
@Override
public CompositeCondition toRestModel(final Collection<ActionCondition> actionConditions)
{
if (CollectionUtils.isEmpty(actionConditions))
{
return null;
}
final CompositeCondition conditions = new CompositeCondition();
conditions.setCompositeConditions(new ArrayList<>());
// group action conditions by inversion flag
actionConditions.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(ActionCondition::getInvertCondition))
// map action condition sub lists
.forEach((inverted, actionConditionsPart) -> Optional
.ofNullable(ofActionConditions(actionConditionsPart, inverted, ConditionOperator.AND))
// if composite condition present add to final list
.ifPresent(compositeCondition -> conditions.getCompositeConditions().add(compositeCondition)));
if (CollectionUtils.isEmpty(conditions.getCompositeConditions()))
{
conditions.setCompositeConditions(null);
}
return conditions;
}
@Override
public List<ActionCondition> toServiceModels(final CompositeCondition compositeCondition)
{
final List<ActionCondition> actionConditions = new ArrayList<>();
if (compositeCondition == null)
{
return actionConditions;
}
if (CollectionUtils.isNotEmpty(compositeCondition.getSimpleConditions()))
{
compositeCondition.getSimpleConditions()
.forEach(simpleCondition -> actionConditions.add(mapSimpleCondition(simpleCondition, compositeCondition.isInverted())));
}
if (CollectionUtils.isNotEmpty(compositeCondition.getCompositeConditions()))
{
compositeCondition.getCompositeConditions().forEach(condition -> actionConditions.addAll(toServiceModels(condition)));
}
return actionConditions;
}
private ActionCondition mapSimpleCondition(final SimpleCondition simpleCondition, final boolean inverted)
{
final ActionCondition actionCondition = simpleConditionMapper.toServiceModel(simpleCondition);
actionCondition.setInvertCondition(inverted);
return actionCondition;
}
private CompositeCondition ofActionConditions(final List<ActionCondition> actionConditions, final boolean inverted,
final ConditionOperator conditionOperator)
{
if (actionConditions == null)
{
return null;
}
return ofSimpleConditions(simpleConditionMapper.toRestModels(actionConditions), inverted, conditionOperator);
}
/**
* Creates a composite condition instance of simple conditions.
*
* @param simpleConditions - list of {@link SimpleCondition}
* @param inverted - determines if condition should be inverted
* @param conditionOperator - determines the operation, see {@link ConditionOperator}
* @return {@link CompositeCondition}
*/
private CompositeCondition ofSimpleConditions(final List<SimpleCondition> simpleConditions, final boolean inverted,
final ConditionOperator conditionOperator)
{
return of(simpleConditions, null, inverted, conditionOperator);
}
private CompositeCondition of(final List<SimpleCondition> simpleConditions, final List<CompositeCondition> compositeConditions,
final boolean inverted, final ConditionOperator conditionOperator)
{
if (CollectionUtils.isEmpty(simpleConditions) && CollectionUtils.isEmpty(compositeConditions))
{
return null;
}
return CompositeCondition.builder()
.inverted(inverted)
.booleanMode(conditionOperator)
.simpleConditions(simpleConditions)
.compositeConditions(compositeConditions)
.create();
}
}

View File

@@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.rometools.utils.Strings;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.evaluator.CompareMimeTypeEvaluator;
@@ -57,6 +58,12 @@ import org.apache.commons.collections.MapUtils;
@Experimental
public class RestRuleSimpleConditionModelMapper implements RestModelMapper<SimpleCondition, ActionCondition>
{
static final String CATEGORY_INVALID_MSG = "Category in condition is invalid";
static final String PARAM_CATEGORY = "category";
static final String PARAM_MIMETYPE = "mimetype";
static final String FIELD_NOT_NULL = "Field in condition must not be blank";
static final String PARAMETER_NOT_NULL = "Parameter in condition must not be blank";
static final String COMPARATOR_NOT_NULL = "Comparator in condition must not be blank";
private final NamespaceService namespaceService;
private final Nodes nodes;
@@ -99,14 +106,12 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
public ActionCondition toServiceModel(SimpleCondition restModel)
{
final String field = restModel.getField();
if (field == null)
{
return null;
}
checkStringNotBlank(field, FIELD_NOT_NULL);
Map<String, Serializable> parameterValues = new HashMap<>();
final Map<String, Serializable> parameterValues = new HashMap<>();
String conditionDefinitionId;
String parameter = restModel.getParameter();
final String parameter = restModel.getParameter();
checkStringNotBlank(parameter, PARAMETER_NOT_NULL);
switch (field)
{
@@ -118,21 +123,21 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
conditionDefinitionId = HasTagEvaluator.NAME;
parameterValues.put(HasTagEvaluator.PARAM_TAG, parameter);
break;
case SimpleCondition.PARAM_CATEGORY:
case PARAM_CATEGORY:
conditionDefinitionId = InCategoryEvaluator.NAME;
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_ASPECT, ContentModel.ASPECT_GEN_CLASSIFIABLE);
try
{
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, nodes.validateOrLookupNode(parameter, null));
} catch (EntityNotFoundException e) {
throw new InvalidArgumentException(SimpleCondition.CATEGORY_INVALID_MSG);
throw new InvalidArgumentException(CATEGORY_INVALID_MSG);
}
break;
case IsSubTypeEvaluator.PARAM_TYPE:
conditionDefinitionId = IsSubTypeEvaluator.NAME;
parameterValues.put(IsSubTypeEvaluator.PARAM_TYPE, QName.createQName(parameter, namespaceService));
break;
case SimpleCondition.PARAM_MIMETYPE:
case PARAM_MIMETYPE:
conditionDefinitionId = CompareMimeTypeEvaluator.NAME;
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.TYPE_CONTENT);
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, parameter);
@@ -151,6 +156,7 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
// else create common property evaluator
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, QName.createQName(field, namespaceService));
}
checkStringNotBlank(restModel.getComparator(), COMPARATOR_NOT_NULL);
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, restModel.getComparator().toUpperCase());
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, parameter);
break;
@@ -158,6 +164,13 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
return new ActionConditionImpl(UUID.randomUUID().toString(), conditionDefinitionId, parameterValues);
}
private void checkStringNotBlank(final String string, final String message) {
if (Strings.isBlank(string))
{
throw new InvalidArgumentException(message);
}
}
private static SimpleCondition createComparePropertyValueCondition(final ActionCondition actionCondition, final NamespaceService namespaceService)
{
final SimpleCondition.Builder builder = SimpleCondition.builder();
@@ -176,7 +189,7 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
private static SimpleCondition createCompareMimeTypeCondition(final ActionCondition actionCondition)
{
return SimpleCondition.builder()
.field(SimpleCondition.PARAM_MIMETYPE)
.field(PARAM_MIMETYPE)
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
.parameter(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_VALUE).toString())
.create();
@@ -203,7 +216,7 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
private static SimpleCondition createInCategoryCondition(final ActionCondition actionCondition)
{
return SimpleCondition.builder()
.field(SimpleCondition.PARAM_CATEGORY)
.field(PARAM_CATEGORY)
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
.parameter(((NodeRef) actionCondition.getParameterValues().get(InCategoryEvaluator.PARAM_CATEGORY_VALUE)).getId())
.create();

View File

@@ -28,13 +28,13 @@ package org.alfresco.rest.api.impl.rules;
import java.util.List;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.namespace.NamespaceService;
/** Responsible for creating {@link Rule} objects. */
@Experimental
@@ -43,11 +43,11 @@ public class RuleLoader
public static final String IS_SHARED = "isShared";
private RuleService ruleService;
private NodeValidator nodeValidator;
private RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper;
private RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper;
public Rule loadRule(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
{
Rule rule = Rule.from(ruleModel, simpleConditionMapper);
Rule rule = Rule.from(ruleModel, compositeConditionMapper);
if (includes != null && includes.contains(IS_SHARED))
{
NodeRef ruleSet = ruleService.getRuleSetNode(ruleModel.getNodeRef());
@@ -67,9 +67,9 @@ public class RuleLoader
this.nodeValidator = nodeValidator;
}
public void setSimpleConditionMapper(
RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
public void setCompositeConditionMapper(
RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper)
{
this.simpleConditionMapper = simpleConditionMapper;
this.compositeConditionMapper = compositeConditionMapper;
}
}

View File

@@ -33,6 +33,7 @@ import java.util.stream.Collectors;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
@@ -63,7 +64,7 @@ public class RulesImpl implements Rules
private RuleLoader ruleLoader;
private ActionParameterConverter actionParameterConverter;
private ActionPermissionValidator actionPermissionValidator;
private RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper;
private RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper;
@Override
public CollectionWithPagingInfo<Rule> getRules(final String folderNodeId,
@@ -137,7 +138,7 @@ public class RulesImpl implements Rules
{
throw new InvalidArgumentException(MUST_HAVE_AT_LEAST_ONE_ACTION);
}
final org.alfresco.service.cmr.rule.Rule serviceModelRule = rule.toServiceModel(nodes, simpleConditionMapper);
final org.alfresco.service.cmr.rule.Rule serviceModelRule = rule.toServiceModel(nodes, compositeConditionMapper);
final CompositeAction compositeAction = (CompositeAction) serviceModelRule.getAction();
compositeAction.getActions().forEach(action -> action.setParameterValues(
actionParameterConverter.getConvertedParams(action.getParameterValues(), action.getActionDefinitionName())));
@@ -188,9 +189,9 @@ public class RulesImpl implements Rules
this.actionPermissionValidator = actionPermissionValidator;
}
public void setSimpleConditionMapper(
RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
public void setCompositeConditionMapper(
RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper)
{
this.simpleConditionMapper = simpleConditionMapper;
this.compositeConditionMapper = compositeConditionMapper;
}
}

View File

@@ -36,8 +36,12 @@ import org.apache.commons.lang3.NotImplementedException;
@Experimental
public interface RestModelMapper<R, S>
{
R toRestModel(S serviceModel);
S toServiceModel(R restModel);
default R toRestModel(S serviceModel) {
throw new NotImplementedException();
}
default S toServiceModel(R restModel) {
throw new NotImplementedException();
}
default R toRestModel(Collection<S> serviceModels) {
throw new NotImplementedException();
}
@@ -50,4 +54,10 @@ public interface RestModelMapper<R, S>
default List<S> toServiceModels(Collection<R> restModels) {
return restModels.stream().map(this::toServiceModel).collect(Collectors.toList());
}
default List<R> toRestModels(S serviceModel) {
throw new NotImplementedException();
}
default List<S> toServiceModels(R restModel) {
throw new NotImplementedException();
}
}

View File

@@ -26,16 +26,10 @@
package org.alfresco.rest.api.model.rules;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.apache.commons.collections.CollectionUtils;
@Experimental
public class CompositeCondition
@@ -45,91 +39,6 @@ public class CompositeCondition
private List<CompositeCondition> compositeConditions;
private List<SimpleCondition> simpleConditions;
/**
* Converts Action conditions (service POJO) list to composite condition (REST model).
*
* @param actionConditions - list of {@link ActionCondition} service POJOs
* @return {@link CompositeCondition} REST model
*/
public static CompositeCondition from(final List<ActionCondition> actionConditions, final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
{
if (actionConditions == null)
{
return null;
}
final CompositeCondition conditions = new CompositeCondition();
conditions.compositeConditions = new ArrayList<>();
// group action conditions by inversion flag
actionConditions.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(ActionCondition::getInvertCondition))
// map action condition sub lists
.forEach((inverted, actionConditionsPart) -> Optional.ofNullable(CompositeCondition.ofActionConditions(actionConditionsPart, simpleConditionMapper, inverted, ConditionOperator.AND))
// if composite condition present add to final list
.ifPresent(compositeCondition -> conditions.compositeConditions.add(compositeCondition)));
if (conditions.compositeConditions.isEmpty()) {
conditions.compositeConditions = null;
}
return conditions;
}
private static CompositeCondition ofActionConditions(final List<ActionCondition> actionConditions,
final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper,
final boolean inverted, final ConditionOperator conditionOperator)
{
if (actionConditions == null)
{
return null;
}
return ofSimpleConditions(SimpleCondition.listOf(actionConditions, simpleConditionMapper), inverted, conditionOperator);
}
/**
* Creates a composite condition instance of simple conditions.
*
* @param simpleConditions - list of {@link SimpleCondition}
* @param inverted - determines if condition should be inverted
* @param conditionOperator - determines the operation, see {@link ConditionOperator}
* @return {@link CompositeCondition}
*/
public static CompositeCondition ofSimpleConditions(final List<SimpleCondition> simpleConditions, final boolean inverted, final ConditionOperator conditionOperator)
{
return of(simpleConditions, null, inverted, conditionOperator);
}
private static CompositeCondition of(final List<SimpleCondition> simpleConditions, final List<CompositeCondition> compositeConditions,
final boolean inverted, final ConditionOperator conditionOperator)
{
if (CollectionUtils.isEmpty(simpleConditions) && CollectionUtils.isEmpty(compositeConditions))
{
return null;
}
return builder()
.inverted(inverted)
.booleanMode(conditionOperator)
.simpleConditions(simpleConditions)
.compositeConditions(compositeConditions)
.create();
}
public List<ActionCondition> toServiceModels(final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
{
final List<ActionCondition> actionConditions = new ArrayList<>();
if (CollectionUtils.isNotEmpty(simpleConditions))
{
simpleConditions.forEach(simpleCondition -> actionConditions.add(simpleCondition.toServiceModel(inverted, simpleConditionMapper)));
}
if (CollectionUtils.isNotEmpty(compositeConditions))
{
compositeConditions.forEach(compositeCondition -> actionConditions.addAll(compositeCondition.toServiceModels(simpleConditionMapper)));
}
return actionConditions;
}
public boolean isInverted()
{
return inverted;

View File

@@ -63,7 +63,7 @@ public class Rule
* @param ruleModel - {@link org.alfresco.service.cmr.rule.Rule} service POJO
* @return {@link Rule} REST model
*/
public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel, final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel, final RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper)
{
if (ruleModel == null)
{
@@ -86,7 +86,7 @@ public class Rule
}
if (ruleModel.getAction() != null)
{
builder.conditions(CompositeCondition.from(ruleModel.getAction().getActionConditions(), simpleConditionMapper));
builder.conditions(compositeConditionMapper.toRestModel(ruleModel.getAction().getActionConditions()));
if (ruleModel.getAction().getCompensatingAction() != null && ruleModel.getAction().getCompensatingAction().getParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF) != null)
{
builder.errorScript(ruleModel.getAction().getCompensatingAction().getParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF).toString());
@@ -106,7 +106,7 @@ public class Rule
* @param nodes The nodes API.
* @return The rule service POJO.
*/
public org.alfresco.service.cmr.rule.Rule toServiceModel(final Nodes nodes, final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
public org.alfresco.service.cmr.rule.Rule toServiceModel(final Nodes nodes, final RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper)
{
final org.alfresco.service.cmr.rule.Rule ruleModel = new org.alfresco.service.cmr.rule.Rule();
final NodeRef nodeRef = (id != null) ? nodes.validateOrLookupNode(id, null) : null;
@@ -129,7 +129,7 @@ public class Rule
}
if (conditions != null)
{
conditions.toServiceModels(simpleConditionMapper).forEach(condition -> ruleModel.getAction().addActionCondition(condition));
compositeConditionMapper.toServiceModels(conditions).forEach(condition -> ruleModel.getAction().addActionCondition(condition));
}
return ruleModel;

View File

@@ -59,49 +59,10 @@ import org.apache.commons.collections.CollectionUtils;
@Experimental
public class SimpleCondition
{
public static final String CATEGORY_INVALID_MSG = "Category in condition is invalid";
public static final String PARAM_CATEGORY = "category";
public static final String PARAM_MIMETYPE = "mimetype";
private String field;
private String comparator;
private String parameter;
/**
* Converts list of service POJO action conditions to list of REST model simple conditions.
*
* @param actionConditions - list of {@link ActionCondition} service POJOs
* @return list of {@link SimpleCondition} REST models
*/
public static List<SimpleCondition> listOf(final List<ActionCondition> actionConditions,
final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
{
if (CollectionUtils.isEmpty(actionConditions))
{
return null;
}
return simpleConditionMapper.toRestModels(actionConditions);
}
/**
* Creates simple condition REST model instance from service POJO action condition.
*
* @param actionCondition - {@link ActionCondition} service POJO
* @return {@link SimpleCondition} REST model
*/
public static SimpleCondition from(final ActionCondition actionCondition,
final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper)
{
return simpleConditionMapper.toRestModel(actionCondition);
}
public ActionCondition toServiceModel(final boolean inverted, final RestModelMapper<SimpleCondition, ActionCondition> mapper)
{
final ActionCondition actionCondition = mapper.toServiceModel(this);
actionCondition.setInvertCondition(inverted);
return actionCondition;
}
public String getField()
{
return field;

View File

@@ -887,7 +887,7 @@
<bean id="ruleLoader" class="org.alfresco.rest.api.impl.rules.RuleLoader">
<property name="ruleService" ref="RuleService" />
<property name="nodeValidator" ref="nodeValidator" />
<property name="simpleConditionMapper" ref="simpleConditionMapper"/>
<property name="compositeConditionMapper" ref="compositeConditionMapper"/>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRuleSetsRelation">
@@ -911,7 +911,7 @@
<property name="ruleLoader" ref="ruleLoader"/>
<property name="actionParameterConverter" ref="actionParameterConverter"/>
<property name="actionPermissionValidator" ref="actionPermissionValidator"/>
<property name="simpleConditionMapper" ref="simpleConditionMapper"/>
<property name="compositeConditionMapper" ref="compositeConditionMapper"/>
</bean>
<bean id="Rules" class="org.springframework.aop.framework.ProxyFactoryBean">
@@ -951,6 +951,9 @@
<constructor-arg name="namespaceService" ref="NamespaceService"/>
<constructor-arg name="nodes" ref="Nodes"/>
</bean>
<bean id="compositeConditionMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleCompositeConditionModelMapper">
<constructor-arg name="simpleConditionMapper" ref="simpleConditionMapper"/>
</bean>
<bean id="publicapi.mimeTypePropertyLookup" class="org.alfresco.rest.api.lookups.MimeTypePropertyLookup">
<property name="serviceRegistry" ref="ServiceRegistry"/>

View File

@@ -26,6 +26,7 @@
package org.alfresco.rest.api;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleCompositeConditionModelMapperTest;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapperTest;
import org.alfresco.rest.api.impl.rules.ActionParameterConverterTest;
import org.alfresco.rest.api.impl.rules.ActionPermissionValidatorTest;
@@ -33,10 +34,8 @@ import org.alfresco.rest.api.impl.rules.NodeValidatorTest;
import org.alfresco.rest.api.impl.rules.RuleLoaderTest;
import org.alfresco.rest.api.impl.rules.RuleSetsImplTest;
import org.alfresco.rest.api.model.rules.ActionTest;
import org.alfresco.rest.api.model.rules.CompositeConditionTest;
import org.alfresco.rest.api.impl.rules.RulesImplTest;
import org.alfresco.rest.api.model.rules.RuleTest;
import org.alfresco.rest.api.model.rules.SimpleConditionTest;
import org.alfresco.rest.api.nodes.NodeRulesRelationTest;
import org.alfresco.service.Experimental;
import org.junit.runner.RunWith;
@@ -51,12 +50,11 @@ import org.junit.runners.Suite;
NodeValidatorTest.class,
RuleTest.class,
ActionTest.class,
SimpleConditionTest.class,
CompositeConditionTest.class,
RuleLoaderTest.class,
ActionParameterConverterTest.class,
ActionPermissionValidatorTest.class,
RestRuleSimpleConditionModelMapperTest.class
RestRuleSimpleConditionModelMapperTest.class,
RestRuleCompositeConditionModelMapperTest.class
})
public class RulesUnitTests
{

View File

@@ -0,0 +1,238 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.mapper.rules;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.ConditionOperator;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class RestRuleCompositeConditionModelMapperTest
{
@Mock
private RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapperMock;
@InjectMocks
RestRuleCompositeConditionModelMapper objectUnderTest;
@Test
public void testToRestModel()
{
final List<ActionCondition> actionConditions = List.of(
createActionCondition("value1"),
createActionCondition("value3"),
createActionCondition("value2", true)
);
final List<SimpleCondition> simpleConditions = List.of(
createSimpleCondition("value1"),
createSimpleCondition("value3"),
createSimpleCondition("value2")
);
final CompositeCondition expectedCompositeCondition = createCompositeCondition(List.of(
createCompositeCondition(false, simpleConditions.subList(0,2)),
createCompositeCondition(true, simpleConditions.subList(2,3))
));
when(simpleConditionMapperMock.toRestModels(actionConditions.subList(0,2))).thenReturn(simpleConditions.subList(0,2));
when(simpleConditionMapperMock.toRestModels(actionConditions.subList(2,3))).thenReturn(simpleConditions.subList(2,3));
// when
final CompositeCondition actualCompositeCondition = objectUnderTest.toRestModel(actionConditions);
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
}
@Test
public void testToRestModel_fromEmptyList()
{
final List<ActionCondition> actionConditions = Collections.emptyList();
// when
final CompositeCondition actualCompositeCondition = objectUnderTest.toRestModel(actionConditions);
assertThat(actualCompositeCondition).isNull();
}
@Test
public void testToRestModel_fromNullValue()
{
// when
final CompositeCondition actualCompositeCondition = objectUnderTest.toRestModel((Collection<ActionCondition>) null);
assertThat(actualCompositeCondition).isNull();
}
@Test
public void testToRestModel_fromListContainingNull()
{
final List<ActionCondition> actionConditions = new ArrayList<>();
actionConditions.add(null);
final CompositeCondition expectedCompositeCondition = CompositeCondition.builder().create();
// when
final CompositeCondition actualCompositeCondition = objectUnderTest.toRestModel(actionConditions);
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
}
@Test
public void testToServiceModels() {
final List<SimpleCondition> simpleConditions = List.of(
createSimpleCondition("value1"),
createSimpleCondition("value3"),
createSimpleCondition("value2")
);
final CompositeCondition compositeCondition = createCompositeCondition(List.of(
createCompositeCondition(false, simpleConditions.subList(0,2)),
createCompositeCondition(true, simpleConditions.subList(2,3))
));
final List<ActionCondition> actionConditions = List.of(
createActionCondition("value1"),
createActionCondition("value3"),
createActionCondition("value2", true)
);
IntStream.rangeClosed(0, 2)
.forEach(i -> when(simpleConditionMapperMock.toServiceModel(simpleConditions.get(i))).thenReturn(actionConditions.get(i)));
final List<ActionCondition> actualActionConditions = objectUnderTest.toServiceModels(compositeCondition);
assertThat(actualActionConditions).isEqualTo(actionConditions);
}
@Test
public void testToServiceModels_simpleNonInvertedConditionsOnly() {
final List<SimpleCondition> simpleConditions = List.of(
createSimpleCondition("value1"),
createSimpleCondition("value2"),
createSimpleCondition("value3")
);
final CompositeCondition compositeCondition = createCompositeCondition(false, simpleConditions);
final List<ActionCondition> actionConditions = List.of(
createActionCondition("value1"),
createActionCondition("value2"),
createActionCondition("value3")
);
IntStream.rangeClosed(0, 2)
.forEach(i -> when(simpleConditionMapperMock.toServiceModel(simpleConditions.get(i))).thenReturn(actionConditions.get(i)));
final List<ActionCondition> actualActionConditions = objectUnderTest.toServiceModels(compositeCondition);
assertThat(actualActionConditions).isEqualTo(actionConditions);
}
@Test
public void testToServiceModels_nullSimpleConditions() {
final CompositeCondition compositeCondition = createCompositeCondition(false, null);
final List<ActionCondition> actualActionConditions = objectUnderTest.toServiceModels(compositeCondition);
assertThat(actualActionConditions).isNotNull().isEmpty();
}
@Test
public void testToServiceModels_emptyCompositeCondition() {
final CompositeCondition compositeCondition = CompositeCondition.builder().create();
final List<ActionCondition> actualActionConditions = objectUnderTest.toServiceModels(compositeCondition);
assertThat(actualActionConditions).isNotNull().isEmpty();
}
@Test
public void testToServiceModels_nullCompositeCondition() {
final CompositeCondition compositeCondition = null;
final List<ActionCondition> actualActionConditions = objectUnderTest.toServiceModels(compositeCondition);
assertThat(actualActionConditions).isNotNull().isEmpty();
}
private static ActionCondition createActionCondition(final String value)
{
return createActionCondition(value, false);
}
private static ActionCondition createActionCondition(final String value, final boolean inverted)
{
final ActionCondition actionCondition = new ActionConditionImpl("fake-id", ComparePropertyValueEvaluator.NAME);
actionCondition.setInvertCondition(inverted);
final Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY, "content-property");
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, "operation");
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, value);
actionCondition.setParameterValues(parameterValues);
return actionCondition;
}
private static SimpleCondition createSimpleCondition(final String value) {
return SimpleCondition.builder()
.field("content-property")
.comparator("operation")
.parameter(value)
.create();
}
private static CompositeCondition createCompositeCondition(final List<CompositeCondition> compositeConditions) {
return createCompositeCondition(false, ConditionOperator.AND, compositeConditions, null);
}
private static CompositeCondition createCompositeCondition(final boolean inverted, final List<SimpleCondition> simpleConditions) {
return createCompositeCondition(inverted, ConditionOperator.AND, null, simpleConditions);
}
private static CompositeCondition createCompositeCondition(final boolean inverted, final ConditionOperator conditionOperator,
final List<CompositeCondition> compositeConditions, final List<SimpleCondition> simpleConditions) {
return CompositeCondition.builder()
.inverted(inverted)
.booleanMode(conditionOperator)
.compositeConditions(compositeConditions)
.simpleConditions(simpleConditions)
.create();
}
}

View File

@@ -26,19 +26,25 @@
package org.alfresco.rest.api.impl.mapper.rules;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.COMPARATOR_NOT_NULL;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.FIELD_NOT_NULL;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.PARAMETER_NOT_NULL;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.PARAM_CATEGORY;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.PARAM_MIMETYPE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.BDDMockito.given;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import junit.framework.TestCase;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.evaluator.CompareMimeTypeEvaluator;
@@ -54,6 +60,7 @@ import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation;
import org.alfresco.repo.action.evaluator.compare.ContentPropertyName;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -69,7 +76,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class RestRuleSimpleConditionModelMapperTest extends TestCase
public class RestRuleSimpleConditionModelMapperTest
{
private static final boolean NULL_RESULT = true;
private static final String PARAMETER_DEFAULT = "value";
@@ -156,7 +163,8 @@ public class RestRuleSimpleConditionModelMapperTest extends TestCase
public void testToRestModelListOfNullActionConditions()
{
// when
assertThatExceptionOfType(NullPointerException.class).isThrownBy(() -> objectUnderTest.toRestModels(null));
assertThatExceptionOfType(NullPointerException.class).isThrownBy(() -> objectUnderTest.toRestModels(
(Collection<ActionCondition>) null));
}
@Test
@@ -212,7 +220,7 @@ public class RestRuleSimpleConditionModelMapperTest extends TestCase
@Test
public void testToServiceModel_compareMimetype()
{
final SimpleCondition simpleCondition = createSimpleCondition(SimpleCondition.PARAM_MIMETYPE);
final SimpleCondition simpleCondition = createSimpleCondition(PARAM_MIMETYPE);
// when
final ActionCondition actualActionCondition = objectUnderTest.toServiceModel(simpleCondition);
@@ -264,7 +272,7 @@ public class RestRuleSimpleConditionModelMapperTest extends TestCase
@Test
public void testToServiceModel_inCategory()
{
final SimpleCondition simpleCondition = createSimpleCondition(SimpleCondition.PARAM_CATEGORY);
final SimpleCondition simpleCondition = createSimpleCondition(PARAM_CATEGORY);
final NodeRef defaultNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARAMETER_DEFAULT);
given(nodesMock.validateOrLookupNode(PARAMETER_DEFAULT, null)).willReturn(defaultNodeRef);
@@ -297,6 +305,67 @@ public class RestRuleSimpleConditionModelMapperTest extends TestCase
.isEqualTo(expectedActionCondition);
}
@Test
public void testToServiceModel_nullOrBlankParameter()
{
final SimpleCondition simpleConditionNullParam = createSimpleCondition(IsSubTypeEvaluator.PARAM_TYPE, null);
// when
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionNullParam))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(PARAMETER_NOT_NULL);
final SimpleCondition simpleConditionEmptyParam = createSimpleCondition(IsSubTypeEvaluator.PARAM_TYPE, " ");
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionEmptyParam))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(PARAMETER_NOT_NULL);
}
@Test
public void testToServiceModel_nullOrEmptyField()
{
final SimpleCondition simpleConditionNullField = createSimpleCondition(null);
// when
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionNullField))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(FIELD_NOT_NULL);
final SimpleCondition simpleConditionEmptyField = createSimpleCondition("");
// when
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionEmptyField))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(FIELD_NOT_NULL);
}
@Test
public void testToServiceModel_nullOrEmptyComparatorWhenRequired()
{
final SimpleCondition simpleConditionNullComparator = SimpleCondition.builder()
.field("size")
.comparator(null)
.parameter("65000")
.create();
// when
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionNullComparator))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(COMPARATOR_NOT_NULL);
final SimpleCondition simpleConditionEmptyComparator = SimpleCondition.builder()
.field("size")
.comparator(" ")
.parameter("65000")
.create();
// when
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionEmptyComparator))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(COMPARATOR_NOT_NULL);
}
private static ActionCondition createActionCondition(final String actionDefinitionName)
{
return new ActionConditionImpl("fake-id", actionDefinitionName, createParameterValues());

View File

@@ -51,6 +51,7 @@ import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
@@ -91,7 +92,7 @@ public class RulesImplTest extends TestCase
@Mock
private Nodes nodesMock;
@Mock
private RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapperMock;
private RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapperMock;
@Mock
private NodeValidator nodeValidatorMock;
@Mock
@@ -297,7 +298,7 @@ public class RulesImplTest extends TestCase
public void testCreateRules()
{
List<Rule> ruleList = List.of(ruleMock);
given(ruleMock.toServiceModel(nodesMock, simpleConditionMapperMock)).willReturn(serviceRuleMock);
given(ruleMock.toServiceModel(nodesMock, compositeConditionMapperMock)).willReturn(serviceRuleMock);
given(ruleMock.getActions()).willReturn(List.of(actionMock));
given(serviceRuleMock.getAction()).willReturn(compositeAction);
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
@@ -314,7 +315,7 @@ public class RulesImplTest extends TestCase
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock, simpleConditionMapperMock));
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock, compositeConditionMapperMock));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
List<Rule> expected = List.of(ruleMock);
assertThat(actual).isEqualTo(expected);
@@ -327,7 +328,7 @@ public class RulesImplTest extends TestCase
public void testCreateRules_defaultRuleSet()
{
List<Rule> ruleList = List.of(ruleMock);
given(ruleMock.toServiceModel(nodesMock, simpleConditionMapperMock)).willReturn(serviceRuleMock);
given(ruleMock.toServiceModel(nodesMock, compositeConditionMapperMock)).willReturn(serviceRuleMock);
given(ruleMock.getActions()).willReturn(List.of(actionMock));
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
@@ -343,7 +344,7 @@ public class RulesImplTest extends TestCase
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock, simpleConditionMapperMock));
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock, compositeConditionMapperMock));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
List<Rule> expected = List.of(ruleMock);
assertThat(actual).isEqualTo(expected);
@@ -374,7 +375,7 @@ public class RulesImplTest extends TestCase
given(ruleBodyMock.getActions()).willReturn(List.of(actionMock));
ruleBodyList.add(ruleBodyMock);
org.alfresco.service.cmr.rule.Rule serviceRuleMockInner = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleBodyMock.toServiceModel(nodesMock, simpleConditionMapperMock)).willReturn(serviceRuleMockInner);
given(ruleBodyMock.toServiceModel(nodesMock, compositeConditionMapperMock)).willReturn(serviceRuleMockInner);
final CompositeAction compositeActionInner = new CompositeActionImpl(RULE_NODE_REF, "compositeActionInnerId");
compositeActionInner.addAction(new ActionImpl(FOLDER_NODE_REF, "actionInnerId", ACTION_DEFINITION_NAME, DUMMY_PARAMS));
given(serviceRuleMockInner.getAction()).willReturn(compositeActionInner);
@@ -393,8 +394,9 @@ public class RulesImplTest extends TestCase
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
for (Rule ruleBody : ruleBodyList)
{
then(actionPermissionValidatorMock).should().validateRulePermissions(ruleBody.toServiceModel(nodesMock, simpleConditionMapperMock));
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleBody.toServiceModel(nodesMock, simpleConditionMapperMock));
then(actionPermissionValidatorMock).should().validateRulePermissions(ruleBody.toServiceModel(nodesMock,
compositeConditionMapperMock));
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleBody.toServiceModel(nodesMock, compositeConditionMapperMock));
}
then(actionParameterConverterMock).should(times(3)).getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
@@ -468,7 +470,7 @@ public class RulesImplTest extends TestCase
@Test
public void testUpdateRuleById()
{
given(ruleMock.toServiceModel(nodesMock, simpleConditionMapperMock)).willReturn(serviceRuleMock);
given(ruleMock.toServiceModel(nodesMock, compositeConditionMapperMock)).willReturn(serviceRuleMock);
given(ruleMock.getActions()).willReturn(List.of(actionMock));
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(a -> a.getArguments()[1]);
given(serviceRuleMock.getAction()).willReturn(compositeAction);

View File

@@ -1,193 +0,0 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.model.rules;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class CompositeConditionTest
{
private final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper = mock(RestRuleSimpleConditionModelMapper.class);
@Test
public void testFrom()
{
final List<ActionCondition> actionConditions = List.of(
createActionCondition("value1"),
createActionCondition("value3"),
createActionCondition("value2", true)
);
final List<SimpleCondition> simpleConditions = List.of(
createSimpleCondition("value1"),
createSimpleCondition("value3"),
createSimpleCondition("value2")
);
final CompositeCondition expectedCompositeCondition = createCompositeCondition(List.of(
createCompositeCondition(false, simpleConditions.subList(0,2)),
createCompositeCondition(true, simpleConditions.subList(2,3))
));
Mockito.when(simpleConditionMapper.toRestModels(actionConditions.subList(0,2))).thenReturn(simpleConditions.subList(0,2));
Mockito.when(simpleConditionMapper.toRestModels(actionConditions.subList(2,3))).thenReturn(simpleConditions.subList(2,3));
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions, simpleConditionMapper);
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
}
@Test
public void testFromEmptyList()
{
final List<ActionCondition> actionConditions = Collections.emptyList();
final CompositeCondition expectedCompositeCondition = CompositeCondition.builder().create();
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions, simpleConditionMapper);
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
}
@Test
public void testFromNullValue()
{
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.from(null, simpleConditionMapper);
assertThat(actualCompositeCondition).isNull();
}
@Test
public void testFromListContainingNull()
{
final List<ActionCondition> actionConditions = new ArrayList<>();
actionConditions.add(null);
final CompositeCondition expectedCompositeCondition = CompositeCondition.builder().create();
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions, simpleConditionMapper);
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
}
@Test
public void testOfSimpleConditions()
{
final List<SimpleCondition> simpleConditions = List.of(SimpleCondition.builder().field("field").comparator("comparator").parameter("param").create());
final boolean inverted = true;
final ConditionOperator conditionOperator = ConditionOperator.OR;
final CompositeCondition expectedCondition = createCompositeCondition(inverted, conditionOperator, null, simpleConditions);
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.ofSimpleConditions(simpleConditions, inverted, conditionOperator);
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCondition);
}
@Test
public void testOfEmptySimpleConditions()
{
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.ofSimpleConditions(Collections.emptyList(), false, ConditionOperator.AND);
assertThat(actualCompositeCondition).isNull();
}
@Test
public void testOfNullSimpleConditions()
{
// when
final CompositeCondition actualCompositeCondition = CompositeCondition.ofSimpleConditions(null, false, ConditionOperator.AND);
assertThat(actualCompositeCondition).isNull();
}
private static ActionCondition createActionCondition(final String value)
{
return createActionCondition(value, false);
}
private static ActionCondition createActionCondition(final String value, final boolean inverted)
{
final ActionCondition actionCondition = new ActionConditionImpl("fake-id", ComparePropertyValueEvaluator.NAME);
actionCondition.setInvertCondition(inverted);
final Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY, "content-property");
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, "operation");
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, value);
actionCondition.setParameterValues(parameterValues);
return actionCondition;
}
private static SimpleCondition createSimpleCondition(final String value) {
return SimpleCondition.builder()
.field("content-property")
.comparator("operation")
.parameter(value)
.create();
}
private static CompositeCondition createCompositeCondition(final List<CompositeCondition> compositeConditions) {
return createCompositeCondition(false, ConditionOperator.AND, compositeConditions, null);
}
private static CompositeCondition createCompositeCondition(final boolean inverted, final List<SimpleCondition> simpleConditions) {
return createCompositeCondition(inverted, ConditionOperator.AND, null, simpleConditions);
}
private static CompositeCondition createCompositeCondition(final boolean inverted, final ConditionOperator conditionOperator,
final List<CompositeCondition> compositeConditions, final List<SimpleCondition> simpleConditions) {
return CompositeCondition.builder()
.inverted(inverted)
.booleanMode(conditionOperator)
.compositeConditions(compositeConditions)
.simpleConditions(simpleConditions)
.create();
}
}

View File

@@ -37,6 +37,7 @@ import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleCompositeConditionModelMapper;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.service.Experimental;
@@ -44,7 +45,6 @@ import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleType;
import org.alfresco.service.namespace.NamespaceService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@@ -63,7 +63,7 @@ public class RuleTest
private static final String ACTION_DEFINITION_NAME = "action-def-name";
private static final String ERROR_SCRIPT = "error-script-ref";
private final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapper = mock(RestRuleSimpleConditionModelMapper.class);
private final RestModelMapper<CompositeCondition, ActionCondition> compositeConditionMapper = mock(RestRuleCompositeConditionModelMapper.class);
@Test
public void testFrom()
@@ -72,7 +72,7 @@ public class RuleTest
final Rule expectedRule = createRuleWithDefaultValues();
// when
final Rule actualRule = Rule.from(ruleModel, simpleConditionMapper);
final Rule actualRule = Rule.from(ruleModel, compositeConditionMapper);
assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
@@ -85,7 +85,7 @@ public class RuleTest
final Rule expectedRule = Rule.builder().enabled(true).create();
// when
final Rule actualRule = Rule.from(ruleModel, simpleConditionMapper);
final Rule actualRule = Rule.from(ruleModel, compositeConditionMapper);
assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
@@ -101,7 +101,7 @@ public class RuleTest
final org.alfresco.service.cmr.action.Action expectedCompensatingActionModel = createCompensatingActionModel();
// when
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock, simpleConditionMapper);
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock, compositeConditionMapper);
then(nodesMock).should().validateOrLookupNode(RULE_ID, null);
then(nodesMock).shouldHaveNoMoreInteractions();
@@ -126,7 +126,7 @@ public class RuleTest
expectedRuleModel.setRuleDisabled(true);
// when
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock, simpleConditionMapper);
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock, compositeConditionMapper);
then(nodesMock).shouldHaveNoInteractions();
assertThat(actualRuleModel)
@@ -146,7 +146,7 @@ public class RuleTest
.asynchronous(RULE_ASYNC)
.triggers(List.of(RuleTrigger.INBOUND, RuleTrigger.UPDATE))
.errorScript(ERROR_SCRIPT)
.conditions(CompositeCondition.from(Collections.emptyList(), simpleConditionMapper))
.conditions(compositeConditionMapper.toRestModel(Collections.emptyList()))
.create();
}

View File

@@ -1,169 +0,0 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.model.rules;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class SimpleConditionTest
{
private static final boolean INVERTED = true;
private static final String VALUE = "value";
private static final String KEY = "key";
private final RestModelMapper<SimpleCondition, ActionCondition> simpleConditionMapperMock = mock(RestRuleSimpleConditionModelMapper.class);
@Test
public void testFrom()
{
final ActionCondition actionCondition = createActionCondition(ComparePropertyValueEvaluator.NAME);
final SimpleCondition simpleConditionMock = mock(SimpleCondition.class);
given(simpleConditionMapperMock.toRestModel(actionCondition)).willReturn(simpleConditionMock);
//when
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition, simpleConditionMapperMock);
then(simpleConditionMapperMock).should().toRestModel(actionCondition);
then(simpleConditionMapperMock).shouldHaveNoMoreInteractions();
assertThat(actualSimpleCondition).isEqualTo(simpleConditionMock);
}
@Test
public void testListOf()
{
final List<ActionCondition> actionConditionsMock = mock(List.class);
final List<SimpleCondition> simpleConditionsMock = mock(List.class);
given(simpleConditionMapperMock.toRestModels(actionConditionsMock)).willReturn(simpleConditionsMock);
// when
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(actionConditionsMock, simpleConditionMapperMock);
then(simpleConditionMapperMock).should().toRestModels(actionConditionsMock);
then(simpleConditionMapperMock).shouldHaveNoMoreInteractions();
assertThat(actualSimpleConditions)
.isNotNull()
.containsExactlyElementsOf(simpleConditionsMock);
}
@Test
public void testListOfEmptyActionConditions()
{
// when
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(Collections.emptyList(), simpleConditionMapperMock);
assertThat(actualSimpleConditions).isNull();
}
@Test
public void testListOfNullActionConditions()
{
// when
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(null, simpleConditionMapperMock);
then(simpleConditionMapperMock).shouldHaveNoInteractions();
assertThat(actualSimpleConditions).isNull();
}
@Test
public void testListOfActionConditionsContainingNull()
{
final List<ActionCondition> actionConditions = new ArrayList<>();
actionConditions.add(null);
// when
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(actionConditions, simpleConditionMapperMock);
then(simpleConditionMapperMock).should().toRestModels(actionConditions);
then(simpleConditionMapperMock).shouldHaveNoMoreInteractions();
assertThat(actualSimpleConditions).isNotNull().isEmpty();
}
@Test
public void testToServiceModel_notInverted()
{
final SimpleCondition simpleCondition = createSimpleCondition("field");
final ActionCondition actionCondition = createActionCondition(ComparePropertyValueEvaluator.NAME);
given(simpleConditionMapperMock.toServiceModel(simpleCondition)).willReturn(actionCondition);
// when
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(!INVERTED, simpleConditionMapperMock);
assertThat(actualActionCondition).isEqualTo(actionCondition);
}
@Test
public void testToServiceModel_inverted()
{
final SimpleCondition simpleCondition = createSimpleCondition("field");
final ActionCondition actionCondition = createActionCondition(ComparePropertyValueEvaluator.NAME);
given(simpleConditionMapperMock.toServiceModel(simpleCondition)).willReturn(actionCondition);
// when
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(INVERTED, simpleConditionMapperMock);
assertThat(actualActionCondition).isEqualTo(actionCondition);
}
private static ActionCondition createActionCondition(final String actionDefinitionName)
{
return new ActionConditionImpl("fake-id", actionDefinitionName, Map.of(KEY, VALUE));
}
private static SimpleCondition createSimpleCondition(final String field)
{
return createSimpleCondition(field, VALUE);
}
private static SimpleCondition createSimpleCondition(final String field, final String parameter)
{
return SimpleCondition.builder()
.field(field)
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
.parameter(parameter)
.create();
}
}