From ec25c0a049550e53d99e40cdaf32c505af74401f Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 9 Jun 2020 14:06:13 +0200 Subject: [PATCH] Document expression evaluators Expression evaluators are now a bit more documented. Some of them were slightly refactored to improve understandability. This is a preparation for MID-6275 implementation. --- .../AbstractSearchExpressionEvaluator.java | 20 +- ...gnmentTargetSearchExpressionEvaluator.java | 3 + ...ssociationFromLinkExpressionEvaluator.java | 142 ++++++----- ...iationTargetSearchExpressionEvaluator.java | 2 + .../evaluator/ConstExpressionEvaluator.java | 16 +- .../FunctionExpressionEvaluator.java | 221 ++++++++++-------- .../GenerateExpressionEvaluator.java | 199 ++++++++-------- .../ReferenceSearchExpressionEvaluator.java | 3 + .../path/PathExpressionEvaluator.java | 2 + .../script/ScriptExpressionEvaluator.java | 2 + .../model/common/mapping/MappingBuilder.java | 15 +- .../model/common/mapping/MappingImpl.java | 12 +- .../model/common/mapping/MappingParser.java | 6 +- .../model/common/util/PopulatorUtil.java | 2 +- .../common/mapping/MappingTestEvaluator.java | 4 +- .../impl/expr/MidpointFunctionsImpl.java | 2 +- .../SequentialValueExpressionEvaluator.java | 63 +++-- ...entialValueExpressionEvaluatorFactory.java | 8 +- .../EvaluatedOutboundConstructionImpl.java | 8 +- .../ProjectionCredentialsProcessor.java | 6 +- .../projector/focus/InboundProcessor.java | 10 +- .../projector/mappings/MappingEvaluator.java | 6 +- ...a => ConfigurableValuePolicySupplier.java} | 2 +- .../ExpressionEvaluationContext.java | 14 +- ...Resolver.java => ValuePolicySupplier.java} | 6 +- .../evaluator/AsIsExpressionEvaluator.java | 6 +- .../evaluator/LiteralExpressionEvaluator.java | 2 +- 27 files changed, 433 insertions(+), 349 deletions(-) rename repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/{ConfigurableValuePolicyResolver.java => ConfigurableValuePolicySupplier.java} (92%) rename repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/{ValuePolicyResolver.java => ValuePolicySupplier.java} (75%) diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractSearchExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractSearchExpressionEvaluator.java index bd118f135bf..bca0475a538 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractSearchExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractSearchExpressionEvaluator.java @@ -147,19 +147,13 @@ protected List transformSingleValue(ExpressionVariables variables, PlusMinusZ throw new SchemaException("No filter in "+shortDebugDump()); } query = prismContext.getQueryConverter().createObjectQuery(targetTypeClass, filterType); - if (LOGGER.isTraceEnabled()){ - LOGGER.trace("XML query converted to: {}", query.debugDump()); - } + LOGGER.trace("XML query converted to: {}", query.debugDumpLazily()); + query = ExpressionUtil.evaluateQueryExpressions(query, variables, context.getExpressionProfile(), context.getExpressionFactory(), prismContext, context.getContextDescription(), task, result); - if (LOGGER.isTraceEnabled()){ - LOGGER.trace("Expression in query evaluated to: {}", query.debugDump()); - } + LOGGER.trace("Expression in query evaluated to: {}", query.debugDumpLazily()); query = extendQuery(query, context); - - if (LOGGER.isTraceEnabled()){ - LOGGER.trace("Query after extension: {}", query.debugDump()); - } + LOGGER.trace("Query after extension: {}", query.debugDumpLazily()); resultValues = executeSearchUsingCache(targetTypeClass, targetTypeQName, query, additionalAttributeDeltas, context, contextDescription, task, result); @@ -344,10 +338,8 @@ private List executeSearchAttempt(List ra } } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Assignment expression resulted in {} objects, using query:\n{}", - valueResults.size(), query.debugDump()); - } + LOGGER.trace("Assignment expression resulted in {} objects, using query:\n{}", + valueResults.size(), query.debugDumpLazily()); return valueResults; } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssignmentTargetSearchExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssignmentTargetSearchExpressionEvaluator.java index 02ff397aa26..b4360f7c513 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssignmentTargetSearchExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssignmentTargetSearchExpressionEvaluator.java @@ -30,6 +30,9 @@ import static java.util.Collections.emptyList; /** + * Creates an assignment (or assignments) based on specified conditions for the assignment target. + * Can create target objects on demand. + * * @author Radovan Semancik */ public class AssignmentTargetSearchExpressionEvaluator diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java index 0c3cbe38a09..a0930dab14e 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import javax.xml.namespace.QName; @@ -51,15 +52,24 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import org.apache.commons.collections4.CollectionUtils; +import org.jetbrains.annotations.NotNull; import static com.evolveum.midpoint.schema.GetOperationOptions.createNoFetchCollection; /** - * @author Radovan Semancik + * Creates an association (or associations) based on projections of given role. + * + * I.e. a role has projection (e.g. group) and it also induces a construction of a user account. Using this expression + * evaluator the account can obtain groups that are projections of that particular role. * + * To be used in induced constructions only i.e. not in mappings! + * + * @author Radovan Semancik */ public class AssociationFromLinkExpressionEvaluator - extends AbstractExpressionEvaluator,PrismContainerDefinition, AssociationFromLinkExpressionEvaluatorType> { + extends AbstractExpressionEvaluator, + PrismContainerDefinition, + AssociationFromLinkExpressionEvaluatorType> { private static final Trace LOGGER = TraceManager.getTrace(AssociationFromLinkExpressionEvaluator.class); @@ -71,65 +81,22 @@ public class AssociationFromLinkExpressionEvaluator this.objectResolver = objectResolver; } - /* (non-Javadoc) - * @see com.evolveum.midpoint.common.expression.ExpressionEvaluator#evaluate(java.util.Collection, java.util.Map, boolean, java.lang.String, com.evolveum.midpoint.schema.result.OperationResult) - */ @Override public PrismValueDeltaSetTriple> evaluate(ExpressionEvaluationContext context, OperationResult result) - throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException { + throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, + ConfigurationException, SecurityViolationException { + checkEvaluatorProfile(context); String desc = context.getContextDescription(); - AbstractRoleType thisRole; - - Integer assignmentPathIndex = expressionEvaluatorBean.getAssignmentPathIndex(); - if (assignmentPathIndex == null) { - // Legacy ... or default in simple cases - @SuppressWarnings("unchecked") - TypedValue orderOneObjectTypedValue = context.getVariables().get(ExpressionConstants.VAR_ORDER_ONE_OBJECT); - if (orderOneObjectTypedValue == null || orderOneObjectTypedValue.getValue() == null) { - throw new ExpressionEvaluationException("No order one object variable in "+desc+"; the expression may be used in a wrong place. It is only supposed to work in a role."); - } - Object orderOneObject = orderOneObjectTypedValue.getValue(); - if (!(orderOneObject instanceof AbstractRoleType)) { - throw new ExpressionEvaluationException("Order one object variable in "+desc+" is not a role, it is "+orderOneObject.getClass().getName() - +"; the expression may be used in a wrong place. It is only supposed to work in a role."); - } - - thisRole = (AbstractRoleType)orderOneObject; - - } else { - - @SuppressWarnings("unchecked") - TypedValue assignmentPathTypedValue = context.getVariables().get(ExpressionConstants.VAR_ASSIGNMENT_PATH); - if (assignmentPathTypedValue == null || assignmentPathTypedValue.getValue() == null) { - throw new ExpressionEvaluationException("No assignment path variable in "+desc+"; the expression may be used in a wrong place. It is only supposed to work in a role."); - } - - AssignmentPath assignmentPath = (AssignmentPath) assignmentPathTypedValue.getValue(); - if (assignmentPath.isEmpty()) { - throw new ExpressionEvaluationException("Empty assignment path variable in "+desc+"; the expression may be used in a wrong place. It is only supposed to work in a role."); - } - - LOGGER.trace("assignmentPath {}:\n{}", expressionEvaluatorBean.getDescription(), assignmentPath.debugDumpLazily(1)); - - AssignmentPathSegment segment; - try { - segment = assignmentPath.getSegment(assignmentPathIndex); - } catch (IndexOutOfBoundsException e) { - throw new ExpressionEvaluationException("Wrong assignment path index in "+desc+"; Index "+assignmentPathIndex+" cannot be applied to a path of length "+assignmentPath.size(), e); - } - - thisRole = (AbstractRoleType) segment.getSource(); - } - - LOGGER.trace("thisRole {}: {}", expressionEvaluatorBean.getDescription(), thisRole); - - LOGGER.trace("Evaluating association from link on: {}", thisRole); + AbstractRoleType thisRole = getRelevantRole(context); + LOGGER.trace("Evaluating association from link {} on: {}", expressionEvaluatorBean.getDescription(), thisRole); - TypedValue rAssocTargetDefTypedValue = context.getVariables().get(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION); + //noinspection unchecked + TypedValue rAssocTargetDefTypedValue = context.getVariables() + .get(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION); if (rAssocTargetDefTypedValue == null || rAssocTargetDefTypedValue.getValue() == null) { throw new ExpressionEvaluationException("No association target object class definition variable in "+desc+"; the expression may be used in a wrong place. It is only supposed to create an association."); } @@ -149,12 +116,11 @@ public PrismValueDeltaSetTriple> eval QName assocName = context.getMappingQName(); String resourceOid = rAssocTargetDef.getResourceOid(); - Collection> options = null; List candidateShadowOidList = new ArrayList<>(); // Always process the first role (myself) regardless of recursion setting gatherCandidateShadowsFromAbstractRole(thisRole, candidateShadowOidList); if (thisRole instanceof OrgType && matchesForRecursion((OrgType)thisRole)) { - gatherCandidateShadowsFromAbstractRoleRecurse((OrgType)thisRole, candidateShadowOidList, options, desc, context, result); + gatherCandidateShadowsFromAbstractRoleRecurse((OrgType)thisRole, candidateShadowOidList, null, desc, context, result); } LOGGER.trace("Candidate shadow OIDs: {}", candidateShadowOidList); @@ -162,6 +128,64 @@ public PrismValueDeltaSetTriple> eval return ItemDeltaUtil.toDeltaSetTriple(output, null, prismContext); } + private AbstractRoleType getRelevantRole(ExpressionEvaluationContext context) throws ExpressionEvaluationException { + AbstractRoleType thisRole; + Integer assignmentPathIndex = expressionEvaluatorBean.getAssignmentPathIndex(); + if (assignmentPathIndex == null) { + // Legacy ... or default in simple cases + thisRole = getOrderOneObject(context); + } else { + AssignmentPathSegment segment = getSpecifiedAssignmentPathSegment(context, assignmentPathIndex); + thisRole = (AbstractRoleType) segment.getSource(); + } + return thisRole; + } + + @NotNull + private AbstractRoleType getOrderOneObject(ExpressionEvaluationContext context) + throws ExpressionEvaluationException { + @SuppressWarnings("unchecked") + TypedValue orderOneObjectTypedValue = context.getVariables().get(ExpressionConstants.VAR_ORDER_ONE_OBJECT); + if (orderOneObjectTypedValue == null || orderOneObjectTypedValue.getValue() == null) { + throw new ExpressionEvaluationException("No order one object variable in " + context.getContextDescription() + + "; the expression may be used in a wrong place. It is only supposed to work in a role."); + } + Object orderOneObject = orderOneObjectTypedValue.getValue(); + if (orderOneObject instanceof AbstractRoleType) { + return (AbstractRoleType) orderOneObject; + } else { + throw new ExpressionEvaluationException("Order one object variable in " + context.getContextDescription() + + " is not a role, it is "+orderOneObject.getClass().getName() + + "; the expression may be used in a wrong place. It is only supposed to work in a role."); + } + } + + private AssignmentPathSegment getSpecifiedAssignmentPathSegment(ExpressionEvaluationContext context, Integer assignmentPathIndex) + throws ExpressionEvaluationException { + + @SuppressWarnings("unchecked") + TypedValue assignmentPathTypedValue = context.getVariables().get(ExpressionConstants.VAR_ASSIGNMENT_PATH); + if (assignmentPathTypedValue == null || assignmentPathTypedValue.getValue() == null) { + throw new ExpressionEvaluationException("No assignment path variable in " + context.getContextDescription() + + "; the expression may be used in a wrong place. It is only supposed to work in a role."); + } + + AssignmentPath assignmentPath = (AssignmentPath) assignmentPathTypedValue.getValue(); + if (assignmentPath.isEmpty()) { + throw new ExpressionEvaluationException("Empty assignment path variable in " + context.getContextDescription() + + "; the expression may be used in a wrong place. It is only supposed to work in a role."); + } + + LOGGER.trace("assignmentPath {}:\n{}", expressionEvaluatorBean.getDescription(), assignmentPath.debugDumpLazily(1)); + + try { + return assignmentPath.getSegment(assignmentPathIndex); + } catch (IndexOutOfBoundsException e) { + throw new ExpressionEvaluationException("Wrong assignment path index in " + context.getContextDescription() + + "; Index "+assignmentPathIndex+" cannot be applied to a path of length "+assignmentPath.size(), e); + } + } + private void selectMatchingShadows(List candidateShadowsOidList, PrismContainer output, String resourceOid, ShadowKindType kind, String intent, QName assocName, ExpressionEvaluationContext context, OperationResult result) { @@ -199,7 +223,8 @@ private void toAssociation(PrismObject shadow, ShadowAssociationType ResourceAttributeContainer identifiersContainer = ObjectFactory.createResourceAttributeContainer( ShadowAssociationType.F_IDENTIFIERS, shadowAttributesContainer.getDefinition(), prismContext); shadowAssociationType.asPrismContainerValue().add(identifiersContainer); - Collection> shadowIdentifiers = ShadowUtil.getAllIdentifiers(shadow); + Collection> shadowIdentifiers = + Objects.requireNonNull(ShadowUtil.getAllIdentifiers(shadow), "no shadow identifiers"); for (ResourceAttribute shadowIdentifier : shadowIdentifiers) { identifiersContainer.add(shadowIdentifier.clone()); } @@ -208,7 +233,6 @@ private void toAssociation(PrismObject shadow, ShadowAssociationType // Should not happen throw new SystemException(e.getMessage(), e); } - } private void gatherCandidateShadowsFromAbstractRole(AbstractRoleType thisRole, List candidateShadowsOidList) { @@ -240,12 +264,8 @@ private boolean matchesForRecursion(OrgType thisOrg) { return false; } - /* (non-Javadoc) - * @see com.evolveum.midpoint.common.expression.ExpressionEvaluator#shortDebugDump() - */ @Override public String shortDebugDump() { return "associationFromLink"; } - } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationTargetSearchExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationTargetSearchExpressionEvaluator.java index 03fc26165bd..263db51afd6 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationTargetSearchExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationTargetSearchExpressionEvaluator.java @@ -43,6 +43,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; /** + * Creates an association (or associations) based on specified condition for the associated object. + * * @author Radovan Semancik */ public class AssociationTargetSearchExpressionEvaluator diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ConstExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ConstExpressionEvaluator.java index c3a6a655c03..62463348d9a 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ConstExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ConstExpressionEvaluator.java @@ -26,10 +26,13 @@ import org.jetbrains.annotations.NotNull; /** - * @author semancik + * Returns zero set with a single value obtained by resolving given constant. + * Currently limited to single-valued string constants. * + * @author semancik */ -public class ConstExpressionEvaluator extends AbstractExpressionEvaluator { +public class ConstExpressionEvaluator + extends AbstractExpressionEvaluator { private final ConstantsManager constantsManager; @@ -47,6 +50,7 @@ public PrismValueDeltaSetTriple evaluate(ExpressionEvaluationContext context, String constName = expressionEvaluatorBean.getValue(); String stringValue = constantsManager.getConstantValue(constName); + //noinspection unchecked Item output = outputDefinition.instantiate(); Object value = ExpressionUtil.convertToOutputValue(stringValue, outputDefinition, protector); @@ -55,18 +59,12 @@ public PrismValueDeltaSetTriple evaluate(ExpressionEvaluationContext context, ((PrismProperty) output).addRealValue(value); } else { throw new UnsupportedOperationException( - "Can only generate values of property, not " + output.getClass()); + "Can only provide values of property, not " + output.getClass()); } return ItemDeltaUtil.toDeltaSetTriple(output, null, prismContext); } - /* - * (non-Javadoc) - * - * @see com.evolveum.midpoint.common.expression.ExpressionEvaluator# - * shortDebugDump() - */ @Override public String shortDebugDump() { return "const:"+ expressionEvaluatorBean.getValue(); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluator.java index 693ca2c2c70..85ee1377122 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluator.java @@ -12,6 +12,8 @@ import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.schema.expression.ExpressionProfile; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.StringUtils; @@ -21,20 +23,32 @@ import com.evolveum.midpoint.repo.common.expression.*; import com.evolveum.midpoint.repo.common.expression.evaluator.AbstractExpressionEvaluator; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; -import com.evolveum.midpoint.schema.expression.ExpressionProfile; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.jetbrains.annotations.NotNull; + /** + * Calls specified custom function expression. It is something like a macro: Arguments for the function call + * (expression themselves) are evaluated into triples, which become additional sources for the function expression. + * Then the function expression is evaluated and the output triple is returned as an output triple for the function + * expression evaluation. + * * @author katkav * @author semancik */ public class FunctionExpressionEvaluator extends AbstractExpressionEvaluator { + private static final String OP_EVALUATE = FunctionExpressionEvaluator.class.getSimpleName() + ".evaluate"; + private static final String OP_GET_FUNCTION_TO_EXECUTE = FunctionExpressionEvaluator.class.getSimpleName() + ".getFunctionToExecute"; + private static final String OP_MAKE_EXPRESSION = FunctionExpressionEvaluator.class.getSimpleName() + ".makeExpression"; + private static final String OP_RESOLVE_PARAMETER_VALUE = FunctionExpressionEvaluator.class.getSimpleName() + ".resolveParameterValue"; + private static final String OP_EVALUATE_FUNCTION = FunctionExpressionEvaluator.class.getSimpleName() + ".evaluateFunction"; + private final ObjectResolver objectResolver; FunctionExpressionEvaluator(QName elementName, FunctionExpressionEvaluatorType functionEvaluatorType, D outputDefinition, @@ -48,100 +62,60 @@ public PrismValueDeltaSetTriple evaluate(ExpressionEvaluationContext context, throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException { checkEvaluatorProfile(context); - List expressions; - ObjectReferenceType functionLibraryRef = expressionEvaluatorBean.getLibraryRef(); - if (functionLibraryRef == null) { throw new SchemaException("No functions library defined in "+context.getContextDescription()); } - OperationResult result = parentResult.createMinorSubresult(FunctionExpressionEvaluator.class.getSimpleName() + ".resolveFunctionLibrary"); + OperationResult result = parentResult.createMinorSubresult(OP_EVALUATE); try { - Task task = context.getTask(); + ExpressionType functionExpressionBean = getFunctionExpressionBean(functionLibraryRef, context, result); + Expression functionExpression = createFunctionExpression(functionExpressionBean, context, result); + ExpressionEvaluationContext functionContext = createFunctionEvaluationContext(functionExpressionBean, context, result); - FunctionLibraryType functionLibraryType = objectResolver.resolve(functionLibraryRef, FunctionLibraryType.class, + return evaluateFunctionExpression(functionExpression, functionContext, result); + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } + } + + private ExpressionType getFunctionExpressionBean(ObjectReferenceType functionLibraryRef, ExpressionEvaluationContext context, + OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, + ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + Task task = context.getTask(); + OperationResult result = parentResult.createMinorSubresult(OP_GET_FUNCTION_TO_EXECUTE); + try { + FunctionLibraryType functionLibrary = objectResolver.resolve(functionLibraryRef, FunctionLibraryType.class, null, "resolving value policy reference in generateExpressionEvaluator", task, result); - expressions = functionLibraryType.getFunction(); - if (CollectionUtils.isEmpty(expressions)) { + List allFunctions = functionLibrary.getFunction(); + if (CollectionUtils.isEmpty(allFunctions)) { throw new ObjectNotFoundException( - "No functions defined in referenced function library: " + functionLibraryType + " used in " + context - .getContextDescription()); + "No functions defined in referenced function library: " + functionLibrary + " used in " + + context.getContextDescription()); } - // TODO: this has to be determined from the library archetype - ExpressionProfile expressionProfile = MiscSchemaUtil.getExpressionProfile(); - String functionName = expressionEvaluatorBean.getName(); - if (StringUtils.isEmpty(functionName)) { throw new SchemaException( "Missing function name in " + shortDebugDump() + " in " + context.getContextDescription()); } - List filteredExpressions = expressions.stream() - .filter(expression -> functionName.equals(expression.getName())).collect(Collectors.toList()); - if (filteredExpressions.size() == 0) { - String possibleFunctions = ""; - for (ExpressionType expression : expressions) { - possibleFunctions += expression.getName() + ", "; - } - possibleFunctions = possibleFunctions.substring(0, possibleFunctions.lastIndexOf(",")); + List functionsMatchingName = allFunctions.stream() + .filter(expression -> functionName.equals(expression.getName())) + .collect(Collectors.toList()); + if (functionsMatchingName.isEmpty()) { + String allFunctionNames = allFunctions.stream() + .map(ExpressionType::getName) + .collect(Collectors.joining(", ")); throw new ObjectNotFoundException("No function with name " + functionName + " found in " + shortDebugDump() - + ". Function defined are: " + possibleFunctions + ". In " + context.getContextDescription()); - } - - ExpressionType functionToExecute = determineFunctionToExecute(filteredExpressions); - - OperationResult functionExpressionResult = result - .createMinorSubresult(FunctionExpressionEvaluator.class.getSimpleName() + ".makeExpression"); - ExpressionFactory factory = context.getExpressionFactory(); - - // TODO: expression profile should be determined from the function library archetype - Expression functionExpression; - try { - functionExpression = factory - .makeExpression(functionToExecute, outputDefinition, MiscSchemaUtil.getExpressionProfile(), - "function execution", task, functionExpressionResult); - functionExpressionResult.recordSuccess(); - } catch (SchemaException | ObjectNotFoundException e) { - functionExpressionResult - .recordFatalError("Cannot make expression for " + functionToExecute + ". Reason: " + e.getMessage(), e); - throw e; + + ". Function defined are: " + allFunctionNames + ". In " + context.getContextDescription()); } - ExpressionEvaluationContext functionContext = context.shallowClone(); - ExpressionVariables functionVariables = new ExpressionVariables(); - - for (ExpressionParameterType param : expressionEvaluatorBean.getParameter()) { - ExpressionType valueExpressionType = param.getExpression(); - OperationResult variableResult = result - .createMinorSubresult(FunctionExpressionEvaluator.class.getSimpleName() + ".resolveVariable"); - Expression valueExpression = null; - try { - variableResult.addArbitraryObjectAsParam("valueExpression", valueExpressionType); - D variableOutputDefinition = determineVariableOutputDefinition(functionToExecute, param.getName(), context); - - valueExpression = factory - .makeExpression(valueExpressionType, variableOutputDefinition, MiscSchemaUtil.getExpressionProfile(), - "parameters execution", task, variableResult); - functionExpressionResult.recordSuccess(); - PrismValueDeltaSetTriple evaluatedValue = valueExpression.evaluate(context, result); - V value = ExpressionUtil.getExpressionOutputValue(evaluatedValue, " evaluated value for paramter"); - functionVariables.addVariableDefinition(param.getName(), value, variableOutputDefinition); - variableResult.recordSuccess(); - } catch (SchemaException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException - | ConfigurationException | SecurityViolationException e) { - variableResult - .recordFatalError("Failed to resolve variable: " + valueExpression + ". Reason: " + e.getMessage()); - throw e; - } - } - - functionContext.setVariables(functionVariables); - - return functionExpression.evaluate(functionContext, result); + return selectFromMatchingFunctions(functionsMatchingName, context); } catch (Throwable t) { result.recordFatalError(t); throw t; @@ -150,15 +124,17 @@ public PrismValueDeltaSetTriple evaluate(ExpressionEvaluationContext context, } } - private ExpressionType determineFunctionToExecute(List filteredExpressions) { + @NotNull + private ExpressionType selectFromMatchingFunctions(List functionsMatchingName, + ExpressionEvaluationContext context) throws ObjectNotFoundException { - if (filteredExpressions.size() == 1) { - return filteredExpressions.iterator().next(); + if (functionsMatchingName.size() == 1) { + return functionsMatchingName.iterator().next(); } List functionParams = expressionEvaluatorBean.getParameter(); - for (ExpressionType filteredExpression : filteredExpressions) { + for (ExpressionType filteredExpression : functionsMatchingName) { List filteredExpressionParameters = filteredExpression.getParameter(); if (functionParams.size() != filteredExpressionParameters.size()) { continue; @@ -168,14 +144,16 @@ private ExpressionType determineFunctionToExecute(List filteredE } return filteredExpression; } - return null; + String functionName = expressionEvaluatorBean.getName(); + throw new ObjectNotFoundException("No matching function with name " + functionName + " found in " + shortDebugDump() + + ". " + functionsMatchingName.size() + " functions with this name found but none matches the parameters. In " + + context.getContextDescription()); } private boolean compareParameters(List functionParams, List filteredExpressionParameters) { for (ExpressionParameterType functionParam: functionParams ) { boolean found = false; for (ExpressionParameterType filteredExpressionParam : filteredExpressionParameters) { - if (filteredExpressionParam.getName().equals(functionParam.getName())) { found = true; break; @@ -188,27 +166,73 @@ private boolean compareParameters(List functionParams, return true; } - private D determineVariableOutputDefinition(ExpressionType functionToExecute, String paramName, ExpressionEvaluationContext context) throws SchemaException { + private Expression createFunctionExpression(ExpressionType functionToExecute, ExpressionEvaluationContext context, + OperationResult parentResult) throws SecurityViolationException, SchemaException, ObjectNotFoundException { + OperationResult result = parentResult.createMinorSubresult(OP_MAKE_EXPRESSION); + try { + // TODO: expression profile should be determined from the function library archetype + ExpressionProfile expressionProfile = MiscSchemaUtil.getExpressionProfile(); - ExpressionParameterType functionParameter = null; - for (ExpressionParameterType functionParam: functionToExecute.getParameter()) { - if (functionParam.getName().equals(paramName)) { - functionParameter = functionParam; - break; - } + return context.getExpressionFactory() + .makeExpression(functionToExecute, outputDefinition, expressionProfile, + "function execution", context.getTask(), result); + } catch (SchemaException | ObjectNotFoundException e) { + result.recordFatalError("Cannot make expression for " + functionToExecute + ". Reason: " + e.getMessage(), e); + throw e; + } finally { + result.computeStatusIfUnknown(); } + } - if (functionParameter == null) { - throw new SchemaException("Unexpected parameter " + paramName + " for function: " + functionToExecute); + @NotNull + private ExpressionEvaluationContext createFunctionEvaluationContext(ExpressionType functionExpressionBean, + ExpressionEvaluationContext context, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, + SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + ExpressionEvaluationContext functionContext = context.shallowClone(); + ExpressionVariables functionVariables = new ExpressionVariables(); + + for (ExpressionParameterType param : expressionEvaluatorBean.getParameter()) { + ExpressionType parameterExpressionBean = param.getExpression(); + OperationResult variableResult = parentResult.createMinorSubresult(OP_RESOLVE_PARAMETER_VALUE); + Expression parameterExpression = null; + try { + variableResult.addArbitraryObjectAsParam("parameterExpression", parameterExpressionBean); + D variableOutputDefinition = determineVariableOutputDefinition(functionExpressionBean, param.getName()); + + // TODO: expression profile should be determined somehow + ExpressionProfile expressionProfile = MiscSchemaUtil.getExpressionProfile(); + + parameterExpression = context.getExpressionFactory() + .makeExpression(parameterExpressionBean, variableOutputDefinition, expressionProfile, + "parameter " + param.getName() + " evaluation in " + context.getContextDescription(), + context.getTask(), variableResult); + PrismValueDeltaSetTriple evaluatedValue = parameterExpression.evaluate(context, parentResult); + V value = ExpressionUtil.getExpressionOutputValue(evaluatedValue, "evaluated value for parameter " + param.getName()); + functionVariables.addVariableDefinition(param.getName(), value, variableOutputDefinition); + } catch (SchemaException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException + | ConfigurationException | SecurityViolationException e) { + variableResult.recordFatalError("Failed to resolve variable: " + parameterExpression + ". Reason: " + e.getMessage()); + throw e; + } finally { + variableResult.computeStatusIfUnknown(); + } } - QName returnType = functionParameter.getType(); + functionContext.setVariables(functionVariables); + return functionContext; + } + private D determineVariableOutputDefinition(ExpressionType functionToExecute, String paramName) throws SchemaException { + ExpressionParameterType functionParameter = functionToExecute.getParameter().stream() + .filter(param -> param.getName().equals(paramName)) + .findFirst() + .orElseThrow(() -> new SchemaException("Unknown parameter " + paramName + " for function: " + functionToExecute)); + + QName returnType = functionParameter.getType(); if (returnType == null) { throw new SchemaException("Cannot determine parameter output definition for " + functionParameter); } - ItemDefinition returnTypeDef = prismContext.getSchemaRegistry().findItemDefinitionByType(returnType); if (returnTypeDef != null) { //noinspection unchecked @@ -222,6 +246,21 @@ private D determineVariableOutputDefinition(ExpressionType functionToExecute, St } } + private PrismValueDeltaSetTriple evaluateFunctionExpression(Expression functionExpression, + ExpressionEvaluationContext functionContext, OperationResult parentResult) throws SchemaException, + ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, + SecurityViolationException { + OperationResult result = parentResult.createMinorSubresult(OP_EVALUATE_FUNCTION); + try { + return functionExpression.evaluate(functionContext, parentResult); + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } + } + @Override public String shortDebugDump() { return "function: " + expressionEvaluatorBean.getName(); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/GenerateExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/GenerateExpressionEvaluator.java index eb00c8f6769..3f936754e52 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/GenerateExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/GenerateExpressionEvaluator.java @@ -15,11 +15,12 @@ import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.prism.delta.ItemDeltaUtil; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.common.ObjectResolver; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; -import com.evolveum.midpoint.repo.common.expression.ValuePolicyResolver; +import com.evolveum.midpoint.repo.common.expression.ValuePolicySupplier; import com.evolveum.midpoint.repo.common.expression.evaluator.AbstractExpressionEvaluator; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.result.OperationResult; @@ -32,17 +33,25 @@ import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.evolveum.midpoint.xml.ns._public.common.common_3.GenerateExpressionEvaluatorModeType.POLICY; + +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; + /** - * @author semancik + * Generates a string value based on given value policy. Puts it into zero set. Plus and minus sets are empty. * + * @author semancik */ -public class GenerateExpressionEvaluator extends AbstractExpressionEvaluator { +public class GenerateExpressionEvaluator + extends AbstractExpressionEvaluator { public static final int DEFAULT_LENGTH = 8; - private ObjectResolver objectResolver; - private ValuePolicyProcessor valuePolicyGenerator; - private ValuePolicyType elementValuePolicy; + private final ObjectResolver objectResolver; + private final ValuePolicyProcessor valuePolicyGenerator; GenerateExpressionEvaluator(QName elementName, GenerateExpressionEvaluatorType generateEvaluatorType, D outputDefinition, Protector protector, ObjectResolver objectResolver, ValuePolicyProcessor valuePolicyGenerator, PrismContext prismContext) { @@ -51,117 +60,113 @@ public class GenerateExpressionEvaluator evaluate(ExpressionEvaluationContext context, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException { checkEvaluatorProfile(context); - ValuePolicyType valuePolicyType = null; + ValuePolicyType valuePolicy = getValuePolicy(context, result); - ObjectReferenceType generateEvaluatorValuePolicyRef = expressionEvaluatorBean.getValuePolicyRef(); - if (generateEvaluatorValuePolicyRef != null) { - if (expressionEvaluatorBean.getValuePolicyRef() != null) { - valuePolicyType = objectResolver.resolve(generateEvaluatorValuePolicyRef, ValuePolicyType.class, - null, "resolving value policy reference in generateExpressionEvaluator", context.getTask(), result); - } - - } - - // if (elementStringPolicy == null) { - // if the policy was changed, the most fresh copy is needed, therefore - // it must be resolved all time the value is generated..if it was not - // resolved each time, the cached policy would be used and so bad values - // would be generated - if (valuePolicyType == null) { - ValuePolicyResolver valuePolicyResolver = context.getValuePolicyResolver(); - if (valuePolicyResolver != null) { - valuePolicyType = valuePolicyResolver.resolve(result); - } - } - - elementValuePolicy = valuePolicyType; - // } else { - // stringPolicyType = elementStringPolicy; - // } - - // - String stringValue = null; - GenerateExpressionEvaluatorModeType mode = expressionEvaluatorBean.getMode(); + //noinspection unchecked Item output = outputDefinition.instantiate(); - if (mode == null || mode == GenerateExpressionEvaluatorModeType.POLICY) { - - ObjectBasedValuePolicyOriginResolver originResolver = getOriginResolver(context); - - // TODO: generate value based on stringPolicyType (if not null) - if (valuePolicyType != null) { - if (isNotEmptyMinLength(valuePolicyType)) { - stringValue = valuePolicyGenerator.generate(output.getPath(), valuePolicyType, DEFAULT_LENGTH, true, originResolver, - context.getContextDescription(), context.getTask(), result); - } else { - stringValue = valuePolicyGenerator.generate(output.getPath(), valuePolicyType, DEFAULT_LENGTH, false, originResolver, - context.getContextDescription(), context.getTask(), result); - } - result.computeStatus(); - if (result.isError()) { - throw new ExpressionEvaluationException("Failed to generate value according to policy: " - + valuePolicyType.getDescription() + ". " + result.getMessage()); - } - } + ItemPath outputPath = output.getPath(); // actually, a name only - if (stringValue == null) { - int length = DEFAULT_LENGTH; - RandomString randomString = new RandomString(length); - stringValue = randomString.nextString(); - } + String stringValue = generateStringValue(valuePolicy, context, outputPath, result); + addValueToOutputProperty(output, stringValue); - } else if (mode == GenerateExpressionEvaluatorModeType.UUID) { - UUID randomUUID = UUID.randomUUID(); - stringValue = randomUUID.toString(); + return ItemDeltaUtil.toDeltaSetTriple(output, null, prismContext); + } - } else { - throw new ExpressionEvaluationException("Unknown mode for generate expression: " + mode); + @NotNull + private String generateStringValue(ValuePolicyType valuePolicy, ExpressionEvaluationContext context, ItemPath outputPath, + OperationResult result) + throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, + CommunicationException, ConfigurationException, SecurityViolationException { + GenerateExpressionEvaluatorModeType mode = defaultIfNull(expressionEvaluatorBean.getMode(), POLICY); + switch (mode) { + case POLICY: + // TODO: generate value based on stringPolicyType (if not null) + if (valuePolicy != null) { + String generatedStringValue = generateStringValueFromPolicy(valuePolicy, context, outputPath, result); + if (generatedStringValue != null) + return generatedStringValue; + } + return new RandomString(DEFAULT_LENGTH).nextString(); + case UUID: + return UUID.randomUUID().toString(); + default: + throw new ExpressionEvaluationException("Unknown mode for generate expression: " + mode); } + } - Object value = ExpressionUtil.convertToOutputValue(stringValue, outputDefinition, protector); - - + private void addValueToOutputProperty(Item output, String stringValue) + throws ExpressionEvaluationException, + SchemaException { if (output instanceof PrismProperty) { + Object value = ExpressionUtil.convertToOutputValue(stringValue, outputDefinition, protector); ((PrismProperty) output).addRealValue(value); } else { throw new UnsupportedOperationException( "Can only generate values of property, not " + output.getClass()); } + } - return ItemDeltaUtil.toDeltaSetTriple(output, null, prismContext); + @Nullable + private String generateStringValueFromPolicy(ValuePolicyType valuePolicy, ExpressionEvaluationContext context, + ItemPath outputPath, OperationResult result) + throws ExpressionEvaluationException, SchemaException, ObjectNotFoundException, CommunicationException, + ConfigurationException, SecurityViolationException { + ObjectBasedValuePolicyOriginResolver originResolver = getOriginResolver(context); + String generatedValue; + if (isNotEmptyMinLength(valuePolicy)) { + generatedValue = valuePolicyGenerator.generate(outputPath, valuePolicy, DEFAULT_LENGTH, true, originResolver, + context.getContextDescription(), context.getTask(), result); + } else { + generatedValue = valuePolicyGenerator.generate(outputPath, valuePolicy, DEFAULT_LENGTH, false, originResolver, + context.getContextDescription(), context.getTask(), result); + } + result.computeStatus(); + if (result.isError()) { + throw new ExpressionEvaluationException("Failed to generate value according to policy: " + + valuePolicy.getDescription() + ". " + result.getMessage()); + } + return generatedValue; + } + + private boolean isNotEmptyMinLength(ValuePolicyType valuePolicy) { + StringPolicyType stringPolicy = valuePolicy.getStringPolicy(); + if (stringPolicy == null) { + return false; + } + Integer minLength = stringPolicy.getLimitations().getMinLength(); + return minLength != null && minLength != 0; + } + + @Nullable + private ValuePolicyType getValuePolicy(ExpressionEvaluationContext context, OperationResult result) + throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, + SecurityViolationException, ExpressionEvaluationException { + ObjectReferenceType specifiedValuePolicyRef = expressionEvaluatorBean.getValuePolicyRef(); + if (specifiedValuePolicyRef != null) { + ValuePolicyType resolvedPolicy = objectResolver.resolve(specifiedValuePolicyRef, ValuePolicyType.class, + null, "resolving value policy reference in generateExpressionEvaluator", context.getTask(), result); + if (resolvedPolicy != null) { + return resolvedPolicy; + } + } + + ValuePolicySupplier valuePolicySupplier = context.getValuePolicySupplier(); + if (valuePolicySupplier != null) { + return valuePolicySupplier.get(result); + } + + return null; } // determine object from the variables @SuppressWarnings("unchecked") - private ObjectBasedValuePolicyOriginResolver getOriginResolver(ExpressionEvaluationContext params) throws SchemaException { - ExpressionVariables variables = params.getVariables(); + private ObjectBasedValuePolicyOriginResolver getOriginResolver(ExpressionEvaluationContext context) throws SchemaException { + ExpressionVariables variables = context.getVariables(); if (variables == null) { return null; } @@ -175,8 +180,10 @@ private ObjectBasedValuePolicyOriginResolver getOrigin @Override public String shortDebugDump() { - if (elementValuePolicy != null) { - return "generate: " + elementValuePolicy; + // Here used to be reference to the value policy. However, although expression evaluators are usually not re-evaluated, + // it is not always the case. So the evaluator should not keep state related to evaluation itself. + if (expressionEvaluatorBean.getValuePolicyRef() != null) { + return "generate:" + expressionEvaluatorBean.getValuePolicyRef(); } else { return "generate"; } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ReferenceSearchExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ReferenceSearchExpressionEvaluator.java index 6be88d75700..f1fe18d5bbd 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ReferenceSearchExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/ReferenceSearchExpressionEvaluator.java @@ -24,6 +24,9 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ReferenceSearchExpressionEvaluatorType; /** + * Creates a generic reference (or references) based on specified condition for the referenced object. + * (It seems to be not much used.) + * * @author Radovan Semancik */ public class ReferenceSearchExpressionEvaluator diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/path/PathExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/path/PathExpressionEvaluator.java index c3c8aff72aa..1f85099bf7e 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/path/PathExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/path/PathExpressionEvaluator.java @@ -23,6 +23,8 @@ import com.evolveum.midpoint.util.exception.SecurityViolationException; /** + * Returns value set triple derived from specified (or default) source by resolving specified path. + * * @author Radovan Semancik */ public class PathExpressionEvaluator implements ExpressionEvaluator { diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluator.java index 938c9901e15..7712984d25f 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluator.java @@ -34,6 +34,8 @@ import org.jetbrains.annotations.NotNull; /** + * Executes specified script written e.g. in Groovy, JavaScript, Python, etc. Velocity template language is supported as well. + * * @author Radovan Semancik */ public class ScriptExpressionEvaluator diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingBuilder.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingBuilder.java index 2eb5986c1c8..ad01967518b 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingBuilder.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingBuilder.java @@ -62,7 +62,7 @@ public final class MappingBuilder targetContext; private OriginType originType; private ObjectType originObject; - private ConfigurableValuePolicyResolver valuePolicyResolver; + private ConfigurableValuePolicySupplier valuePolicySupplier; private VariableProducer variableProducer; private MappingPreExpression mappingPreExpression; private boolean conditionMaskOld = true; @@ -168,8 +168,8 @@ public MappingBuilder originObject(ObjectType val) { return this; } - public MappingBuilder valuePolicyResolver(ConfigurableValuePolicyResolver val) { - valuePolicyResolver = val; + public MappingBuilder valuePolicySupplier(ConfigurableValuePolicySupplier val) { + valuePolicySupplier = val; return this; } @@ -329,11 +329,6 @@ public MappingBuilder addVariableDefinition(String name, Object value, Cla return this; } - public MappingBuilder stringPolicyResolver(ConfigurableValuePolicyResolver stringPolicyResolver) { - this.valuePolicyResolver = stringPolicyResolver; - return this; - } - public boolean hasVariableDefinition(String varName) { return variables.containsKey(varName); } @@ -428,8 +423,8 @@ public ObjectType getOriginObject() { return originObject; } - public ConfigurableValuePolicyResolver getValuePolicyResolver() { - return valuePolicyResolver; + public ConfigurableValuePolicySupplier getValuePolicySupplier() { + return valuePolicySupplier; } public VariableProducer getVariableProducer() { diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java index 5dfe8cc8c49..838a447e709 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java @@ -164,9 +164,9 @@ public class MappingImpl /** * Provider of the value policy (used for "generate" expressions). - * See {@link ExpressionEvaluationContext#valuePolicyResolver}. + * See {@link ExpressionEvaluationContext#valuePolicySupplier}. */ - final ConfigurableValuePolicyResolver valuePolicyResolver; + final ConfigurableValuePolicySupplier valuePolicySupplier; /** * Mapping pre-expression is invoked just before main mapping expression. @@ -335,7 +335,7 @@ public class MappingImpl targetContext = builder.getTargetContext(); originType = builder.getOriginType(); originObject = builder.getOriginObject(); - valuePolicyResolver = builder.getValuePolicyResolver(); + valuePolicySupplier = builder.getValuePolicySupplier(); variableProducer = builder.getVariableProducer(); mappingPreExpression = builder.getMappingPreExpression(); conditionMaskOld = builder.isConditionMaskOld(); @@ -374,7 +374,7 @@ private MappingImpl(MappingImpl prototype) { this.originType = prototype.originType; this.originObject = prototype.originObject; - this.valuePolicyResolver = prototype.valuePolicyResolver; + this.valuePolicySupplier = prototype.valuePolicySupplier; this.mappingPreExpression = prototype.mappingPreExpression; this.conditionMaskOld = prototype.conditionMaskOld; this.conditionMaskNew = prototype.conditionMaskNew; @@ -1044,7 +1044,7 @@ private void computeConditionTriple(OperationResult result) "condition in " + getMappingContextDescription(), task, result); ExpressionEvaluationContext context = new ExpressionEvaluationContext(sources, variables, "condition in " + getMappingContextDescription(), task); - context.setValuePolicyResolver(valuePolicyResolver); + context.setValuePolicySupplier(valuePolicySupplier); context.setExpressionFactory(expressionFactory); context.setDefaultSource(defaultSource); context.setMappingQName(mappingQName); @@ -1063,7 +1063,7 @@ private void evaluateExpression(OperationResult result) context.setDefaultSource(defaultSource); context.setSkipEvaluationMinus(!conditionResultOld); context.setSkipEvaluationPlus(!conditionResultNew); - context.setValuePolicyResolver(valuePolicyResolver); + context.setValuePolicySupplier(valuePolicySupplier); context.setExpressionFactory(expressionFactory); context.setMappingQName(mappingQName); context.setVariableProducer(variableProducer); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingParser.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingParser.java index 095ded222bb..e97aa88b22c 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingParser.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingParser.java @@ -85,9 +85,9 @@ private void parseTarget() throws SchemaException { outputPath = path.stripVariableSegment(); } } - if (m.valuePolicyResolver != null) { - m.valuePolicyResolver.setOutputDefinition(outputDefinition); - m.valuePolicyResolver.setOutputPath(outputPath); + if (m.valuePolicySupplier != null) { + m.valuePolicySupplier.setOutputDefinition(outputDefinition); + m.valuePolicySupplier.setOutputPath(outputPath); } } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/PopulatorUtil.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/PopulatorUtil.java index 8ac0f41f7d6..e2d3cf722d5 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/PopulatorUtil.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/PopulatorUtil.java @@ -109,7 +109,7 @@ private static MappingBuilder, PrismPropertyDefinition> cre PrismObjectDefinition userDefinition = getUserDefinition(); mappingBuilder.targetContext(userDefinition); - mappingBuilder.stringPolicyResolver((result) -> policy); + mappingBuilder.valuePolicySupplier((result) -> policy); // Default target if (defaultTargetPropertyPath != null) { PrismPropertyDefinition targetDefDefinition = userDefinition.findItemDefinition(defaultTargetPropertyPath); @@ -211,7 +211,7 @@ public MappingImpl, PrismPropertyDefinition> create builder.addVariableDefinition(ExpressionConstants.VAR_SHADOW, account.asPrismObject(), ShadowType.class); builder.addVariableDefinition(ExpressionConstants.VAR_PROJECTION, account.asPrismObject(), ShadowType.class); - builder.stringPolicyResolver((result) -> policy); + builder.valuePolicySupplier((result) -> policy); builder.originType(OriginType.INBOUND); builder.originObject(resource); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java index 9c2387c23df..7d29fcb8869 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java @@ -1158,7 +1158,7 @@ public ObjectDeltaType getResourceDelta(ModelContext context, String resourceOid @Override public long getSequenceCounter(String sequenceOid) throws ObjectNotFoundException, SchemaException { - return SequentialValueExpressionEvaluator.getSequenceCounter(sequenceOid, repositoryService, getCurrentResult()); + return SequentialValueExpressionEvaluator.getSequenceCounterValue(sequenceOid, repositoryService, getCurrentResult()); } // orgstruct related methods diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluator.java index 60d99626b1c..624cf4b3428 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluator.java @@ -27,17 +27,26 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SequentialValueExpressionEvaluatorType; +import org.jetbrains.annotations.NotNull; + /** - * @author semancik + * Returns current value of a given sequence object. The value is returned in the zero set. Plus and minus sets are empty. + * The value for a given sequence OID is stored in the model context, so it is returned each time this evaluator (with given + * sequence OID) is invoked. * + * @author semancik */ -public class SequentialValueExpressionEvaluator extends AbstractExpressionEvaluator { +public class SequentialValueExpressionEvaluator + extends AbstractExpressionEvaluator { + @NotNull private final String sequenceOid; private final RepositoryService repositoryService; - SequentialValueExpressionEvaluator(QName elementName, SequentialValueExpressionEvaluatorType sequentialValueEvaluatorType, - D outputDefinition, Protector protector, RepositoryService repositoryService, PrismContext prismContext) { + SequentialValueExpressionEvaluator(QName elementName, @NotNull String sequenceOid, + SequentialValueExpressionEvaluatorType sequentialValueEvaluatorType, D outputDefinition, + Protector protector, RepositoryService repositoryService, PrismContext prismContext) { super(elementName, sequentialValueEvaluatorType, outputDefinition, protector, prismContext); + this.sequenceOid = sequenceOid; this.repositoryService = repositoryService; } @@ -47,35 +56,47 @@ public PrismValueDeltaSetTriple evaluate(ExpressionEvaluationContext context, throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, SecurityViolationException { checkEvaluatorProfile(context); - long counter = getSequenceCounter(expressionEvaluatorBean.getSequenceRef().getOid(), repositoryService, result); + long counterValue = getSequenceCounterValue(sequenceOid, repositoryService, result); - Object value = ExpressionUtil.convertToOutputValue(counter, outputDefinition, protector); - - //noinspection unchecked - Item output = outputDefinition.instantiate(); - if (output instanceof PrismProperty) { - ((PrismProperty)output).addRealValue(value); - } else { - throw new UnsupportedOperationException("Can only generate values of property, not "+output.getClass()); - } + Object value = ExpressionUtil.convertToOutputValue(counterValue, outputDefinition, protector); + Item output = addValueToOutputProperty(value); return ItemDeltaUtil.toDeltaSetTriple(output, null, prismContext); } - static long getSequenceCounter(String sequenceOid, RepositoryService repositoryService, OperationResult result) throws ObjectNotFoundException, SchemaException { + /** + * Returns sequence counter value for this clockwork run. + * + * Because mappings are evaluated repeatedly, the value is obtained from the repository only for the first time. + * Then it is stored in model context to be reused as needed. + */ + static long getSequenceCounterValue(String sequenceOid, RepositoryService repositoryService, OperationResult result) throws ObjectNotFoundException, SchemaException { ModelContext ctx = ModelExpressionThreadLocalHolder.getLensContextRequired(); - Long counter = ctx.getSequenceCounter(sequenceOid); - if (counter == null) { - counter = repositoryService.advanceSequence(sequenceOid, result); - ctx.setSequenceCounter(sequenceOid, counter); + Long alreadyObtainedValue = ctx.getSequenceCounter(sequenceOid); + if (alreadyObtainedValue != null) { + return alreadyObtainedValue; + } else { + long freshValue = repositoryService.advanceSequence(sequenceOid, result); + ctx.setSequenceCounter(sequenceOid, freshValue); + return freshValue; } + } - return counter; + @NotNull + private Item addValueToOutputProperty(Object value) throws SchemaException { + //noinspection unchecked + Item output = outputDefinition.instantiate(); + if (output instanceof PrismProperty) { + ((PrismProperty)output).addRealValue(value); + } else { + throw new UnsupportedOperationException("Can only provide values of property, not "+output.getClass()); + } + return output; } @Override public String shortDebugDump() { - return "sequentialValue: "+ expressionEvaluatorBean.getSequenceRef().getOid(); + return "sequentialValue: "+ sequenceOid; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluatorFactory.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluatorFactory.java index be5a259baaf..57b4b23901e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluatorFactory.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/SequentialValueExpressionEvaluatorFactory.java @@ -57,11 +57,11 @@ public ExpressionEvaluator cr SequentialValueExpressionEvaluatorType evaluatorBean = getSingleEvaluatorBeanRequired(evaluatorElements, SequentialValueExpressionEvaluatorType.class, contextDescription); - if (evaluatorBean.getSequenceRef() == null || evaluatorBean.getSequenceRef().getOid() == null) { + if (evaluatorBean.getSequenceRef() != null && evaluatorBean.getSequenceRef().getOid() != null) { + return new SequentialValueExpressionEvaluator<>(ELEMENT_NAME, evaluatorBean.getSequenceRef().getOid(), evaluatorBean, + outputDefinition, protector, repositoryService, prismContext); + } else { throw new SchemaException("Missing sequence reference in sequentialValue expression evaluator in "+contextDescription); } - - return new SequentialValueExpressionEvaluator<>(ELEMENT_NAME, evaluatorBean, outputDefinition, protector, - repositoryService, prismContext); } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/construction/EvaluatedOutboundConstructionImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/construction/EvaluatedOutboundConstructionImpl.java index f8fbe93e173..28305946ea0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/construction/EvaluatedOutboundConstructionImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/construction/EvaluatedOutboundConstructionImpl.java @@ -22,7 +22,7 @@ import com.evolveum.midpoint.model.impl.lens.projector.mappings.NextRecompute; import com.evolveum.midpoint.prism.util.ObjectDeltaObject; -import com.evolveum.midpoint.repo.common.expression.ConfigurableValuePolicyResolver; +import com.evolveum.midpoint.repo.common.expression.ConfigurableValuePolicySupplier; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import org.jetbrains.annotations.NotNull; @@ -231,7 +231,7 @@ private MappingImpl evalu } } - ConfigurableValuePolicyResolver valuePolicyResolver = new ConfigurableValuePolicyResolver() { + ConfigurableValuePolicySupplier valuePolicySupplier = new ConfigurableValuePolicySupplier() { private ItemDefinition outputDefinition; @Override @@ -240,7 +240,7 @@ public void setOutputDefinition(ItemDefinition outputDefinition) { } @Override - public ValuePolicyType resolve(OperationResult result) { + public ValuePolicyType get(OperationResult result) { if (mappingBuilder.getMappingBean().getExpression() != null) { List> evaluators = mappingBuilder.getMappingBean().getExpression().getExpressionEvaluator(); @@ -263,7 +263,7 @@ public ValuePolicyType resolve(OperationResult result) { return null; } }; - mappingBuilder.valuePolicyResolver(valuePolicyResolver); + mappingBuilder.valuePolicySupplier(valuePolicySupplier); // TODO: other variables? // Set condition masks. There are used as a brakes to avoid evaluating to nonsense values in case user is not present diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java index 13b728991fa..5279cd75715 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java @@ -20,7 +20,7 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.common.expression.ConfigurableValuePolicyResolver; +import com.evolveum.midpoint.repo.common.expression.ConfigurableValuePolicySupplier; import com.evolveum.midpoint.schema.CapabilityUtil; import com.evolveum.midpoint.util.LocalizableMessageBuilder; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; @@ -163,7 +163,7 @@ private void processProjectionPasswordMapping(LensContext< ItemDeltaItem, PrismPropertyDefinition> focusPasswordIdi = focusContext .getObjectDeltaObject().findIdi(SchemaConstants.PATH_PASSWORD_VALUE); - ConfigurableValuePolicyResolver valuePolicyResolver = (result1) -> SecurityUtil.getPasswordPolicy(securityPolicy); + ConfigurableValuePolicySupplier valuePolicySupplier = (result1) -> SecurityUtil.getPasswordPolicy(securityPolicy); MappingInitializer,PrismPropertyDefinition> initializer = (builder) -> { @@ -172,7 +172,7 @@ private void processProjectionPasswordMapping(LensContext< .implicitTargetPath(SchemaConstants.PATH_PASSWORD_VALUE); builder.defaultTargetDefinition(projPasswordPropertyDefinition); builder.defaultSource(new Source<>(focusPasswordIdi, ExpressionConstants.VAR_INPUT_QNAME)); - builder.valuePolicyResolver(valuePolicyResolver); + builder.valuePolicySupplier(valuePolicySupplier); return builder; }; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java index da45814fed7..f851928c9b8 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java @@ -714,7 +714,7 @@ private vo .addVariableDefinition(ExpressionConstants.VAR_CONFIGURATION, context.getSystemConfiguration(), context.getSystemConfiguration().getDefinition()) .addVariableDefinition(ExpressionConstants.VAR_OPERATION, context.getFocusContext().getOperation().getValue(), String.class) .variableResolver(variableProducer) - .valuePolicyResolver(createStringPolicyResolver(context)) + .valuePolicySupplier(createStringPolicyResolver(context)) .originType(OriginType.INBOUND) .originObject(resource); @@ -1180,8 +1180,8 @@ private void resolveEntitlementsIfNeeded(ContainerDelta a } } - private ConfigurableValuePolicyResolver createStringPolicyResolver(final LensContext context) { - return new ConfigurableValuePolicyResolver() { + private ConfigurableValuePolicySupplier createStringPolicyResolver(final LensContext context) { + return new ConfigurableValuePolicySupplier() { private ItemDefinition outputDefinition; @Override @@ -1190,7 +1190,7 @@ public void setOutputDefinition(ItemDefinition outputDefinition) { } @Override - public ValuePolicyType resolve(OperationResult result) { + public ValuePolicyType get(OperationResult result) { if (outputDefinition.getItemName().equals(PasswordType.F_VALUE)) { return credentialsProcessor.determinePasswordPolicy(context.getFocusContext()); } else { @@ -1300,7 +1300,7 @@ private void processSpecialPropertyInbound(Collection createFocusMapping( return null; } - ConfigurableValuePolicyResolver valuePolicyResolver = new ConfigurableValuePolicyResolver() { + ConfigurableValuePolicySupplier valuePolicySupplier = new ConfigurableValuePolicySupplier() { private ItemDefinition outputDefinition; @Override @@ -581,7 +581,7 @@ public void setOutputDefinition(ItemDefinition outputDefinition) { } @Override - public ValuePolicyType resolve(OperationResult result) { + public ValuePolicyType get(OperationResult result) { // TODO need to switch to ObjectValuePolicyEvaluator if (outputDefinition.getItemName().equals(PasswordType.F_VALUE)) { return credentialsProcessor.determinePasswordPolicy(context.getFocusContext()); @@ -636,7 +636,7 @@ public ValuePolicyType resolve(OperationResult result) { .originType(OriginType.USER_POLICY) .originObject(originObject) .objectResolver(objectResolver) - .valuePolicyResolver(valuePolicyResolver) + .valuePolicySupplier(valuePolicySupplier) .rootNode(focusOdo) .mappingPreExpression(request.getMappingPreExpression()) // Used to populate autoassign assignments .now(now); diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ConfigurableValuePolicyResolver.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ConfigurableValuePolicySupplier.java similarity index 92% rename from repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ConfigurableValuePolicyResolver.java rename to repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ConfigurableValuePolicySupplier.java index 1a6f2abce98..af0f1f1c356 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ConfigurableValuePolicyResolver.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ConfigurableValuePolicySupplier.java @@ -13,7 +13,7 @@ * Provides value policy when needed (e.g. in generate expression evaluator). * Accepts setting of path and definition for the item for which the value policy will be obtained. */ -public interface ConfigurableValuePolicyResolver extends ValuePolicyResolver { +public interface ConfigurableValuePolicySupplier extends ValuePolicySupplier { /** * Sets the definition of the item for which value policy will be provided. diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionEvaluationContext.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionEvaluationContext.java index 41962ff4981..be796e1b461 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionEvaluationContext.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionEvaluationContext.java @@ -14,8 +14,6 @@ import org.jetbrains.annotations.NotNull; -import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.schema.expression.ExpressionEvaluatorProfile; import com.evolveum.midpoint.schema.expression.ExpressionProfile; import com.evolveum.midpoint.task.api.Task; @@ -59,7 +57,7 @@ public class ExpressionEvaluationContext { /** * Provider of value policy. Currently used in GenerateExpressionEvaluator. */ - private ValuePolicyResolver valuePolicyResolver; + private ValuePolicySupplier valuePolicySupplier; /** * Factory for expressions. Necessary e.g. for condition evaluation in transformational evaluators. @@ -173,12 +171,12 @@ void setExpressionEvaluatorProfile(ExpressionEvaluatorProfile expressionEvaluato this.expressionEvaluatorProfile = expressionEvaluatorProfile; } - public ValuePolicyResolver getValuePolicyResolver() { - return valuePolicyResolver; + public ValuePolicySupplier getValuePolicySupplier() { + return valuePolicySupplier; } - public void setValuePolicyResolver(ValuePolicyResolver valuePolicyResolver) { - this.valuePolicyResolver = valuePolicyResolver; + public void setValuePolicySupplier(ValuePolicySupplier valuePolicySupplier) { + this.valuePolicySupplier = valuePolicySupplier; } public ExpressionFactory getExpressionFactory() { @@ -239,7 +237,7 @@ public ExpressionEvaluationContext shallowClone() { clone.skipEvaluationMinus = this.skipEvaluationMinus; clone.skipEvaluationPlus = this.skipEvaluationPlus; clone.expressionProfile = this.expressionProfile; - clone.valuePolicyResolver = this.valuePolicyResolver; + clone.valuePolicySupplier = this.valuePolicySupplier; clone.expressionFactory = this.expressionFactory; clone.defaultSource = this.defaultSource; clone.mappingQName = this.mappingQName; diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ValuePolicyResolver.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ValuePolicySupplier.java similarity index 75% rename from repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ValuePolicyResolver.java rename to repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ValuePolicySupplier.java index 880d3e9efb8..6a63eb26a4f 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ValuePolicyResolver.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ValuePolicySupplier.java @@ -10,14 +10,14 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ValuePolicyType; /** - * Provides value policy when needed (e.g. in generate expression evaluator). + * Supplies value policy when needed (e.g. in generate expression evaluator). * * @author semancik */ -public interface ValuePolicyResolver { +public interface ValuePolicySupplier { /** * Returns appropriate value policy. */ - ValuePolicyType resolve(OperationResult result); + ValuePolicyType get(OperationResult result); } diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/AsIsExpressionEvaluator.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/AsIsExpressionEvaluator.java index 356387958c1..a593a9a4c58 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/AsIsExpressionEvaluator.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/AsIsExpressionEvaluator.java @@ -15,7 +15,6 @@ import com.evolveum.midpoint.prism.delta.ItemDeltaUtil; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; -import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; import com.evolveum.midpoint.repo.common.expression.Source; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; @@ -25,9 +24,12 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AsIsExpressionEvaluatorType; /** + * Returns value set triple of the default source. (The same behavior as with empty path.) + * * @author Radovan Semancik */ -public class AsIsExpressionEvaluator extends AbstractExpressionEvaluator { +public class AsIsExpressionEvaluator + extends AbstractExpressionEvaluator { AsIsExpressionEvaluator(QName elementName, AsIsExpressionEvaluatorType evaluatorBean, D outputDefinition, Protector protector, PrismContext prismContext) { super(elementName, evaluatorBean, outputDefinition, protector, prismContext); diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/LiteralExpressionEvaluator.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/LiteralExpressionEvaluator.java index e65a7916c99..72895ff4fb1 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/LiteralExpressionEvaluator.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/evaluator/LiteralExpressionEvaluator.java @@ -21,7 +21,7 @@ import com.evolveum.midpoint.util.exception.SecurityViolationException; /** - * Expression evaluator that provides literal (constant) value(s). + * Always returns zero set with literal value (values) specified in the evaluator. Plus and minus sets are empty. * * @author Radovan Semancik */