From f173e898c2eba792e3f3e71856c9d76f1d322d28 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 20 Sep 2017 15:18:56 +0200 Subject: [PATCH] Added "forWholeInput" parameter of execute-script bulk action. Fixed TestPolicyRules2. --- .../prism/schema/SchemaRegistryImpl.java | 1 + .../scripting/actions/NotifyExecutor.java | 2 +- .../scripting/actions/ScriptExecutor.java | 78 ++++++++++------ .../scripting/helpers/OperationsHelper.java | 6 +- .../model/impl/lens/TestPolicyRules2.java | 2 +- .../lens/policy/role-ambiguous-reference.xml | 4 +- .../lens/policy/role-chained-references.xml | 12 ++- .../lens/policy/role-cyclic-references.xml | 10 +- .../resources/lens/policy/role-student.xml | 92 ++++++++++++------- .../policy/role-unresolvable-references.xml | 4 +- 10 files changed, 138 insertions(+), 73 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistryImpl.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistryImpl.java index 0371867c36b..7bd13cbf200 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistryImpl.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistryImpl.java @@ -435,6 +435,7 @@ private void parsePrismSchema(SchemaDescription schemaDescription, boolean allow detectExtensionSchema(schema); } + // see https://stackoverflow.com/questions/14837293/xsd-circular-import private void parsePrismSchemas(List schemaDescriptions, boolean allowDelayedItemDefinitions) throws SchemaException { List prismSchemaDescriptions = schemaDescriptions.stream() .filter(sd -> sd.isPrismSchema()) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java index 934d7510d07..896a01f4e4e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java @@ -73,7 +73,7 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, PARAM_STATUS, input, context, EventStatusType.class, globalResult); EventOperationType operation = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_OPERATION, false, false, PARAM_OPERATION, input, context, EventOperationType.class, globalResult); - boolean forWholeInput = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_SUBTYPE, globalResult); + boolean forWholeInput = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_FOR_WHOLE_INPUT, globalResult); if (handler != null) { checkRootAuthorization(globalResult, NAME); // TODO explain that the reason is that handler is not null diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java index 4cd7434f959..fcc59cbaf67 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java @@ -60,6 +60,7 @@ public class ScriptExecutor extends BaseActionExecutor { private static final String NAME = "execute-script"; private static final String PARAM_SCRIPT = "script"; private static final String PARAM_OUTPUT_ITEM = "outputItem"; // item name or type (as URI!) -- EXPERIMENTAL + private static final String PARAM_FOR_WHOLE_INPUT = "forWholeInput"; @PostConstruct public void init() { @@ -75,6 +76,7 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, NAME, input, context, ScriptExpressionEvaluatorType.class, globalResult); String outputItem = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_OUTPUT_ITEM, false, false, NAME, input, context, String.class, globalResult); + boolean forWholeInput = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_FOR_WHOLE_INPUT, globalResult); ItemDefinition outputDefinition = getItemDefinition(outputItem); @@ -86,45 +88,69 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, } PipelineData output = PipelineData.createEmpty(); - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); + if (forWholeInput) { + OperationResult result = operationsHelper.createActionResult(null, this, context, globalResult); context.checkTaskStop(); - String valueDescription; - long started; - if (value instanceof PrismObjectValue) { - started = operationsHelper.recordStart(context, asObjectType(value)); - valueDescription = asObjectType(value).asPrismObject().toString(); - } else { - started = 0; - valueDescription = value.toHumanReadableString(); - } Throwable exception = null; try { - Object outObject = executeScript(scriptExpression, value, context, result); + Object outObject = executeScript(scriptExpression, input, context, result); if (outObject != null) { - addToData(outObject, item.getResult(), output); + addToData(outObject, PipelineData.newOperationResult(), output); } else { // no definition means we don't plan to provide any output - so let's just copy the input item to the output // (actually, null definition with non-null outObject should not occur) if (outputDefinition == null) { - output.add(item); + output.addAllFrom(input); } } - if (value instanceof PrismObjectValue) { - operationsHelper.recordEnd(context, asObjectType(value), started, null); - } } catch (Throwable ex) { - if (value instanceof PrismObjectValue) { - operationsHelper.recordEnd(context, asObjectType(value), started, ex); - } - exception = processActionException(ex, NAME, value, context); + exception = processActionException(ex, NAME, null, context); // TODO value for error reporting (3rd parameter) } context.println((exception != null ? "Attempted to execute " : "Executed ") - + "script on " + valueDescription + exceptionSuffix(exception)); + + "script on the pipeline" + exceptionSuffix(exception)); operationsHelper.trimAndCloneResult(result, globalResult, context); - } + } else { + for (PipelineItem item : input.getData()) { + PrismValue value = item.getValue(); + OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); + + context.checkTaskStop(); + String valueDescription; + long started; + if (value instanceof PrismObjectValue) { + started = operationsHelper.recordStart(context, asObjectType(value)); + valueDescription = asObjectType(value).asPrismObject().toString(); + } else { + started = 0; + valueDescription = value.toHumanReadableString(); + } + Throwable exception = null; + try { + Object outObject = executeScript(scriptExpression, value, context, result); + if (outObject != null) { + addToData(outObject, item.getResult(), output); + } else { + // no definition means we don't plan to provide any output - so let's just copy the input item to the output + // (actually, null definition with non-null outObject should not occur) + if (outputDefinition == null) { + output.add(item); + } + } + if (value instanceof PrismObjectValue) { + operationsHelper.recordEnd(context, asObjectType(value), started, null); + } + } catch (Throwable ex) { + if (value instanceof PrismObjectValue) { + operationsHelper.recordEnd(context, asObjectType(value), started, ex); + } + exception = processActionException(ex, NAME, value, context); + } + context.println((exception != null ? "Attempted to execute " : "Executed ") + + "script on " + valueDescription + exceptionSuffix(exception)); + operationsHelper.trimAndCloneResult(result, globalResult, context); + } + } return output; } @@ -165,10 +191,10 @@ private ItemDefinition getItemDefinition(String itemUri) throws ScriptExecuti throw new ScriptExecutionException("Supplied item identification " + itemUri + " corresponds neither to item name nor type name"); } - private Object executeScript(ScriptExpression scriptExpression, PrismValue prismValue, ExecutionContext context, OperationResult result) + private Object executeScript(ScriptExpression scriptExpression, Object input, ExecutionContext context, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { ExpressionVariables variables = new ExpressionVariables(); - variables.addVariableDefinition(ExpressionConstants.VAR_INPUT, prismValue); + variables.addVariableDefinition(ExpressionConstants.VAR_INPUT, input); variables.addVariableDefinition(ExpressionConstants.VAR_PRISM_CONTEXT, prismContext); ExpressionUtil.addActorVariable(variables, securityEnforcer); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java index dde78721937..cf68f29d75d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java @@ -154,8 +154,10 @@ public void recordEnd(ExecutionContext context, ObjectType objectType, long star public OperationResult createActionResult(PipelineItem item, ActionExecutor executor, ExecutionContext context, OperationResult globalResult) { OperationResult result = new OperationResult(executor.getClass().getName() + "." + "execute"); - result.addParam("value", String.valueOf(item.getValue())); - item.getResult().addSubresult(result); + if (item != null) { + result.addParam("value", String.valueOf(item.getValue())); + item.getResult().addSubresult(result); + } return result; } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java index 9522b3301fa..529585a05ca 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java @@ -72,7 +72,7 @@ public class TestPolicyRules2 extends AbstractLensTest { protected static final File ROLE_AMBIGUOUS_REFERENCE_FILE = new File(TEST_DIR, "role-ambiguous-reference.xml"); private static final int STUDENT_TARGET_RULES = 5; // one is global - private static final int STUDENT_FOCUS_RULES = 20; + private static final int STUDENT_FOCUS_RULES = 21; private static final String ACTIVITY_DESCRIPTION = "PROJECTOR (test)"; diff --git a/model/model-impl/src/test/resources/lens/policy/role-ambiguous-reference.xml b/model/model-impl/src/test/resources/lens/policy/role-ambiguous-reference.xml index 99962beb598..241d5bc0f6a 100644 --- a/model/model-impl/src/test/resources/lens/policy/role-ambiguous-reference.xml +++ b/model/model-impl/src/test/resources/lens/policy/role-ambiguous-reference.xml @@ -26,7 +26,9 @@ rule-A constraint-A - constraint-B + + constraint-B + diff --git a/model/model-impl/src/test/resources/lens/policy/role-chained-references.xml b/model/model-impl/src/test/resources/lens/policy/role-chained-references.xml index 119155dc5d3..3b9f09c3f46 100644 --- a/model/model-impl/src/test/resources/lens/policy/role-chained-references.xml +++ b/model/model-impl/src/test/resources/lens/policy/role-chained-references.xml @@ -25,7 +25,9 @@ rule1 - mod-description-and-riskLevel-and-inducement + + mod-description-and-riskLevel-and-inducement + @@ -40,7 +42,9 @@ description - mod-riskLevel-and-inducement + + mod-riskLevel-and-inducement + @@ -55,7 +59,9 @@ riskLevel - mod-inducement + + mod-inducement + diff --git a/model/model-impl/src/test/resources/lens/policy/role-cyclic-references.xml b/model/model-impl/src/test/resources/lens/policy/role-cyclic-references.xml index 653e3e22af1..bc875edcd21 100644 --- a/model/model-impl/src/test/resources/lens/policy/role-cyclic-references.xml +++ b/model/model-impl/src/test/resources/lens/policy/role-cyclic-references.xml @@ -20,13 +20,15 @@ xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - Cyclic references + Cyclic references rule-A constraint-A - constraint-B + + constraint-B + @@ -48,7 +50,9 @@ false true - constraint-A + + constraint-A + diff --git a/model/model-impl/src/test/resources/lens/policy/role-student.xml b/model/model-impl/src/test/resources/lens/policy/role-student.xml index 2ccc89aad87..ea3700cb350 100644 --- a/model/model-impl/src/test/resources/lens/policy/role-student.xml +++ b/model/model-impl/src/test/resources/lens/policy/role-student.xml @@ -19,7 +19,7 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3" xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"> Student @@ -59,7 +59,9 @@ ambivalent-rule-manually-resolved-to-assignment - always-true + + always-true + @@ -73,7 +75,9 @@ ambivalent-rule-manually-resolved-to-focus - always-true + + always-true + @@ -123,7 +127,9 @@ true true - cc-1900 + + cc-1900 + @@ -140,7 +146,9 @@ false true - cc-1900 + + cc-1900 + @@ -157,7 +165,9 @@ true false - cc-1900 + + cc-1900 + @@ -173,7 +183,9 @@ true - cc-1900 + + cc-1900 + @@ -205,7 +217,9 @@ true true - student-assignment + + student-assignment + @@ -222,7 +236,9 @@ false true - student-assignment + + student-assignment + @@ -239,7 +255,9 @@ true false - student-assignment + + student-assignment + @@ -255,7 +273,9 @@ false - student-assignment + + student-assignment + @@ -419,30 +439,32 @@ no-task-for-this-object - - - task-for-this-object-exists - - - TaskType - - - - objectRef - - - - - - - - - - + + + task-for-this-object-exists + + + TaskType + + + + objectRef + + + + + + + + + + diff --git a/model/model-impl/src/test/resources/lens/policy/role-unresolvable-references.xml b/model/model-impl/src/test/resources/lens/policy/role-unresolvable-references.xml index 255202b9da0..29d55c73360 100644 --- a/model/model-impl/src/test/resources/lens/policy/role-unresolvable-references.xml +++ b/model/model-impl/src/test/resources/lens/policy/role-unresolvable-references.xml @@ -25,7 +25,9 @@ rule-A - unresolvable + + unresolvable +