Skip to content

Commit

Permalink
Clean up inbounds processing before pre-mappings
Browse files Browse the repository at this point in the history
Here we cleaned-up the processing of inbound mappings, in the order
to separate parts bound to the clockwork processing from these that
can be executed before the clockwork is even started.

Work in progress. The code is not cleaned up absolutely. But it is
the maximum that could be done in the given time.

BEHAVIORAL CHANGES (to release notes):

1. Up to now, we have skipped association inbound mappings if there was
no input value. This was not consistent with the handling of other
mappings. This is now changed. So, please make sure your mappings
correctly treat null input values. See resource-dummy-autogreen.xml
for an example.

2. Names of classes and packages that are relevant for logging has
been changed. To log the inbound processing in details, one should
now use "com.evolveum.midpoint.model.impl.lens.projector.focus.inbounds"
(however, this may even change before 4.5 release!)

Unrelated changes:
 - contains changes from dcdc09e
  • Loading branch information
mederly committed Feb 14, 2022
1 parent b8a3138 commit 2defd30
Show file tree
Hide file tree
Showing 37 changed files with 2,433 additions and 1,174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private static void putIntoFocus(FocusType preFocus, Item<?, ?> attributeItem) t
String localName = attribute.getElementName().getLocalPart();
ItemName directPath = new ItemName("", localName);
PrismPropertyDefinition<?> directDef = def.findPropertyDefinition(directPath);
if (directDef != null) {
if (directDef != null && isCompatible(attribute, directDef)) {
if (preFocusObject.findItem(directPath) == null) {
preFocusObject.add(
createPropertyClone(attribute, directDef));
Expand All @@ -131,7 +131,7 @@ private static void putIntoFocus(FocusType preFocus, Item<?, ?> attributeItem) t

ItemPath extensionPath = ItemPath.create(ObjectType.F_EXTENSION, directPath);
PrismPropertyDefinition<Object> extensionDef = def.findPropertyDefinition(extensionPath);
if (extensionDef != null) {
if (extensionDef != null && isCompatible(attribute, extensionDef)) {
if (preFocusObject.findItem(extensionPath) == null) {
preFocusObject.getOrCreateExtension().getValue()
.add(createPropertyClone(attribute, extensionDef));
Expand All @@ -142,6 +142,20 @@ private static void putIntoFocus(FocusType preFocus, Item<?, ?> attributeItem) t
LOGGER.trace("{} has no definition in focus", localName);
}

/** Can we copy the attribute to the target (knowing its definition)? */
private static boolean isCompatible(PrismProperty<?> attribute, PrismPropertyDefinition<?> targetDef) {
Class<?> targetType = targetDef.getTypeClassIfKnown();
if (targetType == null) {
return true; // most probably ok
}
for (Object realValue : attribute.getRealValues()) {
if (!targetType.isAssignableFrom(realValue.getClass())) {
return false;
}
}
return true;
}

@SuppressWarnings("unchecked")
@NotNull private static PrismProperty<?> createPropertyClone(
PrismProperty<?> attribute, PrismPropertyDefinition<?> directDef) throws SchemaException {
Expand Down
5 changes: 5 additions & 0 deletions model/model-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.evolveum.axiom</groupId>
<artifactId>axiom</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.evolveum.prism</groupId>
<artifactId>prism-impl</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,10 @@ public String getConst(String name) {

@Override
public ShadowType resolveEntitlement(ShadowAssociationType shadowAssociationType) {
if (shadowAssociationType == null) {
LOGGER.trace("No association");
return null;
}
ObjectReferenceType shadowRef = shadowAssociationType.getShadowRef();
if (shadowRef == null) {
LOGGER.trace("No shadowRef in association {}", shadowAssociationType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ boolean isOfType(Class<?> aClass) {
return object != null && aClass.isAssignableFrom(object.asObjectable().getClass());
}

PrismObjectDefinition<O> getObjectDefinition() {
@NotNull PrismObjectDefinition<O> getObjectDefinition() {
if (objectDefinition == null) {
PrismObjectDefinition<O> rawDefinition = null;
if (oldObject != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public LensElementContext(@NotNull ElementState<O> elementState, @NotNull LensCo
return state.getObjectTypeClass();
}

public PrismObjectDefinition<O> getObjectDefinition() {
public @NotNull PrismObjectDefinition<O> getObjectDefinition() {
return state.getObjectDefinition();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1693,4 +1693,19 @@ public void rotWithDeltaDeletion() {
public boolean isInMaintenance() {
return ResourceTypeUtil.isInMaintenance(resource);
}

/**
* Returns true if there is any context that depends on us.
* (Note that "dependency source" means the context that depends on the "dependency target". We are the target here.)
*/
public boolean hasDependentContext() {
for (LensProjectionContext projectionContext : lensContext.getProjectionContexts()) {
for (ResourceObjectTypeDependencyType dependency : projectionContext.getDependencies()) {
if (LensUtil.areDependent(projectionContext, this, dependency)) {
return true;
}
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -409,22 +409,19 @@ public static <F extends ObjectType> boolean hasLowerOrderContext(LensContext<F>
return false;
}

public static <F extends ObjectType> boolean hasDependentContext(LensContext<F> context,
LensProjectionContext targetProjectionContext) {
for (LensProjectionContext projectionContext: context.getProjectionContexts()) {
for (ResourceObjectTypeDependencyType dependency: projectionContext.getDependencies()) {
if (isDependencyTargetContext(projectionContext, targetProjectionContext, dependency)) {
return true;
}
}
}
return false;
}

public static <F extends ObjectType> boolean isDependencyTargetContext(LensProjectionContext sourceProjContext, LensProjectionContext targetProjectionContext, ResourceObjectTypeDependencyType dependency) {
ResourceShadowDiscriminator refDiscr = new ResourceShadowDiscriminator(dependency,
sourceProjContext.getResource().getOid(), sourceProjContext.getKind());
return targetProjectionContext.compareResourceShadowDiscriminator(refDiscr, false);
/**
* Returns true if there is a dependency of `source` on `target` under given `dependency` configuration.
* (Meaning that `source` depends on `target`!)
*
* I.e. there is a `dependency` configuration in `source` context pointing to `target`.
*/
public static <F extends ObjectType> boolean areDependent(
LensProjectionContext source,
LensProjectionContext target,
ResourceObjectTypeDependencyType dependency) {
ResourceShadowDiscriminator refDiscr = new ResourceShadowDiscriminator(
dependency, source.getResource().getOid(), source.getKind());
return target.compareResourceShadowDiscriminator(refDiscr, false);
}

public static <F extends ObjectType> LensProjectionContext findLowerOrderContext(LensContext<F> context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,10 @@ private MappingImpl<V, D> evaluateMapping()

private ConfigurableValuePolicySupplier createValuePolicySupplier() {
return new ConfigurableValuePolicySupplier() {
private ItemDefinition outputDefinition;
private ItemDefinition<?> outputDefinition;

@Override
public void setOutputDefinition(ItemDefinition outputDefinition) {
public void setOutputDefinition(ItemDefinition<?> outputDefinition) {
this.outputDefinition = outputDefinition;
}

Expand All @@ -219,7 +219,7 @@ public ValuePolicyType get(OperationResult result) {

if (mappingBean.getExpression() != null) {
List<JAXBElement<?>> evaluators = mappingBean.getExpression().getExpressionEvaluator();
for (JAXBElement jaxbEvaluator : evaluators) {
for (JAXBElement<?> jaxbEvaluator : evaluators) {
Object object = jaxbEvaluator.getValue();
if (object instanceof GenerateExpressionEvaluatorType && ((GenerateExpressionEvaluatorType) object).getValuePolicyRef() != null) {
ObjectReferenceType ref = ((GenerateExpressionEvaluatorType) object).getValuePolicyRef();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
import java.util.Iterator;
import java.util.List;

import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SchemaService;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.util.exception.*;
Expand Down Expand Up @@ -226,11 +224,11 @@ private <F extends ObjectType> LensProjectionContext determineProjectionWaveDepr
int determinedOrder = 0;

// This needs to go in the reverse. We need to figure out who depends on us.
for (DependencyAndSource ds: findReverseDependecies(context, projectionContext)) {
for (DependencyAndSource ds: findReverseDependencies(context, projectionContext)) {
LensProjectionContext dependencySourceContext = ds.sourceProjectionContext;
ResourceObjectTypeDependencyType outDependency = ds.dependency;
if (inDependency != null && isHigerOrder(outDependency, inDependency)) {
// There is incomming dependency. Deal only with dependencies of this order and lower
// There is incoming dependency. Deal only with dependencies of this order and lower
// otherwise we can end up in endless loop even for legal dependencies.
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(" processing (reversed) dependency: {}: ignore (higher order)", PrettyPrinter.prettyPrint(outDependency));
Expand Down Expand Up @@ -300,12 +298,15 @@ private <F extends ObjectType> LensProjectionContext determineProjectionWaveDepr
return resultAccountContext;
}

private <F extends ObjectType> Collection<DependencyAndSource> findReverseDependecies(LensContext<F> context,
/**
* Returns all contexts that depend on provided `targetProjectionContext`.
*/
private <F extends ObjectType> Collection<DependencyAndSource> findReverseDependencies(LensContext<F> context,
LensProjectionContext targetProjectionContext) {
Collection<DependencyAndSource> deps = new ArrayList<>();
for (LensProjectionContext projectionContext: context.getProjectionContexts()) {
for (ResourceObjectTypeDependencyType dependency: projectionContext.getDependencies()) {
if (LensUtil.isDependencyTargetContext(projectionContext, targetProjectionContext, dependency)) {
if (LensUtil.areDependent(projectionContext, targetProjectionContext, dependency)) {
DependencyAndSource ds = new DependencyAndSource();
ds.dependency = dependency;
ds.sourceProjectionContext = projectionContext;
Expand All @@ -316,7 +317,6 @@ private <F extends ObjectType> Collection<DependencyAndSource> findReverseDepend
return deps;
}


private void checkForCircular(List<ResourceObjectTypeDependencyType> depPath,
ResourceObjectTypeDependencyType outDependency, LensProjectionContext projectionContext) throws PolicyViolationException {
for (ResourceObjectTypeDependencyType pathElement: depPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ MappingImpl<V, D> createFocusMapping(
private ItemDefinition<?> outputDefinition;

@Override
public void setOutputDefinition(ItemDefinition outputDefinition) {
public void setOutputDefinition(ItemDefinition<?> outputDefinition) {
this.outputDefinition = outputDefinition;
}

Expand Down

0 comments on commit 2defd30

Please sign in to comment.