From 708f9b7a9529de6325d61e38271d20019a1ac8a2 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Feb 2019 13:12:00 +0100 Subject: [PATCH] Add skeleton of UnassignExecutor (MID-4983) This is to be used for unassigning members from an abstract role. --- .../scripting/actions/UnassignExecutor.java | 136 ++++++++++++++++++ .../scripting/helpers/ExpressionHelper.java | 25 ++++ 2 files changed, 161 insertions(+) create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java new file mode 100644 index 00000000000..77e2dbf1436 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2010-2019 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.model.impl.scripting.actions; + +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.model.api.PipelineItem; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.CommonException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionParameterValueType; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Collection; + +/** + * + */ +@Component +public class UnassignExecutor extends BaseActionExecutor { + + private static final Trace LOGGER = TraceManager.getTrace(UnassignExecutor.class); + + private static final String NAME = "unassign"; + private static final String PARAM_RESOURCE = "resource"; + private static final String PARAM_ROLE = "role"; + private static final String PARAM_RELATION = "relation"; + + @PostConstruct + public void init() { + scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + } + + @Override + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + + ModelExecuteOptions executionOptions = getOptions(expression, input, context, globalResult); + boolean dryRun = getParamDryRun(expression, input, context, globalResult); + + ActionParameterValueType resourceParameterValue = expressionHelper.getArgument(expression.getParameter(), PARAM_RESOURCE, false, false, NAME); + ActionParameterValueType roleParameterValue = expressionHelper.getArgument(expression.getParameter(), PARAM_ROLE, false, false, NAME); + Collection relations = expressionHelper.getArgumentValues(expression.getParameter(), PARAM_RELATION, false, false, NAME, input, context, String.class, globalResult); + + Collection resources; + try { + if (resourceParameterValue != null) { + PipelineData data = expressionHelper + .evaluateParameter(resourceParameterValue, null, input, context, globalResult); + resources = data.getDataAsReferences(ResourceType.COMPLEX_TYPE, ResourceType.class, context, globalResult); + } else { + resources = null; + } + } catch (CommonException e) { + throw new ScriptExecutionException("Couldn't evaluate '" + PARAM_RESOURCE + "' parameter of a scripting expression: " + e.getMessage(), e); + } + + Collection roles; + try { + if (roleParameterValue != null) { + PipelineData data = expressionHelper.evaluateParameter(roleParameterValue, null, input, context, globalResult); + roles = data.getDataAsReferences(RoleType.COMPLEX_TYPE, AbstractRoleType.class, context, globalResult); // if somebody wants to assign Org, he has to use full reference value (including object type) + } else { + roles = null; + } + } catch (CommonException e) { + throw new ScriptExecutionException("Couldn't evaluate '" + PARAM_ROLE + "' parameter of a scripting expression: " + e.getMessage(), e); + } + + if (resources == null && roles == null) { + throw new ScriptExecutionException("Nothing to assign: neither resource nor role specified"); + } + + if (CollectionUtils.isEmpty(resources) && CollectionUtils.isEmpty(roles)) { + LOGGER.warn("No resources and no roles to unassign in a scripting expression"); + context.println("Warning: no resources and no roles to unassign"); // TODO some better handling? + return input; + } + + for (PipelineItem item : input.getData()) { + PrismValue value = item.getValue(); + OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); + context.checkTaskStop(); + if (value instanceof PrismObjectValue && ((PrismObjectValue) value).asObjectable() instanceof AssignmentHolderType) { + @SuppressWarnings({"unchecked", "raw"}) + PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); + AssignmentHolderType objectType = (AssignmentHolderType) prismObject.asObjectable(); + long started = operationsHelper.recordStart(context, objectType); + Throwable exception = null; + try { + operationsHelper.applyDelta(createDelta(objectType, resources, roles, relations), executionOptions, dryRun, context, result); + operationsHelper.recordEnd(context, objectType, started, null); + } catch (Throwable ex) { + operationsHelper.recordEnd(context, objectType, started, ex); + exception = processActionException(ex, NAME, value, context); + } + context.println((exception != null ? "Attempted to modify " : "Modified ") + prismObject.toString() + optionsSuffix(executionOptions, dryRun) + exceptionSuffix(exception)); + } else { + //noinspection ThrowableNotThrown + processActionException(new ScriptExecutionException("Item is not a PrismObject of AssignmentHolderType"), NAME, value, context); + } + operationsHelper.trimAndCloneResult(result, globalResult, context); + } + return input; // TODO updated objects? + } + + private ObjectDelta createDelta(ObjectType object, Collection resources, Collection roles, Collection relations) throws ScriptExecutionException { + // TODO implement delta creation + return null; + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java index 8d8cc8f4586..1dbc5cf5e0f 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.model.impl.scripting.helpers; +import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; @@ -27,10 +28,13 @@ import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionParameterValueType; import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.apache.commons.lang.Validate; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -136,4 +140,25 @@ public T getSingleArgumentValue(List arguments, St throw new ScriptExecutionException("Couldn't retrieve value of parameter '" + parameterName + "': " + t.getMessage(), t); } } + + @NotNull + public Collection getArgumentValues(List arguments, String parameterName, boolean required, + boolean requiredNonNull, String context, PipelineData input, ExecutionContext executionContext, Class clazz, OperationResult result) throws ScriptExecutionException { + List rv = new ArrayList<>(); + ActionParameterValueType paramValue = getArgument(arguments, parameterName, required, requiredNonNull, context); + if (paramValue != null) { + PipelineData paramData = evaluateParameter(paramValue, clazz, input, executionContext, result); + for (PipelineItem item : paramData.getData()) { + PrismValue prismValue = item.getValue(); + if (!(prismValue instanceof PrismPropertyValue)) { + throw new ScriptExecutionException( + "A prism property value was expected in '" + parameterName + "' parameter. Got " + prismValue + .getClass().getName() + " instead."); + } else { + rv.add(JavaTypeConverter.convert(clazz, prismValue.getRealValue())); + } + } + } + return rv; + } }