Skip to content

Commit

Permalink
fix for MID-5182
Browse files Browse the repository at this point in the history
  • Loading branch information
katkav committed Apr 11, 2019
1 parent d319402 commit d0d16fb
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 21 deletions.
Expand Up @@ -15,7 +15,9 @@
*/
package com.evolveum.midpoint.model.common.expression.evaluator;

import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import javax.xml.namespace.QName;
Expand All @@ -35,9 +37,12 @@
import com.evolveum.midpoint.repo.common.expression.ExpressionFactory;
import com.evolveum.midpoint.repo.common.expression.ExpressionUtil;
import com.evolveum.midpoint.repo.common.expression.ExpressionVariables;
import com.evolveum.midpoint.repo.common.expression.Source;
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.expression.TypedValue;
import com.evolveum.midpoint.schema.expression.VariablesMap;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
import com.evolveum.midpoint.task.api.Task;
Expand Down Expand Up @@ -131,27 +136,31 @@ public PrismValueDeltaSetTriple<V> evaluate(ExpressionEvaluationContext context)
ExpressionFactory factory = context.getExpressionFactory();

// TODO: expression profile should be determined from the function library archetype
Expression<V, D> expression;
Expression<V, D> functionExpression;
try {
expression = factory.makeExpression(functionToExecute, outputDefinition, MiscSchemaUtil.getExpressionProfile(), "function execution", task, functionExpressionResult);
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;
}

ExpressionVariables originVariables = context.getVariables();


ExpressionEvaluationContext functionContext = context.shallowClone();
ExpressionVariables functionVariables = new ExpressionVariables();

for (ExpressionParameterType param : getExpressionEvaluatorType().getParameter()) {
ExpressionType valueExpression = param.getExpression();
ExpressionType valueExpressionType = param.getExpression();
OperationResult variableResult = result.createMinorSubresult(FunctionExpressionEvaluator.class.getSimpleName() + ".resolveVariable");
Expression<V, D> valueExpression = null;
try {
variableResult.addArbitraryObjectAsParam("valueExpression", valueExpression);
variableResult.addArbitraryObjectAsParam("valueExpression", valueExpressionType);
D variableOutputDefinition = determineVariableOutputDefinition(functionToExecute, param.getName(), context);
ExpressionUtil.evaluateExpression(originVariables, variableOutputDefinition, valueExpression, expressionProfile, context.getExpressionFactory(), "resolve variable", task, variableResult);

valueExpression = factory.makeExpression(valueExpressionType, variableOutputDefinition, MiscSchemaUtil.getExpressionProfile(), "parameters execution", task, variableResult);
functionExpressionResult.recordSuccess();
PrismValueDeltaSetTriple<V> evaluatedValue = valueExpression.evaluate(context);
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) {
Expand All @@ -160,9 +169,10 @@ public PrismValueDeltaSetTriple<V> evaluate(ExpressionEvaluationContext context)
}
}


functionContext.setVariables(functionVariables);

return expression.evaluate(context);
return functionExpression.evaluate(functionContext);
}

private ExpressionType determineFunctionToExecute(List<ExpressionType> filteredExpressions) {
Expand Down
Expand Up @@ -42,12 +42,16 @@
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;

/**
* @author Radovan Semancik
*/
public class PathExpressionEvaluator<V extends PrismValue, D extends ItemDefinition> implements ExpressionEvaluator<V,D> {

private static final transient Trace LOGGER = TraceManager.getTrace(PathExpressionEvaluator.class);

private final QName elementName;
private final ItemPath path;
private final ObjectResolver objectResolver;
Expand Down Expand Up @@ -81,21 +85,25 @@ public PrismValueDeltaSetTriple<V> evaluate(ExpressionEvaluationContext context)

ItemDeltaItem<?,?> resolveContext = null;

ItemPath resolvePath = path;
if (context.getSources() != null && context.getSources().size() == 1) {
Source<?,?> source = context.getSources().iterator().next();
if (path.isEmpty()) {
PrismValueDeltaSetTriple<V> outputTriple = (PrismValueDeltaSetTriple<V>) source.toDeltaSetTriple(prismContext);
return outputTriple.clone();
}
resolveContext = source;
//FIXME quite a hack, but should work for now.
if (QNameUtil.match(path.firstName(), source.getName())) {
resolvePath = path.rest();
}
}

Map<String, TypedValue> variablesAndSources = ExpressionUtil.compileVariablesAndSources(context);

ItemPath resolvePath = path;
Object first = path.first();
if (ItemPath.isVariable(first)) {
String variableName = ItemPath.toVariableName(first).getLocalPart();
String variableName = ItemPath.toVariableName(first).getLocalPart();
TypedValue variableValueAndDefinition = variablesAndSources.get(variableName);
if (variableValueAndDefinition == null) {
throw new ExpressionEvaluationException("No variable with name "+variableName+" in "+ context.getContextDescription());
Expand Down
Expand Up @@ -517,7 +517,7 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra
protected static final String DUMMY_ACCOUNT_ATTRIBUTE_SEA_NAME = "sea";
protected static final String DUMMY_ACCOUNT_ATTRIBUTE_MATE_NAME = "mate";
protected static final String DUMMY_ACCOUNT_ATTRIBUTE_LOCKER_NAME = "locker";

protected static final String INTENT_TEST = "test";
protected static final String INTENT_DUMMY_GROUP = "group";
protected static final String INTENT_DUMMY_PRIVILEGE = "privilege";
Expand Down
13 changes: 9 additions & 4 deletions model/model-intest/src/test/resources/common/custom-library.xml
Expand Up @@ -26,12 +26,12 @@
<function>
<name>getName</name>
<parameter>
<name>name</name>
<name>username</name>
<type>xsd:string</type>
</parameter>
<script>
<code>
return name.toUpperCase();
return username.toUpperCase();
</code>
</script>
<returnType>t:PolyStringType</returnType>
Expand All @@ -41,9 +41,14 @@
<name>getLocality</name>
<parameter>
<name>location</name>
<type>xsd:string</type>
<type>t:PolyStringType</type>
</parameter>
<asIs/>
<script>
<code>
log.info("##Location: " + location)
return location;
</code>
</script>
<returnType>t:PolyStringType</returnType>
</function>

Expand Down
Expand Up @@ -104,7 +104,7 @@
<displayName>Full Name</displayName>
<outbound>
<source>
<path>$user/fullName</path>
<path>fullName</path>
</source>
</outbound>
<inbound>
Expand Down
Expand Up @@ -70,7 +70,7 @@
<script>
<code>
map = new HashMap();
map.put("name", name);
map.put("username", name);
name = myLib.execute("getName", map);
log.info("custom library name: " + name)
return name;
Expand Down
Expand Up @@ -950,22 +950,30 @@ private static <V extends PrismValue> V evaluateExpression(ExpressionVariables v
// expressionHandler.evaluateExpression(currentShadow, valueExpression,
// shortDesc, result);
}

public static <V extends PrismValue, D extends ItemDefinition> V evaluateExpression(
public static <V extends PrismValue, D extends ItemDefinition> V evaluateExpression(Collection<Source<?, ?>> sources,
ExpressionVariables variables, D outputDefinition, ExpressionType expressionType, ExpressionProfile expressionProfile,
ExpressionFactory expressionFactory, String shortDesc, Task task, OperationResult parentResult)
throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException {

Expression<V, D> expression = expressionFactory.makeExpression(expressionType, outputDefinition, expressionProfile,
shortDesc, task, parentResult);

ExpressionEvaluationContext context = new ExpressionEvaluationContext(null, variables, shortDesc, task, parentResult);
ExpressionEvaluationContext context = new ExpressionEvaluationContext(sources, variables, shortDesc, task, parentResult);
PrismValueDeltaSetTriple<V> outputTriple = expression.evaluate(context);

LOGGER.trace("Result of the expression evaluation: {}", outputTriple);

return getExpressionOutputValue(outputTriple, shortDesc);
}

public static <V extends PrismValue, D extends ItemDefinition> V evaluateExpression(
ExpressionVariables variables, D outputDefinition, ExpressionType expressionType, ExpressionProfile expressionProfile,
ExpressionFactory expressionFactory, String shortDesc, Task task, OperationResult parentResult)
throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException {

return evaluateExpression(null, variables, outputDefinition, expressionType, expressionProfile, expressionFactory, shortDesc, task, parentResult);
}

public static <V extends PrismValue> V getExpressionOutputValue(PrismValueDeltaSetTriple<V> outputTriple, String shortDesc) throws ExpressionEvaluationException {
if (outputTriple == null) {
Expand Down Expand Up @@ -1048,6 +1056,16 @@ public static VariablesMap compileVariablesAndSources(ExpressionEvaluationContex

return variablesAndSources;
}

public static VariablesMap compileSources(Collection<Source<?, ?>> sources) {
VariablesMap sourcesMap = new VariablesMap();
if (sources != null) {
for (Source<?, ?> source : sources) {
sourcesMap.put(source.getName().getLocalPart(), source, source.getDefinition());
}
}
return sourcesMap;
}

public static boolean hasExplicitTarget(List<MappingType> mappingTypes) {
for (MappingType mappingType : mappingTypes) {
Expand Down

0 comments on commit d0d16fb

Please sign in to comment.