Skip to content

Commit

Permalink
Refactoring ModelExpressionThreadLocalHolder (MID-3661)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Jan 16, 2017
1 parent 0097cd2 commit 47f5f6a
Show file tree
Hide file tree
Showing 14 changed files with 188 additions and 135 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2015 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@
package com.evolveum.midpoint.certification.impl;

import com.evolveum.midpoint.model.api.expr.OrgStructFunctions;
import com.evolveum.midpoint.model.impl.expr.ExpressionEnvironment;
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
Expand Down Expand Up @@ -111,8 +112,7 @@ private boolean containsOid(List<ObjectReferenceType> reviewers, String oid) {
}

private Collection<ObjectReferenceType> getObjectManagers(AccessCertificationCaseType _case, ManagerSearchType managerSearch, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException {
ModelExpressionThreadLocalHolder.pushCurrentResult(result);
ModelExpressionThreadLocalHolder.pushCurrentTask(task);
ModelExpressionThreadLocalHolder.pushExpressionEnvironment(new ExpressionEnvironment<>(task, result));
try {
ObjectReferenceType objectRef = _case.getObjectRef();
ObjectType object = resolveReference(objectRef, ObjectType.class, result);
Expand Down Expand Up @@ -141,8 +141,7 @@ private Collection<ObjectReferenceType> getObjectManagers(AccessCertificationCas
// never occurs, as preAuthorized is TRUE above
throw new IllegalStateException("Impossible has happened: " + e.getMessage(), e);
} finally {
ModelExpressionThreadLocalHolder.popCurrentResult();
ModelExpressionThreadLocalHolder.popCurrentTask();
ModelExpressionThreadLocalHolder.popExpressionEnvironment();
}
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2016 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,6 +22,7 @@
import com.evolveum.midpoint.model.common.mapping.Mapping;
import com.evolveum.midpoint.model.common.mapping.MappingFactory;
import com.evolveum.midpoint.model.impl.ModelObjectResolver;
import com.evolveum.midpoint.model.impl.expr.ExpressionEnvironment;
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
Expand Down Expand Up @@ -80,13 +81,11 @@ public MappingEvaluationResponseType evaluateMapping(@NotNull MappingEvaluationR

Mapping<?,?> mapping = builder.build();

ModelExpressionThreadLocalHolder.pushCurrentResult(result);
ModelExpressionThreadLocalHolder.pushCurrentTask(task);
ModelExpressionThreadLocalHolder.pushExpressionEnvironment(new ExpressionEnvironment<>(task, result));
try {
mapping.evaluate(task, result);
} finally {
ModelExpressionThreadLocalHolder.popCurrentResult();
ModelExpressionThreadLocalHolder.popCurrentTask();
ModelExpressionThreadLocalHolder.popExpressionEnvironment();
}

StringBuilder sb = new StringBuilder();
Expand Down
@@ -0,0 +1,93 @@
/**
* Copyright (c) 2017 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.expr;

import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

/**
* @author semancik
*
*/
public class ExpressionEnvironment<F extends ObjectType> {

private LensContext<F> lensContext;
private LensProjectionContext projectionContext;
private OperationResult currentResult;
private Task currentTask;

public ExpressionEnvironment() {
super();
}

public ExpressionEnvironment(Task currentTask, OperationResult currentResult) {
super();
this.currentResult = currentResult;
this.currentTask = currentTask;
}

public ExpressionEnvironment(LensContext<F> lensContext, LensProjectionContext projectionContext,
Task currentTask, OperationResult currentResult) {
super();
this.lensContext = lensContext;
this.projectionContext = projectionContext;
this.currentResult = currentResult;
this.currentTask = currentTask;
}

public LensContext<F> getLensContext() {
return lensContext;
}

public void setLensContext(LensContext<F> lensContext) {
this.lensContext = lensContext;
}

public LensProjectionContext getProjectionContext() {
return projectionContext;
}

public void setProjectionContext(LensProjectionContext projectionContext) {
this.projectionContext = projectionContext;
}

public OperationResult getCurrentResult() {
return currentResult;
}

public void setCurrentResult(OperationResult currentResult) {
this.currentResult = currentResult;
}

public Task getCurrentTask() {
return currentTask;
}

public void setCurrentTask(Task currentTask) {
this.currentTask = currentTask;
}

@Override
public String toString() {
return "ExpressionEnvironment(lensContext=" + lensContext + ", projectionContext="
+ projectionContext + ", currentResult=" + currentResult + ", currentTask=" + currentTask
+ ")";
}

}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2015 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2016 Evolveum
* Copyright (c) 2013-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,13 +21,11 @@
import com.evolveum.midpoint.model.common.expression.Expression;
import com.evolveum.midpoint.model.common.expression.ExpressionEvaluationContext;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensContextPlaceholder;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.Holder;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
Expand All @@ -39,99 +37,66 @@
*/
public class ModelExpressionThreadLocalHolder {

private static ThreadLocal<Deque<LensContext<ObjectType>>> lensContextStackTl =
new ThreadLocal<Deque<LensContext<ObjectType>>>();
private static ThreadLocal<Deque<OperationResult>> currentResultStackTl = new ThreadLocal<Deque<OperationResult>>();
private static ThreadLocal<Deque<Holder<Task>>> currentTaskStackTl = new ThreadLocal<>(); // to allow task to be null

public static <F extends ObjectType> void pushLensContext(LensContext<F> ctx) {
Deque<LensContext<ObjectType>> stack = lensContextStackTl.get();
private static ThreadLocal<Deque<ExpressionEnvironment<ObjectType>>> expressionEnvironmentStackTl =
new ThreadLocal<>();

public static <F extends ObjectType> void pushExpressionEnvironment(ExpressionEnvironment<F> env) {
Deque<ExpressionEnvironment<ObjectType>> stack = expressionEnvironmentStackTl.get();
if (stack == null) {
stack = new ArrayDeque<LensContext<ObjectType>>();
lensContextStackTl.set(stack);
}
if (ctx == null) {
// Deque cannot hold null elements. So we need to create a placeholder
ctx = new LensContextPlaceholder<>(null);
stack = new ArrayDeque<>();
expressionEnvironmentStackTl.set(stack);
}
stack.push((LensContext<ObjectType>)ctx);
stack.push((ExpressionEnvironment<ObjectType>)env);
}

public static <F extends ObjectType> void popLensContext() {
Deque<LensContext<ObjectType>> stack = lensContextStackTl.get();
public static <F extends ObjectType> void popExpressionEnvironment() {
Deque<ExpressionEnvironment<ObjectType>> stack = expressionEnvironmentStackTl.get();
stack.pop();
}

public static <F extends ObjectType> LensContext<F> getLensContext() {
Deque<LensContext<ObjectType>> stack = lensContextStackTl.get();
public static <F extends ObjectType> ExpressionEnvironment<F> getExpressionEnvironment() {
Deque<ExpressionEnvironment<ObjectType>> stack = expressionEnvironmentStackTl.get();
if (stack == null) {
return null;
}
LensContext<F> ctx = (LensContext<F>) stack.peek();
if (ctx instanceof LensContextPlaceholder) {
return null;
} else {
return ctx;
}
return (ExpressionEnvironment<F>) stack.peek();
}

public static void pushCurrentResult(OperationResult result) {
Deque<OperationResult> stack = currentResultStackTl.get();
if (stack == null) {
stack = new ArrayDeque<OperationResult>();
currentResultStackTl.set(stack);
public static <F extends ObjectType> LensContext<F> getLensContext() {
ExpressionEnvironment<ObjectType> env = getExpressionEnvironment();
if (env == null) {
return null;
}
stack.push(result);
return (LensContext<F>) env.getLensContext();
}

public static void popCurrentResult() {
Deque<OperationResult> stack = currentResultStackTl.get();
stack.pop();
}

public static OperationResult getCurrentResult() {
Deque<OperationResult> stack = currentResultStackTl.get();
if (stack == null) {
public static Task getCurrentTask() {
ExpressionEnvironment<ObjectType> env = getExpressionEnvironment();
if (env == null) {
return null;
}
return stack.peek();
}

public static void pushCurrentTask(Task task) {
Deque<Holder<Task>> stack = currentTaskStackTl.get();
if (stack == null) {
stack = new ArrayDeque<>();
currentTaskStackTl.set(stack);
}
stack.push(new Holder<>(task));
return env.getCurrentTask();
}

public static void popCurrentTask() {
Deque<Holder<Task>> stack = currentTaskStackTl.get();
stack.pop();
}

public static Task getCurrentTask() {
Deque<Holder<Task>> stack = currentTaskStackTl.get();
if (stack == null) {
public static OperationResult getCurrentResult() {
ExpressionEnvironment<ObjectType> env = getExpressionEnvironment();
if (env == null) {
return null;
}
Holder<Task> holder = stack.peek();
return holder != null ? holder.getValue() : null;
return env.getCurrentResult();
}

// TODO move to better place
public static <T> PrismValueDeltaSetTriple<PrismPropertyValue<T>> evaluateExpressionInContext(Expression<PrismPropertyValue<T>,
PrismPropertyDefinition<T>> expression, ExpressionEvaluationContext params, Task task, OperationResult result)
throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException {
ModelExpressionThreadLocalHolder.pushCurrentResult(result);
ModelExpressionThreadLocalHolder.pushCurrentTask(task);
ExpressionEnvironment<?> env = new ExpressionEnvironment<>(task, result);
ModelExpressionThreadLocalHolder.pushExpressionEnvironment(env);
PrismValueDeltaSetTriple<PrismPropertyValue<T>> exprResultTriple;
try {
exprResultTriple = expression.evaluate(params);
} finally {
ModelExpressionThreadLocalHolder.popCurrentResult();
ModelExpressionThreadLocalHolder.popCurrentTask();
ModelExpressionThreadLocalHolder.popExpressionEnvironment();
}
return exprResultTriple;
}
Expand Down
Expand Up @@ -34,6 +34,7 @@
import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject;
import com.evolveum.midpoint.model.common.mapping.Mapping;
import com.evolveum.midpoint.model.common.mapping.MappingFactory;
import com.evolveum.midpoint.model.impl.expr.ExpressionEnvironment;
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator;
import com.evolveum.midpoint.model.impl.util.Utils;
Expand Down Expand Up @@ -546,9 +547,11 @@ private <O extends ObjectType> List<PrismObject<O>> resolveTargets(AssignmentTyp

private <O extends ObjectType> List<PrismObject<O>> resolveTargetsFromFilter(Class<O> clazz, AssignmentPathSegment assignmentPathSegment, ObjectType source, SearchFilterType filter, String sourceDescription, AssignmentPathImpl assignmentPath, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException{
// SearchFilterType filter = targetRef.getFilter();
ModelExpressionThreadLocalHolder.pushLensContext(lensContext);
ModelExpressionThreadLocalHolder.pushCurrentResult(result);
ModelExpressionThreadLocalHolder.pushCurrentTask(task);
ExpressionEnvironment<F> env = new ExpressionEnvironment<>();
env.setLensContext(lensContext);
env.setCurrentResult(result);
env.setCurrentTask(task);
ModelExpressionThreadLocalHolder.pushExpressionEnvironment(env);
try {

PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(result);
Expand All @@ -573,9 +576,7 @@ private <O extends ObjectType> List<PrismObject<O>> resolveTargetsFromFilter(Cla
return targets;

} finally {
ModelExpressionThreadLocalHolder.popLensContext();
ModelExpressionThreadLocalHolder.popCurrentResult();
ModelExpressionThreadLocalHolder.popCurrentTask();
ModelExpressionThreadLocalHolder.popExpressionEnvironment();
}

}
Expand Down
Expand Up @@ -29,6 +29,7 @@

import com.evolveum.midpoint.model.common.mapping.Mapping;
import com.evolveum.midpoint.model.common.mapping.MappingFactory;
import com.evolveum.midpoint.model.impl.expr.ExpressionEnvironment;
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensElementContext;
Expand Down Expand Up @@ -75,9 +76,11 @@ public class MappingEvaluator {

public <V extends PrismValue, D extends ItemDefinition, F extends ObjectType> void evaluateMapping(
Mapping<V,D> mapping, LensContext<F> lensContext, Task task, OperationResult parentResult) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
ModelExpressionThreadLocalHolder.pushLensContext(lensContext);
ModelExpressionThreadLocalHolder.pushCurrentResult(parentResult);
ModelExpressionThreadLocalHolder.pushCurrentTask(task);
ExpressionEnvironment<F> env = new ExpressionEnvironment<>();
env.setLensContext(lensContext);
env.setCurrentResult(parentResult);
env.setCurrentTask(task);
ModelExpressionThreadLocalHolder.pushExpressionEnvironment(env);
ObjectType originObject = mapping.getOriginObject();
String objectOid, objectName, objectTypeName;
if (originObject != null) {
Expand All @@ -98,9 +101,7 @@ public <V extends PrismValue, D extends ItemDefinition, F extends ObjectType> vo
throw new IllegalArgumentException(e.getMessage()+" in "+mapping.getContextDescription(), e);
} finally {
task.recordMappingOperation(objectOid, objectName, objectTypeName, mappingName, System.currentTimeMillis() - start);
ModelExpressionThreadLocalHolder.popLensContext();
ModelExpressionThreadLocalHolder.popCurrentResult();
ModelExpressionThreadLocalHolder.popCurrentTask();
ModelExpressionThreadLocalHolder.popExpressionEnvironment();
if (lensContext.getDebugListener() != null) {
lensContext.getDebugListener().afterMappingEvaluation(lensContext, mapping);
}
Expand Down

0 comments on commit 47f5f6a

Please sign in to comment.