Search in sources :

Example 1 with Mapping

use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.

the class Construction method debugDump.

@Override
public String debugDump(int indent) {
    StringBuilder sb = new StringBuilder();
    DebugUtil.debugDumpLabel(sb, "Construction", indent);
    if (refinedObjectClassDefinition == null) {
        sb.append(" (no object class definition)");
        if (getConstructionType() != null && getConstructionType().getResourceRef() != null) {
            // should
            // be
            // always
            // the
            // case
            sb.append("\n");
            DebugUtil.debugDumpLabel(sb, "resourceRef / kind / intent", indent + 1);
            sb.append(" ");
            sb.append(ObjectTypeUtil.toShortString(getConstructionType().getResourceRef()));
            sb.append(" / ");
            sb.append(getConstructionType().getKind());
            sb.append(" / ");
            sb.append(getConstructionType().getIntent());
        }
    } else {
        sb.append(refinedObjectClassDefinition.getShadowDiscriminator());
    }
    if (getConstructionType() != null && getConstructionType().getStrength() == ConstructionStrengthType.WEAK) {
        sb.append(" weak");
    }
    sb.append("\n");
    DebugUtil.debugDumpWithLabel(sb, "isValid", isValid(), indent + 1);
    sb.append("\n");
    DebugUtil.debugDumpLabel(sb, "auxiliary object classes", indent + 1);
    if (auxiliaryObjectClassDefinitions == null) {
        sb.append(" (null)");
    } else if (auxiliaryObjectClassDefinitions.isEmpty()) {
        sb.append(" (empty)");
    } else {
        for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
            sb.append("\n");
            DebugUtil.indentDebugDump(sb, indent + 2);
            sb.append(auxiliaryObjectClassDefinition.getTypeName());
        }
    }
    if (getConstructionType() != null && getConstructionType().getDescription() != null) {
        sb.append("\n");
        DebugUtil.debugDumpLabel(sb, "description", indent + 1);
        sb.append(" ").append(getConstructionType().getDescription());
    }
    if (attributeMappings != null && !attributeMappings.isEmpty()) {
        sb.append("\n");
        DebugUtil.debugDumpLabel(sb, "attribute mappings", indent + 1);
        for (Mapping mapping : attributeMappings) {
            sb.append("\n");
            sb.append(mapping.debugDump(indent + 2));
        }
    }
    if (associationMappings != null && !associationMappings.isEmpty()) {
        sb.append("\n");
        DebugUtil.debugDumpLabel(sb, "association mappings", indent + 1);
        for (Mapping mapping : associationMappings) {
            sb.append("\n");
            sb.append(mapping.debugDump(indent + 2));
        }
    }
    if (getAssignmentPath() != null) {
        sb.append("\n");
        sb.append(getAssignmentPath().debugDump(indent + 1));
    }
    return sb.toString();
}
Also used : RefinedObjectClassDefinition(com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition) Mapping(com.evolveum.midpoint.model.common.mapping.Mapping)

Example 2 with Mapping

use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.

the class OutboundProcessor method processOutbound.

public <F extends FocusType> void processOutbound(LensContext<F> context, LensProjectionContext projCtx, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException {
    ResourceShadowDiscriminator discr = projCtx.getResourceShadowDiscriminator();
    ObjectDelta<ShadowType> projectionDelta = projCtx.getDelta();
    if (projectionDelta != null && projectionDelta.getChangeType() == ChangeType.DELETE) {
        LOGGER.trace("Processing outbound expressions for {} skipped, DELETE account delta", discr);
        // No point in evaluating outbound
        return;
    }
    LOGGER.trace("Processing outbound expressions for {} starting", discr);
    RefinedObjectClassDefinition rOcDef = projCtx.getStructuralObjectClassDefinition();
    if (rOcDef == null) {
        LOGGER.error("Definition for {} not found in the context, but it should be there, dumping context:\n{}", discr, context.debugDump());
        throw new IllegalStateException("Definition for " + discr + " not found in the context, but it should be there");
    }
    ObjectDeltaObject<F> focusOdo = context.getFocusContext().getObjectDeltaObject();
    ObjectDeltaObject<ShadowType> projectionOdo = projCtx.getObjectDeltaObject();
    Construction<F> outboundConstruction = new Construction<>(null, projCtx.getResource());
    outboundConstruction.setRefinedObjectClassDefinition(rOcDef);
    Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions = rOcDef.getAuxiliaryObjectClassDefinitions();
    if (auxiliaryObjectClassDefinitions != null) {
        for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
            outboundConstruction.addAuxiliaryObjectClassDefinition(auxiliaryObjectClassDefinition);
        }
    }
    String operation = projCtx.getOperation().getValue();
    for (QName attributeName : rOcDef.getNamesOfAttributesWithOutboundExpressions()) {
        RefinedAttributeDefinition<?> refinedAttributeDefinition = rOcDef.findAttributeDefinition(attributeName);
        final MappingType outboundMappingType = refinedAttributeDefinition.getOutboundMappingType();
        if (outboundMappingType == null) {
            continue;
        }
        if (refinedAttributeDefinition.isIgnored(LayerType.MODEL)) {
            LOGGER.trace("Skipping processing outbound mapping for attribute {} because it is ignored", attributeName);
            continue;
        }
        Mapping.Builder<PrismPropertyValue<?>, RefinedAttributeDefinition<?>> builder = mappingFactory.createMappingBuilder(outboundMappingType, "outbound mapping for " + PrettyPrinter.prettyPrint(refinedAttributeDefinition.getName()) + " in " + rOcDef.getResourceType());
        builder = builder.originObject(rOcDef.getResourceType()).originType(OriginType.OUTBOUND);
        Mapping<PrismPropertyValue<?>, RefinedAttributeDefinition<?>> evaluatedMapping = evaluateMapping(builder, attributeName, refinedAttributeDefinition, focusOdo, projectionOdo, operation, rOcDef, null, context, projCtx, task, result);
        if (evaluatedMapping != null) {
            outboundConstruction.addAttributeMapping(evaluatedMapping);
        }
    }
    for (QName assocName : rOcDef.getNamesOfAssociationsWithOutboundExpressions()) {
        RefinedAssociationDefinition associationDefinition = rOcDef.findAssociationDefinition(assocName);
        final MappingType outboundMappingType = associationDefinition.getOutboundMappingType();
        if (outboundMappingType == null) {
            continue;
        }
        //			if (associationDefinition.isIgnored(LayerType.MODEL)) {
        //				LOGGER.trace("Skipping processing outbound mapping for attribute {} because it is ignored", assocName);
        //				continue;
        //			}
        Mapping.Builder<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> mappingBuilder = mappingFactory.createMappingBuilder(outboundMappingType, "outbound mapping for " + PrettyPrinter.prettyPrint(associationDefinition.getName()) + " in " + rOcDef.getResourceType());
        PrismContainerDefinition<ShadowAssociationType> outputDefinition = getAssociationContainerDefinition();
        Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluatedMapping = (Mapping) evaluateMapping(mappingBuilder, assocName, outputDefinition, focusOdo, projectionOdo, operation, rOcDef, associationDefinition.getAssociationTarget(), context, projCtx, task, result);
        if (evaluatedMapping != null) {
            outboundConstruction.addAssociationMapping(evaluatedMapping);
        }
    }
    projCtx.setOutboundConstruction(outboundConstruction);
}
Also used : MappingType(com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType) Mapping(com.evolveum.midpoint.model.common.mapping.Mapping) RefinedAssociationDefinition(com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition) RefinedObjectClassDefinition(com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition) RefinedAttributeDefinition(com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition) ShadowAssociationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue) Construction(com.evolveum.midpoint.model.impl.lens.Construction) PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) QName(javax.xml.namespace.QName) PrismContainerDefinition(com.evolveum.midpoint.prism.PrismContainerDefinition) ResourceShadowDiscriminator(com.evolveum.midpoint.schema.ResourceShadowDiscriminator)

Example 3 with Mapping

use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.

the class AssignmentProcessor method collectFocusTripleFromMappings.

private <V extends PrismValue, D extends ItemDefinition, F extends FocusType> XMLGregorianCalendar collectFocusTripleFromMappings(Collection<EvaluatedAssignmentImpl<F>> evaluatedAssignments, Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> outputTripleMap, PlusMinusZero plusMinusZero) throws SchemaException {
    XMLGregorianCalendar nextRecomputeTime = null;
    for (EvaluatedAssignmentImpl<F> ea : evaluatedAssignments) {
        Collection<Mapping<V, D>> focusMappings = (Collection) ea.getFocusMappings();
        for (Mapping<V, D> mapping : focusMappings) {
            ItemPath itemPath = mapping.getOutputPath();
            DeltaSetTriple<ItemValueWithOrigin<V, D>> outputTriple = ItemValueWithOrigin.createOutputTriple(mapping);
            if (outputTriple == null) {
                continue;
            }
            if (plusMinusZero == PlusMinusZero.PLUS) {
                outputTriple.addAllToPlusSet(outputTriple.getZeroSet());
                outputTriple.clearZeroSet();
                outputTriple.clearMinusSet();
            } else if (plusMinusZero == PlusMinusZero.MINUS) {
                outputTriple.addAllToMinusSet(outputTriple.getZeroSet());
                outputTriple.clearZeroSet();
                outputTriple.clearPlusSet();
            }
            DeltaSetTriple<ItemValueWithOrigin<V, D>> mapTriple = (DeltaSetTriple<ItemValueWithOrigin<V, D>>) outputTripleMap.get(itemPath);
            if (mapTriple == null) {
                outputTripleMap.put(itemPath, outputTriple);
            } else {
                mapTriple.merge(outputTriple);
            }
        }
    }
    return nextRecomputeTime;
}
Also used : PrismValueDeltaSetTriple(com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple) DeltaSetTriple(com.evolveum.midpoint.prism.delta.DeltaSetTriple) Mapping(com.evolveum.midpoint.model.common.mapping.Mapping) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 4 with Mapping

use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.

the class InboundProcessor method evaluateInboundMapping.

private <A, F extends FocusType, V extends PrismValue, D extends ItemDefinition> ItemDelta<V, D> evaluateInboundMapping(final LensContext<F> context, MappingType inboundMappingType, QName accountAttributeName, PrismProperty<A> oldAccountProperty, PropertyDelta<A> attributeAPrioriDelta, PrismObject<F> focusNew, PrismObject<ShadowType> account, ResourceType resource, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, ConfigurationException {
    if (oldAccountProperty != null && oldAccountProperty.hasRaw()) {
        throw new SystemException("Property " + oldAccountProperty + " has raw parsing state, such property cannot be used in inbound expressions");
    }
    Mapping.Builder<V, D> builder = mappingFactory.createMappingBuilder(inboundMappingType, "inbound expression for " + accountAttributeName + " in " + resource);
    if (!builder.isApplicableToChannel(context.getChannel())) {
        return null;
    }
    Source<PrismPropertyValue<A>, PrismPropertyDefinition<A>> defaultSource = new Source<>(oldAccountProperty, attributeAPrioriDelta, null, ExpressionConstants.VAR_INPUT);
    defaultSource.recompute();
    Mapping<V, D> mapping = builder.defaultSource(defaultSource).targetContext(LensUtil.getFocusDefinition(context)).addVariableDefinition(ExpressionConstants.VAR_USER, focusNew).addVariableDefinition(ExpressionConstants.VAR_FOCUS, focusNew).addVariableDefinition(ExpressionConstants.VAR_ACCOUNT, account).addVariableDefinition(ExpressionConstants.VAR_SHADOW, account).addVariableDefinition(ExpressionConstants.VAR_RESOURCE, resource).stringPolicyResolver(createStringPolicyResolver(context, task, result)).originType(OriginType.INBOUND).originObject(resource).build();
    if (checkWeakSkip(mapping, focusNew)) {
        LOGGER.trace("Skipping because of mapping is weak and focus property has already a value");
        return null;
    }
    ItemPath targetFocusItemPath = mapping.getOutputPath();
    if (ItemPath.isNullOrEmpty(targetFocusItemPath)) {
        throw new ConfigurationException("Empty target path in " + mapping.getContextDescription());
    }
    Item targetFocusItem = null;
    if (focusNew != null) {
        targetFocusItem = focusNew.findItem(targetFocusItemPath);
    }
    PrismObjectDefinition<F> focusDefinition = context.getFocusContext().getObjectDefinition();
    ItemDefinition targetItemDef = focusDefinition.findItemDefinition(targetFocusItemPath);
    if (targetItemDef == null) {
        throw new SchemaException("No definition for focus property " + targetFocusItemPath + ", cannot process inbound expression in " + resource);
    }
    final ItemDelta outputFocusItemDelta = targetItemDef.createEmptyDelta(targetFocusItemPath);
    mappingEvaluator.evaluateMapping(mapping, context, task, result);
    PrismValueDeltaSetTriple<V> triple = mapping.getOutputTriple();
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("Inbound mapping for {} returned triple:\n{}", accountAttributeName, triple == null ? "null" : triple.debugDump());
    }
    if (triple != null) {
        if (triple.hasPlusSet()) {
            boolean alreadyReplaced = false;
            for (V value : triple.getPlusSet()) {
                if (targetFocusItem != null && targetFocusItem.hasRealValue(value)) {
                    continue;
                }
                //if property is not multi value replace existing attribute
                if (targetFocusItem != null && !targetFocusItem.getDefinition().isMultiValue() && !targetFocusItem.isEmpty()) {
                    Collection<V> replace = new ArrayList<V>();
                    replace.add((V) value.clone());
                    outputFocusItemDelta.setValuesToReplace(replace);
                    if (alreadyReplaced) {
                        LOGGER.warn("Multiple values for a single-valued property {}; duplicate value = {}", targetFocusItem, value);
                    } else {
                        alreadyReplaced = true;
                    }
                } else {
                    outputFocusItemDelta.addValueToAdd(value.clone());
                }
            }
        }
        if (triple.hasMinusSet()) {
            LOGGER.trace("Checking account sync property delta values to delete");
            for (V value : triple.getMinusSet()) {
                if (targetFocusItem == null || targetFocusItem.hasRealValue(value)) {
                    if (!outputFocusItemDelta.isReplace()) {
                        // This is not needed if we are going to replace. In fact it might cause an error.
                        outputFocusItemDelta.addValueToDelete(value);
                    }
                }
            }
        }
        Item shouldBeItem = targetItemDef.instantiate();
        shouldBeItem.addAll(PrismValue.cloneCollection(triple.getZeroSet()));
        shouldBeItem.addAll(PrismValue.cloneCollection(triple.getPlusSet()));
        if (targetFocusItem != null) {
            ItemDelta diffDelta = targetFocusItem.diff(shouldBeItem);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Comparing focus item:\n{}\nto should be item:\n{}\ndiff:\n{} ", DebugUtil.debugDump(targetFocusItem, 1), DebugUtil.debugDump(shouldBeItem, 1), DebugUtil.debugDump(diffDelta, 1));
            }
            if (diffDelta != null) {
                if (mapping.isTolerant() == Boolean.TRUE) {
                    // this is probably not correct, as the default for inbounds should be TRUE
                    if (diffDelta.isReplace()) {
                        if (diffDelta.getValuesToReplace().isEmpty()) {
                            diffDelta.resetValuesToReplace();
                            if (LOGGER.isTraceEnabled()) {
                                LOGGER.trace("Removing empty replace part of the diff delta because mapping is tolerant:\n{}", diffDelta.debugDump());
                            }
                        } else {
                            if (LOGGER.isTraceEnabled()) {
                                LOGGER.trace("Making sure that the replace part of the diff contains old values delta because mapping is tolerant:\n{}", diffDelta.debugDump());
                            }
                            for (Object shouldBeValueObj : shouldBeItem.getValues()) {
                                PrismValue shouldBeValue = (PrismValue) shouldBeValueObj;
                                if (!PrismValue.containsRealValue(diffDelta.getValuesToReplace(), shouldBeValue)) {
                                    diffDelta.addValueToReplace(shouldBeValue.clone());
                                }
                            }
                        }
                    } else {
                        diffDelta.resetValuesToDelete();
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace("Removing delete part of the diff delta because mapping is tolerant:\n{}", diffDelta.debugDump());
                        }
                    }
                }
                diffDelta.setElementName(ItemPath.getName(targetFocusItemPath.last()));
                diffDelta.setParentPath(targetFocusItemPath.allExceptLast());
                outputFocusItemDelta.merge(diffDelta);
            }
        } else {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Adding user property because inbound say so (account doesn't contain that value):\n{}", shouldBeItem.getValues());
            }
            //if user property doesn't exist we have to add it (as delta), because inbound say so
            outputFocusItemDelta.addValuesToAdd(shouldBeItem.getClonedValues());
        }
    } else {
    // triple == null
    // the mapping is not applicable. Nothing to do.
    }
    // if no changes were generated return null
    return outputFocusItemDelta.isEmpty() ? null : outputFocusItemDelta;
}
Also used : ArrayList(java.util.ArrayList) Mapping(com.evolveum.midpoint.model.common.mapping.Mapping) Source(com.evolveum.midpoint.repo.common.expression.Source) ItemDeltaItem(com.evolveum.midpoint.repo.common.expression.ItemDeltaItem) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 5 with Mapping

use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.

the class Construction method evaluateAssociation.

private Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluateAssociation(ResourceObjectAssociationType associationDefinitionType, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
    QName assocName = ItemPathUtil.getOnlySegmentQName(associationDefinitionType.getRef());
    if (assocName == null) {
        throw new SchemaException("Missing 'ref' in association in construction in " + getSource());
    }
    MappingType outboundMappingType = associationDefinitionType.getOutbound();
    if (outboundMappingType == null) {
        throw new SchemaException("No outbound section in definition of association " + assocName + " in construction in " + getSource());
    }
    PrismContainerDefinition<ShadowAssociationType> outputDefinition = getAssociationContainerDefinition();
    Mapping.Builder<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> mappingBuilder = mappingFactory.<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>createMappingBuilder().mappingType(outboundMappingType).contextDescription("for association " + PrettyPrinter.prettyPrint(assocName) + " in " + getSource()).originType(OriginType.ASSIGNMENTS).originObject(getSource());
    RefinedAssociationDefinition rAssocDef = refinedObjectClassDefinition.findAssociationDefinition(assocName);
    if (rAssocDef == null) {
        throw new SchemaException("No association " + assocName + " in object class " + refinedObjectClassDefinition.getHumanReadableName() + " in construction in " + getSource());
    }
    Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluatedMapping = evaluateMapping(mappingBuilder, assocName, outputDefinition, rAssocDef.getAssociationTarget(), task, result);
    LOGGER.trace("Evaluated mapping for association " + assocName + ": " + evaluatedMapping);
    return evaluatedMapping;
}
Also used : MappingType(com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) QName(javax.xml.namespace.QName) PrismContainerDefinition(com.evolveum.midpoint.prism.PrismContainerDefinition) Mapping(com.evolveum.midpoint.model.common.mapping.Mapping) ShadowAssociationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType) RefinedAssociationDefinition(com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition)

Aggregations

Mapping (com.evolveum.midpoint.model.common.mapping.Mapping)12 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)7 QName (javax.xml.namespace.QName)5 PrismContainerDefinition (com.evolveum.midpoint.prism.PrismContainerDefinition)4 PrismContainerValue (com.evolveum.midpoint.prism.PrismContainerValue)4 PrismPropertyValue (com.evolveum.midpoint.prism.PrismPropertyValue)4 ItemDeltaItem (com.evolveum.midpoint.repo.common.expression.ItemDeltaItem)4 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)4 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)4 MappingType (com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType)4 RefinedObjectClassDefinition (com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition)3 ItemDefinition (com.evolveum.midpoint.prism.ItemDefinition)3 DeltaSetTriple (com.evolveum.midpoint.prism.delta.DeltaSetTriple)3 PrismValueDeltaSetTriple (com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple)3 ResourceShadowDiscriminator (com.evolveum.midpoint.schema.ResourceShadowDiscriminator)3 Task (com.evolveum.midpoint.task.api.Task)3 ShadowAssociationType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType)3 ArrayList (java.util.ArrayList)3 XMLGregorianCalendar (javax.xml.datatype.XMLGregorianCalendar)3 RefinedAssociationDefinition (com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition)2