Search in sources :

Example 1 with UniformItemPath

use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.

the class ActivationProcessor method reconcileOutboundValue.

/**
 * TODO: can we align this with ReconciliationProcessor?
 */
private <T, F extends FocusType> void reconcileOutboundValue(LensContext<F> context, LensProjectionContext projCtx, Map<UniformItemPath, MappingOutputStruct<PrismPropertyValue<T>>> outputTripleMap, String desc) throws SchemaException {
    for (Entry<UniformItemPath, MappingOutputStruct<PrismPropertyValue<T>>> entry : outputTripleMap.entrySet()) {
        UniformItemPath mappingOutputPath = entry.getKey();
        MappingOutputStruct<PrismPropertyValue<T>> mappingOutputStruct = entry.getValue();
        if (mappingOutputStruct.isWeakMappingWasUsed()) {
            // Thing to do. All deltas should already be in context
            LOGGER.trace("Skip reconciliation of {} in {} because of weak", mappingOutputPath, desc);
            continue;
        }
        if (!mappingOutputStruct.isStrongMappingWasUsed()) {
            // Normal mappings are not processed for reconciliation
            LOGGER.trace("Skip reconciliation of {} in {} because not strong", mappingOutputPath, desc);
            continue;
        }
        LOGGER.trace("reconciliation of {} for {}", mappingOutputPath, desc);
        PrismObjectDefinition<ShadowType> targetObjectDefinition = projCtx.getObjectDefinition();
        PrismPropertyDefinition<T> targetItemDefinition = targetObjectDefinition.findPropertyDefinition(mappingOutputPath);
        if (targetItemDefinition == null) {
            throw new SchemaException("No definition for item " + mappingOutputPath + " in " + targetObjectDefinition);
        }
        PropertyDelta<T> targetItemDelta = targetItemDefinition.createEmptyDelta(mappingOutputPath);
        PrismValueDeltaSetTriple<PrismPropertyValue<T>> outputTriple = mappingOutputStruct.getOutputTriple();
        PrismProperty<T> currentTargetItem = null;
        PrismObject<ShadowType> shadowCurrent = projCtx.getObjectCurrent();
        if (shadowCurrent != null) {
            currentTargetItem = shadowCurrent.findProperty(mappingOutputPath);
        }
        Collection<PrismPropertyValue<T>> hasValues = new ArrayList<>();
        if (currentTargetItem != null) {
            hasValues.addAll(currentTargetItem.getValues());
        }
        Collection<PrismPropertyValue<T>> shouldHaveValues = outputTriple.getNonNegativeValues();
        LOGGER.trace("Reconciliation of {}:\n  hasValues:\n{}\n  shouldHaveValues\n{}", mappingOutputPath, DebugUtil.debugDumpLazily(hasValues, 2), DebugUtil.debugDumpLazily(shouldHaveValues, 2));
        for (PrismPropertyValue<T> shouldHaveValue : shouldHaveValues) {
            if (!PrismValueCollectionsUtil.containsRealValue(hasValues, shouldHaveValue)) {
                if (targetItemDefinition.isSingleValue()) {
                    targetItemDelta.setValueToReplace(shouldHaveValue.clone());
                } else {
                    targetItemDelta.addValueToAdd(shouldHaveValue.clone());
                }
            }
        }
        if (targetItemDefinition.isSingleValue()) {
            if (!targetItemDelta.isReplace() && shouldHaveValues.isEmpty()) {
                targetItemDelta.setValueToReplace();
            }
        } else {
            for (PrismPropertyValue<T> hasValue : hasValues) {
                if (!PrismValueCollectionsUtil.containsRealValue(shouldHaveValues, hasValue)) {
                    targetItemDelta.addValueToDelete(hasValue.clone());
                }
            }
        }
        if (!targetItemDelta.isEmpty()) {
            LOGGER.trace("Reconciliation delta:\n{}", targetItemDelta.debugDumpLazily(1));
            projCtx.swallowToSecondaryDelta(targetItemDelta);
        }
    }
}
Also used : UniformItemPath(com.evolveum.midpoint.prism.path.UniformItemPath)

Example 2 with UniformItemPath

use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.

the class ProjectionMappingSetEvaluator method evaluateMappingsToTriples.

public <V extends PrismValue, D extends ItemDefinition<?>, T extends ObjectType, F extends FocusType> Map<UniformItemPath, MappingOutputStruct<V>> evaluateMappingsToTriples(MappingEvaluatorParams<V, D, T, F> params, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException {
    String mappingDesc = params.getMappingDesc();
    LensElementContext<T> targetContext = params.getTargetContext();
    PrismObjectDefinition<T> targetObjectDefinition = targetContext.getObjectDefinition();
    ItemPath defaultTargetItemPath = params.getDefaultTargetItemPath();
    Map<UniformItemPath, MappingOutputStruct<V>> outputTripleMap = new HashMap<>();
    XMLGregorianCalendar nextRecomputeTime = null;
    String triggerOriginDescription = null;
    Collection<MappingType> mappingBeans = params.getMappingTypes();
    Collection<MappingImpl<V, D>> mappings = new ArrayList<>(mappingBeans.size());
    for (MappingType mappingBean : mappingBeans) {
        MappingBuilder<V, D> mappingBuilder = mappingFactory.createMappingBuilder(mappingBean, mappingDesc);
        String mappingName = mappingBean.getName();
        if (!mappingBuilder.isApplicableToChannel(params.getContext().getChannel())) {
            LOGGER.trace("Mapping {} not applicable to channel, skipping {}", mappingName, params.getContext().getChannel());
            continue;
        }
        mappingBuilder.now(params.getNow());
        if (defaultTargetItemPath != null && targetObjectDefinition != null) {
            mappingBuilder.defaultTargetDefinition(targetObjectDefinition.findItemDefinition(defaultTargetItemPath));
        } else {
            mappingBuilder.defaultTargetDefinition(params.getTargetItemDefinition());
        }
        mappingBuilder.defaultTargetPath(defaultTargetItemPath);
        mappingBuilder.targetContext(targetObjectDefinition);
        mappingBuilder.sourceContext(params.getSourceContext());
        // Initialize mapping (using Inversion of Control)
        MappingBuilder<V, D> initializedMappingBuilder = params.getInitializer().initialize(mappingBuilder);
        MappingImpl<V, D> mapping = initializedMappingBuilder.build();
        mapping.evaluateTimeValidity(task, result);
        boolean timeConstraintValid = mapping.isTimeConstraintValid();
        if (params.getEvaluateCurrent() == MappingTimeEval.CURRENT && !timeConstraintValid) {
            LOGGER.trace("Mapping {} is non-current, but evaluating current mappings, skipping {}", mappingName, params.getContext().getChannel());
        } else if (params.getEvaluateCurrent() == MappingTimeEval.FUTURE && timeConstraintValid) {
            LOGGER.trace("Mapping {} is current, but evaluating non-current mappings, skipping {}", mappingName, params.getContext().getChannel());
        } else {
            mappings.add(mapping);
        }
    }
    boolean hasFullTargetObject = params.hasFullTargetObject();
    PrismObject<T> aPrioriTargetObject = params.getAPrioriTargetObject();
    LOGGER.trace("Going to process {} mappings for {}", mappings.size(), mappingDesc);
    for (MappingImpl<V, D> mapping : mappings) {
        if (mapping.getStrength() == MappingStrengthType.WEAK) {
            // Evaluate weak mappings in a second run.
            continue;
        }
        UniformItemPath mappingOutputPathUniform = prismContext.toUniformPathKeepNull(mapping.getOutputPath());
        if (params.isFixTarget() && mappingOutputPathUniform != null && defaultTargetItemPath != null && !mappingOutputPathUniform.equivalent(defaultTargetItemPath)) {
            throw new ExpressionEvaluationException("Target cannot be overridden in " + mappingDesc);
        }
        if (params.getAPrioriTargetDelta() != null && mappingOutputPathUniform != null) {
            ItemDelta<?, ?> aPrioriItemDelta = params.getAPrioriTargetDelta().findItemDelta(mappingOutputPathUniform);
            if (mapping.getStrength() != MappingStrengthType.STRONG) {
                if (aPrioriItemDelta != null && !aPrioriItemDelta.isEmpty()) {
                    continue;
                }
            }
        }
        mappingEvaluator.evaluateMapping(mapping, params.getContext(), task, result);
        PrismValueDeltaSetTriple<V> mappingOutputTriple = mapping.getOutputTriple();
        LOGGER.trace("Output triple of mapping {}\n{}", mapping.getContextDescription(), mappingOutputTriple == null ? null : mappingOutputTriple.debugDumpLazily(1));
        if (isMeaningful(mappingOutputTriple)) {
            MappingOutputStruct<V> mappingOutputStruct = outputTripleMap.get(mappingOutputPathUniform);
            if (mappingOutputStruct == null) {
                mappingOutputStruct = new MappingOutputStruct<>();
                outputTripleMap.put(mappingOutputPathUniform, mappingOutputStruct);
            }
            if (mapping.getStrength() == MappingStrengthType.STRONG) {
                mappingOutputStruct.setStrongMappingWasUsed(true);
                if (!hasFullTargetObject && params.getTargetLoader() != null && aPrioriTargetObject != null && aPrioriTargetObject.getOid() != null) {
                    if (!params.getTargetLoader().isLoaded()) {
                        aPrioriTargetObject = params.getTargetLoader().load("strong mapping", task, result);
                        LOGGER.trace("Loaded object because of strong mapping: {}", aPrioriTargetObject);
                        hasFullTargetObject = true;
                    }
                }
            }
            // experimental
            if (mapping.isPushChanges()) {
                mappingOutputStruct.setPushChanges(true);
                // (but it looks like we have to!)
                if (!hasFullTargetObject && params.getTargetLoader() != null && aPrioriTargetObject != null && aPrioriTargetObject.getOid() != null) {
                    if (!params.getTargetLoader().isLoaded()) {
                        aPrioriTargetObject = params.getTargetLoader().load("pushing changes", task, result);
                        LOGGER.trace("Loaded object because of pushing changes: {}", aPrioriTargetObject);
                        hasFullTargetObject = true;
                    }
                }
            }
            PrismValueDeltaSetTriple<V> outputTriple = mappingOutputStruct.getOutputTriple();
            if (outputTriple == null) {
                mappingOutputStruct.setOutputTriple(mappingOutputTriple);
            } else {
                outputTriple.merge(mappingOutputTriple);
            }
        } else {
            LOGGER.trace("Output triple of mapping {} is NOT meaningful", mapping.getContextDescription());
        }
    }
    if (params.isEvaluateWeak()) {
        // Second pass, evaluate only weak mappings
        for (MappingImpl<V, D> mapping : mappings) {
            if (mapping.getStrength() != MappingStrengthType.WEAK) {
                continue;
            }
            UniformItemPath mappingOutputPath = prismContext.toUniformPathKeepNull(mapping.getOutputPath());
            if (params.isFixTarget() && mappingOutputPath != null && defaultTargetItemPath != null && !mappingOutputPath.equivalent(defaultTargetItemPath)) {
                throw new ExpressionEvaluationException("Target cannot be overridden in " + mappingDesc);
            }
            MappingOutputStruct<V> mappingOutputStruct = outputTripleMap.get(mappingOutputPath);
            if (mappingOutputStruct == null) {
                mappingOutputStruct = new MappingOutputStruct<>();
                outputTripleMap.put(mappingOutputPath, mappingOutputStruct);
            }
            PrismValueDeltaSetTriple<V> outputTriple = mappingOutputStruct.getOutputTriple();
            if (outputTriple != null && !outputTriple.getNonNegativeValues().isEmpty()) {
                // MID-3847
                continue;
            }
            Item<V, D> aPrioriTargetItem = null;
            if (aPrioriTargetObject != null && mappingOutputPath != null) {
                aPrioriTargetItem = aPrioriTargetObject.findItem(mappingOutputPath);
            }
            if (hasNoValue(aPrioriTargetItem)) {
                mappingOutputStruct.setWeakMappingWasUsed(true);
                mappingEvaluator.evaluateMapping(mapping, params.getContext(), task, result);
                PrismValueDeltaSetTriple<V> mappingOutputTriple = mapping.getOutputTriple();
                if (mappingOutputTriple != null) {
                    // This is all not right. See MID-3847
                    if (!hasFullTargetObject && params.getTargetLoader() != null && aPrioriTargetObject != null && aPrioriTargetObject.getOid() != null) {
                        if (!params.getTargetLoader().isLoaded()) {
                            aPrioriTargetObject = params.getTargetLoader().load("weak mapping", task, result);
                            LOGGER.trace("Loaded object because of weak mapping: {}", aPrioriTargetObject);
                            hasFullTargetObject = true;
                        }
                    }
                    if (aPrioriTargetObject != null && mappingOutputPath != null) {
                        aPrioriTargetItem = aPrioriTargetObject.findItem(mappingOutputPath);
                    }
                    if (!hasNoValue(aPrioriTargetItem)) {
                        continue;
                    }
                    if (outputTriple == null) {
                        // this is currently always true (see above)
                        mappingOutputStruct.setOutputTriple(mappingOutputTriple);
                    } else {
                        outputTriple.merge(mappingOutputTriple);
                    }
                }
            }
        }
    }
    MappingOutputProcessor<V> processor = params.getProcessor();
    for (Map.Entry<UniformItemPath, MappingOutputStruct<V>> outputTripleMapEntry : outputTripleMap.entrySet()) {
        UniformItemPath mappingOutputPath = outputTripleMapEntry.getKey();
        MappingOutputStruct<V> mappingOutputStruct = outputTripleMapEntry.getValue();
        PrismValueDeltaSetTriple<V> outputTriple = mappingOutputStruct.getOutputTriple();
        boolean defaultProcessing;
        if (processor != null) {
            LOGGER.trace("Executing processor to process mapping evaluation results: {}", processor);
            defaultProcessing = processor.process(mappingOutputPath, mappingOutputStruct);
        } else {
            defaultProcessing = true;
        }
        if (defaultProcessing) {
            if (outputTriple == null) {
                LOGGER.trace("{} expression resulted in null triple for {}, skipping", mappingDesc, targetContext);
                continue;
            }
            ItemDefinition targetItemDefinition;
            if (mappingOutputPath != null) {
                targetItemDefinition = targetObjectDefinition.findItemDefinition(mappingOutputPath);
                if (targetItemDefinition == null) {
                    throw new SchemaException("No definition for item " + mappingOutputPath + " in " + targetObjectDefinition);
                }
            } else {
                targetItemDefinition = params.getTargetItemDefinition();
            }
            // noinspection unchecked
            ItemDelta<V, D> targetItemDelta = targetItemDefinition.createEmptyDelta(mappingOutputPath);
            Item<V, D> aPrioriTargetItem;
            if (aPrioriTargetObject != null) {
                aPrioriTargetItem = aPrioriTargetObject.findItem(mappingOutputPath);
            } else {
                aPrioriTargetItem = null;
            }
            if (targetContext.isAdd()) {
                Collection<V> nonNegativeValues = outputTriple.getNonNegativeValues();
                if (nonNegativeValues.isEmpty()) {
                    LOGGER.trace("{} resulted in null or empty value for {}, skipping", mappingDesc, targetContext);
                    continue;
                }
                targetItemDelta.setValuesToReplace(PrismValueCollectionsUtil.cloneCollection(nonNegativeValues));
            } else {
                // if we have fresh information (full shadow) AND the mapping used to derive the information was strong,
                // we will consider all values (zero & plus sets) -- otherwise, we take only the "plus" (i.e. changed) set
                // the first case is necessary, because in some situations (e.g. when mapping is changed)
                // the evaluator sees no differences w.r.t. real state, even if there is a difference
                // - and we must have a way to push new information onto the resource
                Collection<V> valuesToReplace;
                if (hasFullTargetObject && (mappingOutputStruct.isStrongMappingWasUsed() || mappingOutputStruct.isPushChanges())) {
                    valuesToReplace = outputTriple.getNonNegativeValues();
                } else {
                    valuesToReplace = outputTriple.getPlusSet();
                }
                LOGGER.trace("{}: hasFullTargetObject={}, isStrongMappingWasUsed={}, pushingChange={}, valuesToReplace={}", mappingDesc, hasFullTargetObject, mappingOutputStruct.isStrongMappingWasUsed(), mappingOutputStruct.isPushChanges(), valuesToReplace);
                if (!valuesToReplace.isEmpty()) {
                    if (hasFullTargetObject && targetContext.isFresh() && aPrioriTargetItem != null) {
                        Collection<V> valuesPresent = aPrioriTargetItem.getValues();
                        if (PrismValueCollectionsUtil.equalsRealValues(valuesPresent, valuesToReplace)) {
                            LOGGER.trace("{} resulted in existing values for {}, skipping creation of a delta", mappingDesc, targetContext);
                            continue;
                        }
                    }
                    targetItemDelta.setValuesToReplace(PrismValueCollectionsUtil.cloneCollection(valuesToReplace));
                    applyEstematedOldValueInReplaceCase(targetItemDelta, outputTriple);
                } else if (outputTriple.hasMinusSet()) {
                    LOGGER.trace("{} resulted in null or empty value for {} and there is a minus set, resetting it (replace with empty)", mappingDesc, targetContext);
                    targetItemDelta.setValueToReplace();
                    applyEstematedOldValueInReplaceCase(targetItemDelta, outputTriple);
                } else {
                    LOGGER.trace("{} resulted in null or empty value for {}, skipping", mappingDesc, targetContext);
                }
            }
            if (targetItemDelta.isEmpty()) {
                continue;
            }
            LOGGER.trace("{} adding new delta for {}: {}", mappingDesc, targetContext, targetItemDelta);
            targetContext.swallowToSecondaryDelta(targetItemDelta);
        }
    }
    for (MappingImpl<V, D> mapping : mappings) {
        XMLGregorianCalendar mappingNextRecomputeTime = mapping.getNextRecomputeTime();
        if (mappingNextRecomputeTime != null) {
            if (mapping.isConditionSatisfied() && (nextRecomputeTime == null || nextRecomputeTime.compare(mappingNextRecomputeTime) == DatatypeConstants.GREATER)) {
                nextRecomputeTime = mappingNextRecomputeTime;
                // TODO: maybe better description? But consider storage requirements. We do not want to store too much.
                triggerOriginDescription = mapping.getIdentifier();
            }
        }
    }
    if (nextRecomputeTime != null) {
        NextRecompute nextRecompute = new NextRecompute(nextRecomputeTime, triggerOriginDescription);
        nextRecompute.createTrigger(params.getAPrioriTargetObject(), targetObjectDefinition, targetContext);
    }
    return outputTripleMap;
}
Also used : MappingImpl(com.evolveum.midpoint.model.common.mapping.MappingImpl) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) UniformItemPath(com.evolveum.midpoint.prism.path.UniformItemPath) UniformItemPath(com.evolveum.midpoint.prism.path.UniformItemPath) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 3 with UniformItemPath

use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.

the class TemplateMappingsEvaluation method collectLocalItemDefinitions.

private void collectLocalItemDefinitions(ObjectTemplateType objectTemplate) {
    for (ObjectTemplateItemDefinitionType def : objectTemplate.getItem()) {
        if (def.getRef() == null) {
            throw new IllegalStateException("Item definition with null ref in " + env.contextDescription);
        }
        UniformItemPath itemPath = beans.prismContext.toUniformPath(def.getRef());
        LensUtil.rejectNonTolerantSettingIfPresent(def, itemPath, env.contextDescription);
        // TODO check for incompatible overrides
        itemDefinitionsMap.put(itemPath, def);
    }
}
Also used : UniformItemPath(com.evolveum.midpoint.prism.path.UniformItemPath)

Example 4 with UniformItemPath

use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.

the class NameResolutionHelper method getPathsToResolve.

@NotNull
private List<? extends ItemPath> getPathsToResolve(Collection<SelectorOptions<GetOperationOptions>> options) {
    final UniformItemPath emptyPath = prismContext.emptyPath();
    List<UniformItemPath> rv = new ArrayList<>();
    for (SelectorOptions<GetOperationOptions> option : CollectionUtils.emptyIfNull(options)) {
        if (GetOperationOptions.isResolveNames(option.getOptions())) {
            rv.add(option.getItemPath(emptyPath));
        }
    }
    return rv;
}
Also used : GetOperationOptions(com.evolveum.midpoint.schema.GetOperationOptions) UniformItemPath(com.evolveum.midpoint.prism.path.UniformItemPath) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with UniformItemPath

use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.

the class QAccessCertificationCampaignMapping method isRetrieveAllCases.

private boolean isRetrieveAllCases(SelectorOptions<GetOperationOptions> option) {
    GetOperationOptions getOp = option.getOptions();
    if (getOp == null) {
        return false;
    }
    UniformItemPath path = option.getSelector() != null ? option.getSelector().getPath() : null;
    return RetrieveOption.INCLUDE.equals(getOp.getRetrieve()) && (path == null || path.isEmpty() || F_CASE.equivalent(path));
}
Also used : GetOperationOptions(com.evolveum.midpoint.schema.GetOperationOptions) UniformItemPath(com.evolveum.midpoint.prism.path.UniformItemPath)

Aggregations

UniformItemPath (com.evolveum.midpoint.prism.path.UniformItemPath)18 NotNull (org.jetbrains.annotations.NotNull)5 GetOperationOptions (com.evolveum.midpoint.schema.GetOperationOptions)4 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)2 UserInterfaceElementVisibilityType (com.evolveum.midpoint.xml.ns._public.common.common_3.UserInterfaceElementVisibilityType)2 ArrayList (java.util.ArrayList)2 Attribute (javax.persistence.metamodel.Attribute)2 MappingImpl (com.evolveum.midpoint.model.common.mapping.MappingImpl)1 DefinitionsToTransformable (com.evolveum.midpoint.model.impl.schema.transform.DefinitionsToTransformable)1 ItemName (com.evolveum.midpoint.prism.path.ItemName)1 JaxbName (com.evolveum.midpoint.repo.sql.query.definition.JaxbName)1 JaxbPath (com.evolveum.midpoint.repo.sql.query.definition.JaxbPath)1 JaxbType (com.evolveum.midpoint.repo.sql.query.definition.JaxbType)1 DefinitionProcessingOption (com.evolveum.midpoint.schema.DefinitionProcessingOption)1 GetOperationOptions.createReadOnlyCollection (com.evolveum.midpoint.schema.GetOperationOptions.createReadOnlyCollection)1 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)1 ObjectSecurityConstraints (com.evolveum.midpoint.security.enforcer.api.ObjectSecurityConstraints)1 ItemPathType (com.evolveum.prism.xml.ns._public.types_3.ItemPathType)1 Method (java.lang.reflect.Method)1 HashMap (java.util.HashMap)1