Skip to content

Commit

Permalink
Improve asynchronous execution of scripting rules
Browse files Browse the repository at this point in the history
Full support for three modes of asynchronous execution of "execute
script" policy actions (iterative, single run, single run with no
input).

Removed obsolete query classes from repo API.

Introduced experimental CompleteQuery class to encapsulate substantial
items related to a query (type, options).

A part of MID-5967 implementation.
  • Loading branch information
mederly committed May 28, 2020
1 parent ef9c585 commit 0901dda
Show file tree
Hide file tree
Showing 40 changed files with 1,347 additions and 712 deletions.
Expand Up @@ -115,12 +115,34 @@ <T> LessFilter<T> createLess(@NotNull ItemPath path, PrismPropertyDefinition<T>
@NotNull
AndFilter createAnd(List<ObjectFilter> conditions);

@NotNull
default ObjectFilter createAndOptimized(List<ObjectFilter> conditions) {
if (conditions.isEmpty()) {
return createAll();
} else if (conditions.size() == 1) {
return conditions.get(0);
} else {
return createAnd(conditions);
}
}

@NotNull
OrFilter createOr(ObjectFilter... conditions);

@NotNull
OrFilter createOr(List<ObjectFilter> conditions);

@NotNull
default ObjectFilter createOrOptimized(List<ObjectFilter> conditions) {
if (conditions.isEmpty()) {
return createNone();
} else if (conditions.size() == 1) {
return conditions.get(0);
} else {
return createOr(conditions);
}
}

@NotNull
NotFilter createNot(ObjectFilter inner);

Expand Down Expand Up @@ -156,7 +178,6 @@ <T> LessFilter<T> createLess(@NotNull ItemPath path, PrismPropertyDefinition<T>
OrgFilter createRootOrg();

@NotNull
@Deprecated // please use QueryBuilder instead
TypeFilter createType(QName type, ObjectFilter filter);

@NotNull
Expand Down
Expand Up @@ -9,6 +9,7 @@

import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.OrgFilter;

import javax.xml.namespace.QName;
Expand All @@ -20,6 +21,7 @@ public interface S_AtomicFilterEntry {
S_AtomicFilterExit all();
S_AtomicFilterExit none();
S_AtomicFilterExit undefined();
S_AtomicFilterExit filter(ObjectFilter filter); // not much tested, use with care
S_ConditionEntry item(QName... names);
S_ConditionEntry item(String... names);
S_ConditionEntry item(ItemPath path);
Expand Down
Expand Up @@ -83,6 +83,16 @@ ItemDefinition locateItemDefinition(@NotNull QName itemName,
*/
QName determineTypeForClass(Class<?> clazz);

@NotNull
default QName determineTypeForClassRequired(Class<?> clazz) {
QName typeName = determineTypeForClass(clazz);
if (typeName != null) {
return typeName;
} else {
throw new IllegalStateException("No type for " + clazz);
}
}

/**
* This method will try to locate the appropriate object definition and apply it.
* @param container
Expand Down Expand Up @@ -124,6 +134,15 @@ <T extends ItemDefinition> T findItemDefinitionByFullPath(Class<? extends Object
// Takes XSD types into account as well
<T> Class<T> determineClassForType(QName type);

default <T> Class<T> determineClassForTypeRequired(QName type) {
Class<T> clazz = determineClassForType(type);
if (clazz != null) {
return clazz;
} else {
throw new IllegalStateException("No class for " + type);
}
}

// Takes XSD types into account as well
Class<?> determineClassForItemDefinition(ItemDefinition<?> itemDefinition);

Expand Down
Expand Up @@ -186,6 +186,12 @@ public S_AtomicFilterExit none() {
public S_AtomicFilterExit undefined() {
return addSubfilter(UndefinedFilterImpl.createUndefined());
}

@Override
public S_AtomicFilterExit filter(ObjectFilter filter) {
return addSubfilter(filter);
}

// TODO .............................................

@Override
Expand Down
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.schema.util;

import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ValueListType;

import java.util.Collection;

public class ExecuteScriptUtil {

/**
* "Implants" specified input into ExecuteScriptType, not changing the original.
*/
public static ExecuteScriptType implantInput(ExecuteScriptType originalBean, ValueListType input) {
return originalBean.clone().input(input);
}

public static ValueListType createInput(Collection<? extends PrismValue> values) {
ValueListType input = new ValueListType();
values.forEach(o -> input.getValue().add(o));
return input;
}

public static ValueListType createInputCloned(Collection<? extends PrismValue> values) {
ValueListType input = new ValueListType();
values.forEach(o -> input.getValue().add(o.clone()));
return input;
}
}
Expand Up @@ -289,20 +289,20 @@ public static ObjectReferenceType createObjectRef(ObjectType objectType, QName r
return createObjectRef(objectType.asPrismObject(), relation);
}

public static <T extends ObjectType> ObjectReferenceType createObjectRef(PrismObject<T> object, PrismContext prismContext) {
public static ObjectReferenceType createObjectRef(PrismObject<?> object, PrismContext prismContext) {
if (object == null) {
return null;
}
return createObjectRef(object, prismContext.getDefaultRelation());
}

public static <T extends ObjectType> ObjectReferenceType createObjectRef(PrismObject<T> object, QName relation) {
public static ObjectReferenceType createObjectRef(PrismObject<?> object, QName relation) {
if (object == null) {
return null;
}
ObjectReferenceType ref = new ObjectReferenceType();
ref.setOid(object.getOid());
PrismObjectDefinition<T> definition = object.getDefinition();
PrismObjectDefinition<?> definition = object.getDefinition();
if (definition != null) {
ref.setType(definition.getTypeName());
}
Expand Down
Expand Up @@ -2067,7 +2067,7 @@
</xsd:annotation>
</xsd:element>
<xsd:element name="executeScript" type="s:ExecuteScriptType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="asynchronous" type="c:AsynchronousScriptExecutionType" minOccurs="0">
<xsd:element name="asynchronousExecution" type="c:AsynchronousScriptExecutionType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Options for asynchronous script execution.
Expand Down
Expand Up @@ -940,7 +940,7 @@
<xsd:complexContent>
<xsd:extension base="tns:AbstractExecutionActionExpressionType">
<xsd:sequence>
<xsd:element name="triggered" type="c:TriggerCreationType">
<xsd:element name="triggered" type="c:TriggerCreationType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Does not invoke recompute immediately but uses a trigger to do that.
Expand Down
15 changes: 15 additions & 0 deletions infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java
Expand Up @@ -41,6 +41,8 @@
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.exception.TunnelException;

import org.springframework.util.ClassUtils;

import static java.util.Collections.*;

/**
Expand Down Expand Up @@ -798,4 +800,17 @@ public static <T> T cast(Object value, Class<T> expectedClass) throws SchemaExce
return (T) value;
}
}

public static Class<?> determineCommonAncestor(Collection<Class<?>> classes) {
if (!classes.isEmpty()) {
Iterator<Class<?>> iterator = classes.iterator();
Class<?> currentCommonAncestor = iterator.next();
while (iterator.hasNext()) {
currentCommonAncestor = ClassUtils.determineCommonAncestor(currentCommonAncestor, iterator.next());
}
return currentCommonAncestor;
} else {
return null;
}
}
}
Expand Up @@ -276,6 +276,10 @@ public LensFocusContext<F> getFocusContext() {
return focusContext;
}

public boolean hasFocusContext() {
return focusContext != null;
}

@Override
@NotNull
public LensFocusContext<F> getFocusContextRequired() {
Expand Down
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2020 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.model.impl.lens.projector.policy.scriptExecutor;

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.model.api.ModelPublicConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType;

/**
* Creates "single run" scripting task.
*/
abstract class AbstractSingleRunTaskCreator extends ScriptingTaskCreator {

AbstractSingleRunTaskCreator(@NotNull ActionContext actx) {
super(actx);
}

@NotNull
TaskType createTaskForSingleRunScript(ExecuteScriptType executeScript, OperationResult result)
throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException,
SecurityViolationException, ExpressionEvaluationException {
TaskType newTask = createArchetypedTask(result);
setScriptInTask(newTask, executeScript);
return newTask;
}

@NotNull
private TaskType createArchetypedTask(OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException,
ConfigurationException, SecurityViolationException, ExpressionEvaluationException {

TaskType newTask = createEmptyTask(result);
newTask.setHandlerUri(ModelPublicConstants.SCRIPT_EXECUTION_TASK_HANDLER_URI);

// TODO task customizer
// TODO task archetype

return newTask;
}

}
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2020 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.model.impl.lens.projector.policy.scriptExecutor;

import com.evolveum.midpoint.model.impl.lens.EvaluatedPolicyRuleImpl;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ScriptExecutionPolicyActionType;

import org.jetbrains.annotations.NotNull;

/**
* Context of execution of specific "script execution" policy action.
*/
class ActionContext {

@NotNull final ScriptExecutionPolicyActionType action;
@NotNull final EvaluatedPolicyRuleImpl rule;
@NotNull final LensContext<?> context;
@NotNull final LensFocusContext<?> focusContext;
@NotNull final Task task;
@NotNull final PolicyRuleScriptExecutor beans;

ActionContext(@NotNull ScriptExecutionPolicyActionType action, @NotNull EvaluatedPolicyRuleImpl rule,
@NotNull LensContext<?> context, @NotNull Task task, @NotNull PolicyRuleScriptExecutor beans) {
this.action = action;
this.rule = rule;
this.context = context;
this.focusContext = context.getFocusContextRequired();
this.task = task;
this.beans = beans;
}
}

0 comments on commit 0901dda

Please sign in to comment.