Search in sources :

Example 11 with ItemValueWithOrigin

use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.

the class ConsolidationProcessor method sqeezeAttributesFromConstructionAllToMinus.

private <V extends PrismValue, D extends ItemDefinition, F extends FocusType> void sqeezeAttributesFromConstructionAllToMinus(Map<QName, DeltaSetTriple<ItemValueWithOrigin<V, D>>> squeezedMap, Construction<F> construction, MappingExtractor<V, D, F> extractor) {
    for (PrismValueDeltaSetTripleProducer<V, D> mapping : extractor.getMappings(construction)) {
        PrismValueDeltaSetTriple<V> vcTriple = mapping.getOutputTriple();
        if (vcTriple == null) {
            continue;
        }
        QName name = mapping.getMappingQName();
        DeltaSetTriple<ItemValueWithOrigin<V, D>> squeezeTriple = getSqueezeMapTriple(squeezedMap, name);
        convertSqueezeSet(vcTriple.getZeroSet(), squeezeTriple.getMinusSet(), mapping, construction);
        convertSqueezeSet(vcTriple.getPlusSet(), squeezeTriple.getMinusSet(), mapping, construction);
        convertSqueezeSet(vcTriple.getMinusSet(), squeezeTriple.getMinusSet(), mapping, construction);
    }
}
Also used : ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) QName(javax.xml.namespace.QName)

Example 12 with ItemValueWithOrigin

use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.

the class ConsolidationProcessor method sqeezeAttributesFromConstructionNonminusToMinus.

private <V extends PrismValue, D extends ItemDefinition, F extends FocusType> void sqeezeAttributesFromConstructionNonminusToMinus(Map<QName, DeltaSetTriple<ItemValueWithOrigin<V, D>>> squeezedMap, Construction<F> construction, MappingExtractor<V, D, F> extractor) {
    for (PrismValueDeltaSetTripleProducer<V, D> mapping : extractor.getMappings(construction)) {
        PrismValueDeltaSetTriple<V> vcTriple = mapping.getOutputTriple();
        if (vcTriple == null) {
            continue;
        }
        QName name = mapping.getMappingQName();
        DeltaSetTriple<ItemValueWithOrigin<V, D>> squeezeTriple = getSqueezeMapTriple(squeezedMap, name);
        convertSqueezeSet(vcTriple.getZeroSet(), squeezeTriple.getMinusSet(), mapping, construction);
        convertSqueezeSet(vcTriple.getPlusSet(), squeezeTriple.getMinusSet(), mapping, construction);
    }
}
Also used : ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) QName(javax.xml.namespace.QName)

Example 13 with ItemValueWithOrigin

use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.

the class ObjectTemplateProcessor method computeItemDeltas.

<F extends FocusType, T extends FocusType> Collection<ItemDelta<?, ?>> computeItemDeltas(Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> outputTripleMap, @Nullable Map<ItemPath, ObjectTemplateItemDefinitionType> itemDefinitionsMap, ObjectDelta<T> targetObjectAPrioriDelta, PrismObject<T> targetObject, PrismObjectDefinition<F> focusDefinition, String contextDesc) throws ExpressionEvaluationException, PolicyViolationException, SchemaException {
    Collection<ItemDelta<?, ?>> itemDeltas = new ArrayList<>();
    LOGGER.trace("Computing deltas in {}, focusDelta:\n{}", contextDesc, targetObjectAPrioriDelta);
    boolean addUnchangedValues = false;
    if (targetObjectAPrioriDelta != null && targetObjectAPrioriDelta.isAdd()) {
        addUnchangedValues = true;
    }
    for (Entry<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> entry : outputTripleMap.entrySet()) {
        ItemPath itemPath = entry.getKey();
        DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>> outputTriple = entry.getValue();
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Computed triple for {}:\n{}", itemPath, outputTriple.debugDump());
        }
        final ObjectTemplateItemDefinitionType templateItemDefinition;
        if (itemDefinitionsMap != null) {
            templateItemDefinition = ItemPathUtil.getFromMap(itemDefinitionsMap, itemPath);
        } else {
            templateItemDefinition = null;
        }
        boolean isNonTolerant = templateItemDefinition != null && Boolean.FALSE.equals(templateItemDefinition.isTolerant());
        ItemDelta aprioriItemDelta = getAprioriItemDelta(targetObjectAPrioriDelta, itemPath);
        // if non-tolerant, we want to gather ZERO & PLUS sets
        boolean filterExistingValues = !isNonTolerant;
        ItemDefinition itemDefinition = focusDefinition.findItemDefinition(itemPath);
        ItemDelta itemDelta = LensUtil.consolidateTripleToDelta(itemPath, (DeltaSetTriple) outputTriple, itemDefinition, aprioriItemDelta, targetObject, null, null, addUnchangedValues, filterExistingValues, false, contextDesc, true);
        // Do a quick version of reconciliation. There is not much to reconcile as both the source and the target
        // is focus. But there are few cases to handle, such as strong mappings, and sourceless normal mappings. 
        Collection<? extends ItemValueWithOrigin<?, ?>> zeroSet = outputTriple.getZeroSet();
        Item<PrismValue, ItemDefinition> itemNew = null;
        if (targetObject != null) {
            itemNew = targetObject.findItem(itemPath);
        }
        for (ItemValueWithOrigin<?, ?> zeroSetIvwo : zeroSet) {
            PrismValueDeltaSetTripleProducer<?, ?> mapping = zeroSetIvwo.getMapping();
            if ((mapping.getStrength() == null || mapping.getStrength() == MappingStrengthType.NORMAL)) {
                if (aprioriItemDelta != null && !aprioriItemDelta.isEmpty()) {
                    continue;
                }
                if (!mapping.isSourceless()) {
                    continue;
                }
                LOGGER.trace("Adding zero values from normal mapping {}, a-priori delta: {}, isSourceless: {}", mapping, aprioriItemDelta, mapping.isSourceless());
            } else if (mapping.getStrength() == MappingStrengthType.WEAK) {
                if ((itemNew != null && !itemNew.isEmpty()) || (itemDelta != null && itemDelta.addsAnyValue())) {
                    continue;
                }
                LOGGER.trace("Adding zero values from weak mapping {}, itemNew: {}, itemDelta: {}", mapping, itemNew, itemDelta);
            } else {
                LOGGER.trace("Adding zero values from strong mapping {}", mapping);
            }
            PrismValue valueFromZeroSet = zeroSetIvwo.getItemValue();
            if (itemNew == null || !itemNew.containsRealValue(valueFromZeroSet)) {
                LOGGER.trace("Reconciliation will add value {} for item {}. Existing item: {}", valueFromZeroSet, itemPath, itemNew);
                itemDelta.addValuesToAdd(valueFromZeroSet.clone());
            }
        }
        if (isNonTolerant) {
            if (itemDelta.isDelete()) {
                LOGGER.trace("Non-tolerant item with values to DELETE => removing them");
                // these are useless now - we move everything to REPLACE
                itemDelta.resetValuesToDelete();
            }
            if (itemDelta.isReplace()) {
                LOGGER.trace("Non-tolerant item with resulting REPLACE delta => doing nothing");
            } else {
                for (ItemValueWithOrigin<?, ?> zeroSetIvwo : zeroSet) {
                    itemDelta.addValuesToAdd(zeroSetIvwo.getItemValue().clone());
                }
                itemDelta.addToReplaceDelta();
                LOGGER.trace("Non-tolerant item with resulting ADD delta => converted ADD to REPLACE values: {}", itemDelta.getValuesToReplace());
            }
            // under a special option "createReplaceDelta", but for the time being, let's keep it here
            if (itemDelta instanceof PropertyDelta) {
                PropertyDelta propertyDelta = ((PropertyDelta) itemDelta);
                QName matchingRuleName = templateItemDefinition != null ? templateItemDefinition.getMatchingRule() : null;
                MatchingRule matchingRule = matchingRuleRegistry.getMatchingRule(matchingRuleName, null);
                if (propertyDelta.isRedundant(targetObject, matchingRule)) {
                    LOGGER.trace("Computed property delta is redundant => skipping it. Delta = \n{}", propertyDelta.debugDump());
                    continue;
                }
            } else {
                if (itemDelta.isRedundant(targetObject)) {
                    LOGGER.trace("Computed item delta is redundant => skipping it. Delta = \n{}", itemDelta.debugDump());
                    continue;
                }
            }
            PrismUtil.setDeltaOldValue(targetObject, itemDelta);
        }
        itemDelta.simplify();
        itemDelta.validate(contextDesc);
        itemDeltas.add(itemDelta);
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Computed delta:\n{}", itemDelta.debugDump());
        }
    }
    return itemDeltas;
}
Also used : DeltaSetTriple(com.evolveum.midpoint.prism.delta.DeltaSetTriple) QName(javax.xml.namespace.QName) ArrayList(java.util.ArrayList) ItemDefinition(com.evolveum.midpoint.prism.ItemDefinition) ObjectTemplateItemDefinitionType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectTemplateItemDefinitionType) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) PrismValue(com.evolveum.midpoint.prism.PrismValue) ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) MatchingRule(com.evolveum.midpoint.prism.match.MatchingRule) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 14 with ItemValueWithOrigin

use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.

the class ReconciliationProcessor method reconcileProjectionAssociations.

private void reconcileProjectionAssociations(LensProjectionContext projCtx, Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations, RefinedObjectClassDefinition accountDefinition, Task task, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException {
    PrismObject<ShadowType> shadowNew = projCtx.getObjectNew();
    PrismContainer associationsContainer = shadowNew.findContainer(ShadowType.F_ASSOCIATION);
    Collection<QName> associationNames = squeezedAssociations != null ? MiscUtil.union(squeezedAssociations.keySet(), accountDefinition.getNamesOfAssociations()) : accountDefinition.getNamesOfAssociations();
    for (QName assocName : associationNames) {
        LOGGER.trace("Association reconciliation processing association {}", assocName);
        RefinedAssociationDefinition associationDefinition = accountDefinition.findAssociationDefinition(assocName);
        if (associationDefinition == null) {
            throw new SchemaException("No definition for association " + assocName + " in " + projCtx.getResourceShadowDiscriminator());
        }
        DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> cvwoTriple = squeezedAssociations != null ? squeezedAssociations.get(assocName) : null;
        // note: actually isIgnored is not implemented yet
        if (associationDefinition.isIgnored()) {
            LOGGER.trace("Skipping reconciliation of association {} because it is ignored", assocName);
            continue;
        }
        // TODO implement limitations
        //            PropertyLimitations limitations = associationDefinition.getLimitations(LayerType.MODEL);
        //            if (limitations != null) {
        //                PropertyAccessType access = limitations.getAccess();
        //                if (access != null) {
        //                    if (projCtx.isAdd() && (access.isAdd() == null || !access.isAdd())) {
        //                        LOGGER.trace("Skipping reconciliation of attribute {} because it is non-createable",
        //                                attrName);
        //                        continue;
        //                    }
        //                    if (projCtx.isModify() && (access.isModify() == null || !access.isModify())) {
        //                        LOGGER.trace("Skipping reconciliation of attribute {} because it is non-updateable",
        //                                attrName);
        //                        continue;
        //                    }
        //                }
        //            }
        Collection<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> shouldBeCValues;
        if (cvwoTriple == null) {
            shouldBeCValues = new HashSet<>();
        } else {
            shouldBeCValues = new HashSet<>(cvwoTriple.getNonNegativeValues());
        }
        // TODO what about equality checks? There will be probably duplicates there.
        // We consider values explicitly requested by user to be among "should be values".
        addContainerValuesFromDelta(shouldBeCValues, projCtx.getPrimaryDelta(), assocName);
        // But we DO NOT take values from sync delta (because they just reflect what's on the resource),
        // nor from secondary delta (because these got there from mappings).
        // values in shouldBeCValues are parent-less
        // to be able to make Containerable out of them, we provide them a (fake) parent
        // (and we clone them not to mess anything)
        PrismContainer<ShadowAssociationType> fakeParent = prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(ShadowAssociationType.class).instantiate();
        for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> cvwo : shouldBeCValues) {
            PrismContainerValue<ShadowAssociationType> cvalue = cvwo.getItemValue().clone();
            cvalue.setParent(fakeParent);
            cvwo.setItemValue(cvalue);
        }
        boolean hasStrongShouldBeCValue = false;
        for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCValue : shouldBeCValues) {
            if (shouldBeCValue.getMapping() != null && shouldBeCValue.getMapping().getStrength() == MappingStrengthType.STRONG) {
                hasStrongShouldBeCValue = true;
                break;
            }
        }
        Collection<PrismContainerValue<ShadowAssociationType>> areCValues = new HashSet<>();
        if (associationsContainer != null) {
            for (Object o : associationsContainer.getValues()) {
                PrismContainerValue<ShadowAssociationType> existingAssocValue = (PrismContainerValue<ShadowAssociationType>) o;
                if (existingAssocValue.getValue().getName().equals(assocName)) {
                    areCValues.add(existingAssocValue);
                }
            }
        } else {
            areCValues = new HashSet<>();
        }
        // todo comment this logging code out eventually
        //			if (LOGGER.isTraceEnabled()) {
        //				StringBuilder sb = new StringBuilder();
        //				sb.append("Reconciliation\nASSOCIATION: ").append(PrettyPrinter.prettyPrint(assocName));
        //				sb.append("\n  Should be:");
        //				for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>,PrismContainerDefinition<ShadowAssociationType>> shouldBeCValue : shouldBeCValues) {
        //					sb.append("\n    ");
        //					sb.append(shouldBeCValue.getItemValue());
        //					PrismValueDeltaSetTripleProducer<?,?> shouldBeMapping = shouldBeCValue.getMapping();
        //					if (shouldBeMapping != null && shouldBeMapping.getStrength() == MappingStrengthType.STRONG) {
        //						sb.append(" STRONG");
        //					}
        //					if (shouldBeMapping != null && shouldBeMapping.getStrength() == MappingStrengthType.WEAK) {
        //						sb.append(" WEAK");
        //					}
        //					if (!shouldBeCValue.isValid()) {
        //						sb.append(" INVALID");
        //					}
        //				}
        //				sb.append("\n  Is:");
        //				for (PrismContainerValue<ShadowAssociationType> isCVal : areCValues) {
        //					sb.append("\n    ");
        //					sb.append(isCVal);
        //				}
        //				LOGGER.trace("{}", sb.toString());
        //			}
        ValueMatcher associationValueMatcher = new ValueMatcher(null) {

            // todo is this correct? [med]
            @Override
            public boolean match(Object realA, Object realB) {
                checkType(realA);
                checkType(realB);
                if (realA == null) {
                    return realB == null;
                } else if (realB == null) {
                    return false;
                } else {
                    ShadowAssociationType a = (ShadowAssociationType) realA;
                    ShadowAssociationType b = (ShadowAssociationType) realB;
                    checkName(a);
                    checkName(b);
                    if (!a.getName().equals(b.getName())) {
                        return false;
                    }
                    if (a.getShadowRef() != null && a.getShadowRef().getOid() != null && b.getShadowRef() != null && b.getShadowRef().getOid() != null) {
                        return a.getShadowRef().getOid().equals(b.getShadowRef().getOid());
                    }
                    LOGGER.warn("Comparing association values without shadowRefs: {} and {}", a, b);
                    return false;
                }
            }

            private void checkName(ShadowAssociationType s) {
                if (s.getName() == null) {
                    throw new IllegalStateException("No name for association " + s);
                }
            }

            @Override
            public boolean matches(Object realValue, String regex) {
                throw new UnsupportedOperationException();
            }

            @Override
            public boolean hasRealValue(PrismProperty property, PrismPropertyValue pValue) {
                throw new UnsupportedOperationException();
            }

            @Override
            public boolean isRealValueToAdd(PropertyDelta delta, PrismPropertyValue pValue) {
                throw new UnsupportedOperationException();
            }

            private void checkType(Object o) {
                if (o != null && !(o instanceof ShadowAssociationType)) {
                    throw new IllegalStateException("Object is not a ShadowAssociationType, it is " + o.getClass() + " instead");
                }
            }
        };
        for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCvwo : shouldBeCValues) {
            PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBeCvwo.getMapping();
            if (shouldBeMapping == null) {
                continue;
            }
            if (shouldBeMapping.getStrength() != MappingStrengthType.STRONG && (!areCValues.isEmpty() || hasStrongShouldBeCValue)) {
                // changed directly on the projection resource object
                continue;
            }
            ShadowAssociationType shouldBeRealValue = shouldBeCvwo.getItemValue().getValue();
            if (shouldBeCvwo.isValid() && !isInAssociationValues(associationValueMatcher, shouldBeRealValue, areCValues)) {
                recordAssociationDelta(associationValueMatcher, projCtx, associationDefinition, ModificationType.ADD, shouldBeRealValue, shouldBeCvwo.getSource(), "it is given by a mapping");
            }
        }
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Before decideIfTolerateAssociation:");
            LOGGER.trace("areCValues:\n{}", DebugUtil.debugDump(areCValues));
            LOGGER.trace("shouldBeCValues:\n{}", DebugUtil.debugDump(shouldBeCValues));
        }
        decideIfTolerateAssociation(projCtx, associationDefinition, areCValues, shouldBeCValues, associationValueMatcher, task, result);
    }
}
Also used : RefinedAssociationDefinition(com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) ShadowAssociationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType) HashSet(java.util.HashSet) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) QName(javax.xml.namespace.QName) ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin)

Aggregations

ItemValueWithOrigin (com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin)14 QName (javax.xml.namespace.QName)9 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)8 DeltaSetTriple (com.evolveum.midpoint.prism.delta.DeltaSetTriple)7 ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)4 PrismValueDeltaSetTriple (com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple)4 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)4 XMLGregorianCalendar (javax.xml.datatype.XMLGregorianCalendar)4 LensProjectionContext (com.evolveum.midpoint.model.impl.lens.LensProjectionContext)3 PropertyDelta (com.evolveum.midpoint.prism.delta.PropertyDelta)3 ResourceShadowDiscriminator (com.evolveum.midpoint.schema.ResourceShadowDiscriminator)3 SynchronizationPolicyDecision (com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision)2 Mapping (com.evolveum.midpoint.model.common.mapping.Mapping)2 Construction (com.evolveum.midpoint.model.impl.lens.Construction)2 LensContext (com.evolveum.midpoint.model.impl.lens.LensContext)2 LensUtil (com.evolveum.midpoint.model.impl.lens.LensUtil)2 ItemDefinition (com.evolveum.midpoint.prism.ItemDefinition)2 PrismValue (com.evolveum.midpoint.prism.PrismValue)2 ShadowAssociationType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType)2 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)2