Search in sources :

Example 66 with PropertyDelta

use of com.evolveum.midpoint.prism.delta.PropertyDelta in project midpoint by Evolveum.

the class ResourceObjectConverter method checkSimulatedActivationLockoutStatus.

private void checkSimulatedActivationLockoutStatus(ProvisioningContext ctx, Collection<? extends ItemDelta> objectChange, LockoutStatusType status, ActivationCapabilityType activationCapability, ShadowType shadow, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
    ActivationLockoutStatusCapabilityType capActStatus = getActivationLockoutStatusFromSimulatedActivation(ctx, activationCapability, shadow, result);
    ResourceAttribute<?> activationAttribute = getSimulatedActivationLockoutStatusAttribute(ctx, shadow, capActStatus, result);
    if (activationAttribute == null) {
        return;
    }
    PropertyDelta simulatedActivationDelta = PropertyDelta.findPropertyDelta(objectChange, activationAttribute.getPath());
    PrismProperty simulatedActivationProperty = simulatedActivationDelta.getPropertyNewMatchingPath();
    Collection realValues = simulatedActivationProperty.getRealValues();
    if (realValues.isEmpty()) {
        //nothing to do, no value for simulatedActivation
        return;
    }
    if (realValues.size() > 1) {
        throw new SchemaException("Found more than one value for simulated lockout.");
    }
    Object simulatedActivationValue = realValues.iterator().next();
    // TODO this is strange; evaluating lockout but looking at status! [med]
    boolean transformedValue = getTransformedValue(ctx, activationCapability, shadow, simulatedActivationValue, result);
    if (transformedValue && status == LockoutStatusType.NORMAL) {
    //this is ok, simulated value and also value for native capability resulted to the same vale
    } else {
        throw new SchemaException("Found conflicting change for activation lockout. Simulated lockout resulted to " + transformedValue + ", but native activation resulted to " + status);
    }
}
Also used : ActivationLockoutStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationLockoutStatusCapabilityType) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta)

Example 67 with PropertyDelta

use of com.evolveum.midpoint.prism.delta.PropertyDelta in project midpoint by Evolveum.

the class ResourceObjectConverter method modifyResourceObject.

public AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>> modifyResourceObject(ProvisioningContext ctx, PrismObject<ShadowType> repoShadow, OperationProvisioningScriptsType scripts, Collection<? extends ItemDelta> itemDeltas, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
    OperationResult result = parentResult.createSubresult(OPERATION_MODIFY_RESOURCE_OBJECT);
    try {
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Modifying resource object {}, deltas:\n", repoShadow, DebugUtil.debugDump(itemDeltas, 1));
        }
        RefinedObjectClassDefinition objectClassDefinition = ctx.getObjectClassDefinition();
        Collection<Operation> operations = new ArrayList<Operation>();
        Collection<? extends ResourceAttribute<?>> identifiers = ShadowUtil.getAllIdentifiers(repoShadow);
        Collection<? extends ResourceAttribute<?>> primaryIdentifiers = ShadowUtil.getPrimaryIdentifiers(repoShadow);
        if (ProvisioningUtil.isProtectedShadow(ctx.getObjectClassDefinition(), repoShadow, matchingRuleRegistry)) {
            if (hasChangesOnResource(itemDeltas)) {
                LOGGER.error("Attempt to modify protected resource object " + objectClassDefinition + ": " + identifiers);
                SecurityViolationException e = new SecurityViolationException("Cannot modify protected resource object " + objectClassDefinition + ": " + identifiers);
                result.recordFatalError(e);
                throw e;
            } else {
                // Return immediately. This structure of the code makes sure that we do not execute any
                // resource operation for protected account even if there is a bug in the code below.
                LOGGER.trace("No resource modifications for protected resource object {}: {}; skipping", objectClassDefinition, identifiers);
                result.recordNotApplicableIfUnknown();
                return AsynchronousOperationReturnValue.wrap(null, result);
            }
        }
        boolean hasVolatilityTriggerModification = false;
        boolean hasResourceModification = false;
        for (ItemDelta modification : itemDeltas) {
            ItemPath path = modification.getPath();
            QName firstPathName = ItemPath.getFirstName(path);
            if (QNameUtil.match(firstPathName, ShadowType.F_ATTRIBUTES)) {
                hasResourceModification = true;
                QName attrName = ItemPath.getFirstName(path.rest());
                RefinedAttributeDefinition<Object> attrDef = ctx.getObjectClassDefinition().findAttributeDefinition(attrName);
                if (attrDef.isVolatilityTrigger()) {
                    LOGGER.trace("Will pre-read and re-read object because volatility trigger attribute {} has changed", attrName);
                    hasVolatilityTriggerModification = true;
                    break;
                }
            } else if (QNameUtil.match(firstPathName, ShadowType.F_ACTIVATION) || QNameUtil.match(firstPathName, ShadowType.F_CREDENTIALS) || QNameUtil.match(firstPathName, ShadowType.F_ASSOCIATION) || QNameUtil.match(firstPathName, ShadowType.F_AUXILIARY_OBJECT_CLASS)) {
                hasResourceModification = true;
            }
        }
        if (!hasResourceModification) {
            // Quit early, so we avoid potential pre-read and other processing when there is no point of doing so.
            // Also the read may fail which may invoke consistency mechanism which will complicate the situation.
            LOGGER.trace("No resource modification found for {}, skipping", identifiers);
            result.recordNotApplicableIfUnknown();
            return AsynchronousOperationReturnValue.wrap(null, result);
        }
        /*
	         *  State of the shadow before execution of the deltas - e.g. with original attributes, as it may be recorded in such a way in
	         *  groups of which this account is a member of. (In case of object->subject associations.)
	         *
	         *  This is used when the resource does NOT provide referential integrity by itself. This is e.g. the case of OpenDJ with default
	         *  settings.
	         *
	         *  On the contrary, AD and OpenDJ with referential integrity plugin do provide automatic referential integrity, so this feature is
	         *  not needed.
	         *
	         *  We decide based on setting of explicitReferentialIntegrity in association definition.
	         */
        collectAttributeAndEntitlementChanges(ctx, itemDeltas, operations, repoShadow, result);
        PrismObject<ShadowType> preReadShadow = null;
        Collection<PropertyModificationOperation> sideEffectOperations = null;
        //check identifier if it is not null
        if (primaryIdentifiers.isEmpty() && repoShadow.asObjectable().getFailedOperationType() != null) {
            GenericConnectorException e = new GenericConnectorException("Unable to modify object in the resource. Probably it has not been created yet because of previous unavailability of the resource.");
            result.recordFatalError(e);
            throw e;
        }
        if (hasVolatilityTriggerModification || ResourceTypeUtil.isAvoidDuplicateValues(ctx.getResource()) || isRename(ctx, operations)) {
            // We need to filter out the deltas that add duplicate values or remove values that are not there
            LOGGER.trace("Pre-reading resource shadow");
            // yes, we need associations here
            preReadShadow = preReadShadow(ctx, identifiers, operations, true, result);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Pre-read object:\n{}", preReadShadow.debugDump());
            }
        }
        if (!operations.isEmpty()) {
            // This must go after the skip check above. Otherwise the scripts would be executed even if there is no need to.
            addExecuteScriptOperation(operations, ProvisioningOperationTypeType.MODIFY, scripts, ctx.getResource(), result);
            // Execute primary ICF operation on this shadow
            sideEffectOperations = executeModify(ctx, preReadShadow, identifiers, operations, result);
        } else {
            // We have to check BEFORE we add script operations, otherwise the check would be pointless
            LOGGER.trace("No modifications for connector object specified. Skipping processing of subject executeModify.");
        }
        Collection<PropertyDelta<PrismPropertyValue>> sideEffectDeltas = convertToPropertyDelta(sideEffectOperations);
        /*
	         *  State of the shadow after execution of the deltas - e.g. with new DN (if it was part of the delta), because this one should be recorded
	         *  in groups of which this account is a member of. (In case of object->subject associations.)
	         */
        PrismObject<ShadowType> shadowAfter = preReadShadow == null ? repoShadow.clone() : preReadShadow.clone();
        for (ItemDelta itemDelta : itemDeltas) {
            itemDelta.applyTo(shadowAfter);
        }
        PrismObject<ShadowType> postReadShadow = null;
        if (hasVolatilityTriggerModification) {
            // There may be other changes that were not detected by the connector. Re-read the object and compare.
            LOGGER.trace("Post-reading resource shadow");
            postReadShadow = preReadShadow(ctx, identifiers, operations, true, result);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Post-read object:\n{}", postReadShadow.debugDump());
            }
            ObjectDelta<ShadowType> resourceShadowDelta = preReadShadow.diff(postReadShadow);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Determined side-effect changes by old-new diff:\n{}", resourceShadowDelta.debugDump());
            }
            for (ItemDelta modification : resourceShadowDelta.getModifications()) {
                if (modification.getParentPath().startsWithName(ShadowType.F_ATTRIBUTES) && !ItemDelta.hasEquivalent(itemDeltas, modification)) {
                    ItemDelta.merge(sideEffectDeltas, modification);
                }
            }
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Side-effect changes after merging with old-new diff:\n{}", DebugUtil.debugDump(sideEffectDeltas));
            }
        }
        Collection<? extends ItemDelta> allDeltas = new ArrayList<>();
        ((Collection) allDeltas).addAll(itemDeltas);
        ((Collection) allDeltas).addAll(sideEffectDeltas);
        // Execute entitlement modification on other objects (if needed)
        shadowAfter = executeEntitlementChangesModify(ctx, preReadShadow == null ? repoShadow : preReadShadow, postReadShadow == null ? shadowAfter : postReadShadow, scripts, allDeltas, result);
        if (!sideEffectDeltas.isEmpty()) {
            if (preReadShadow != null) {
                PrismUtil.setDeltaOldValue(preReadShadow, sideEffectDeltas);
            } else {
                PrismUtil.setDeltaOldValue(repoShadow, sideEffectDeltas);
            }
        }
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Modificaiton side-effect changes:\n{}", DebugUtil.debugDump(sideEffectDeltas));
        }
        LOGGER.trace("Modified resource object {}", repoShadow);
        computeResultStatus(result);
        return AsynchronousOperationReturnValue.wrap(sideEffectDeltas, result);
    } catch (Throwable e) {
        result.recordFatalError(e);
        throw e;
    }
}
Also used : QName(javax.xml.namespace.QName) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) AsynchronousOperationResult(com.evolveum.midpoint.schema.result.AsynchronousOperationResult) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 68 with PropertyDelta

use of com.evolveum.midpoint.prism.delta.PropertyDelta in project midpoint by Evolveum.

the class ResourceObjectConverter method convertToReplace.

private PropertyModificationOperation convertToReplace(PropertyDelta<?> propertyDelta, PrismObject<ShadowType> currentShadow, QName matchingRuleQName) throws SchemaException {
    if (propertyDelta.isReplace()) {
        // this was probably checked before
        throw new IllegalStateException("PropertyDelta is both ADD/DELETE and REPLACE");
    }
    // let's extract (parent-less) current values
    PrismProperty<?> currentProperty = currentShadow.findProperty(propertyDelta.getPath());
    Collection<PrismPropertyValue> currentValues = new ArrayList<>();
    if (currentProperty != null) {
        for (PrismPropertyValue currentValue : currentProperty.getValues()) {
            currentValues.add(currentValue.clone());
        }
    }
    final MatchingRule matchingRule;
    if (matchingRuleQName != null) {
        ItemDefinition def = propertyDelta.getDefinition();
        QName typeName;
        if (def != null) {
            typeName = def.getTypeName();
        } else {
            // we'll skip testing rule fitness w.r.t type
            typeName = null;
        }
        matchingRule = matchingRuleRegistry.getMatchingRule(matchingRuleQName, typeName);
    } else {
        matchingRule = null;
    }
    Comparator comparator = new Comparator<PrismPropertyValue<?>>() {

        @Override
        public int compare(PrismPropertyValue<?> o1, PrismPropertyValue<?> o2) {
            if (o1.equalsComplex(o2, true, false, matchingRule)) {
                return 0;
            } else {
                return 1;
            }
        }
    };
    // add values that have to be added
    if (propertyDelta.isAdd()) {
        for (PrismPropertyValue valueToAdd : propertyDelta.getValuesToAdd()) {
            if (!PrismPropertyValue.containsValue(currentValues, valueToAdd, comparator)) {
                currentValues.add(valueToAdd.clone());
            } else {
                LOGGER.warn("Attempting to add a value of {} that is already present in {}: {}", valueToAdd, propertyDelta.getElementName(), currentValues);
            }
        }
    }
    // remove values that should not be there
    if (propertyDelta.isDelete()) {
        for (PrismPropertyValue valueToDelete : propertyDelta.getValuesToDelete()) {
            Iterator<PrismPropertyValue> iterator = currentValues.iterator();
            boolean found = false;
            while (iterator.hasNext()) {
                PrismPropertyValue pValue = iterator.next();
                LOGGER.trace("Comparing existing {} to about-to-be-deleted {}, matching rule: {}", pValue, valueToDelete, matchingRule);
                if (comparator.compare(pValue, valueToDelete) == 0) {
                    LOGGER.trace("MATCH! compared existing {} to about-to-be-deleted {}", pValue, valueToDelete);
                    iterator.remove();
                    found = true;
                }
            }
            if (!found) {
                LOGGER.warn("Attempting to remove a value of {} that is not in {}: {}", valueToDelete, propertyDelta.getElementName(), currentValues);
            }
        }
    }
    PropertyDelta resultingDelta = new PropertyDelta(propertyDelta.getPath(), propertyDelta.getPropertyDefinition(), propertyDelta.getPrismContext());
    resultingDelta.setValuesToReplace(currentValues);
    return new PropertyModificationOperation(resultingDelta);
}
Also used : QName(javax.xml.namespace.QName) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) MatchingRule(com.evolveum.midpoint.prism.match.MatchingRule)

Example 69 with PropertyDelta

use of com.evolveum.midpoint.prism.delta.PropertyDelta in project midpoint by Evolveum.

the class ConsolidationProcessor method consolidateValuesToModifyDelta.

private <F extends FocusType> ObjectDelta<ShadowType> consolidateValuesToModifyDelta(LensContext<F> context, LensProjectionContext projCtx, boolean addUnchangedValues, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException {
    // "Squeeze" all the relevant mappings into a data structure that we can process conveniently. We want to have all the
    // (meta)data about relevant for a specific attribute in one data structure, not spread over several account constructions.
    Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes = sqeeze(projCtx, construction -> (Collection) construction.getAttributeMappings());
    projCtx.setSqueezedAttributes(squeezedAttributes);
    Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations = sqeeze(projCtx, construction -> construction.getAssociationMappings());
    projCtx.setSqueezedAssociations(squeezedAssociations);
    // So, we do it here - once and for all.
    if (!squeezedAssociations.isEmpty()) {
        fillInAssociationNames(squeezedAssociations);
    }
    MappingExtractor<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>, F> auxiliaryObjectClassExtractor = construction -> {
        PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> prod = new PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>() {

            @Override
            public QName getMappingQName() {
                return ShadowType.F_AUXILIARY_OBJECT_CLASS;
            }

            @Override
            public PrismValueDeltaSetTriple<PrismPropertyValue<QName>> getOutputTriple() {
                PrismValueDeltaSetTriple<PrismPropertyValue<QName>> triple = new PrismValueDeltaSetTriple<>();
                if (construction.getAuxiliaryObjectClassDefinitions() != null) {
                    for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : construction.getAuxiliaryObjectClassDefinitions()) {
                        triple.addToZeroSet(new PrismPropertyValue<QName>(auxiliaryObjectClassDefinition.getTypeName()));
                    }
                }
                return triple;
            }

            @Override
            public MappingStrengthType getStrength() {
                return MappingStrengthType.STRONG;
            }

            @Override
            public PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> clone() {
                return this;
            }

            @Override
            public boolean isExclusive() {
                return false;
            }

            @Override
            public boolean isAuthoritative() {
                return true;
            }

            @Override
            public boolean isSourceless() {
                return false;
            }
        };
        Collection<PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>> col = new ArrayList<>(1);
        col.add(prod);
        return col;
    };
    Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>>> squeezedAuxiliaryObjectClasses = sqeeze(projCtx, auxiliaryObjectClassExtractor);
    projCtx.setSqueezedAuxiliaryObjectClasses(squeezedAuxiliaryObjectClasses);
    ResourceShadowDiscriminator discr = projCtx.getResourceShadowDiscriminator();
    ObjectDelta<ShadowType> objectDelta = new ObjectDelta<ShadowType>(ShadowType.class, ChangeType.MODIFY, prismContext);
    objectDelta.setOid(projCtx.getOid());
    // Let's be very very lazy about fetching the account from the resource.
    if (!projCtx.hasFullShadow() && (hasActiveWeakMapping(squeezedAttributes, projCtx) || hasActiveWeakMapping(squeezedAssociations, projCtx) || (hasActiveStrongMapping(squeezedAttributes, projCtx) || hasActiveStrongMapping(squeezedAssociations, projCtx)))) {
        // Full account was not yet loaded. This will cause problems as
        // the weak mapping may be applied even though it should not be
        // applied
        // and also same changes may be discarded because of unavailability
        // of all
        // account's attributes.Therefore load the account now, but with
        // doNotDiscovery options..
        // We also need to get account if there are strong mappings. Strong mappings
        // should always be applied. So reading the account now will indirectly
        // trigger reconciliation which makes sure that the strong mappings are
        // applied.
        // By getting accounts from provisioning, there might be a problem with
        // resource availability. We need to know, if the account was read full
        // or we have only the shadow from the repository. If we have only
        // shadow, the weak mappings may applied even if they should not be. 
        contextLoader.loadFullShadow(context, projCtx, "weak or strong mapping", task, result);
        if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
            return null;
        }
    }
    boolean completeAccount = projCtx.hasFullShadow();
    ObjectDelta<ShadowType> existingDelta = projCtx.getDelta();
    // AUXILIARY OBJECT CLASSES
    ItemPath auxiliaryObjectClassItemPath = new ItemPath(ShadowType.F_AUXILIARY_OBJECT_CLASS);
    PrismPropertyDefinition<QName> auxiliaryObjectClassPropertyDef = projCtx.getObjectDefinition().findPropertyDefinition(auxiliaryObjectClassItemPath);
    PropertyDelta<QName> auxiliaryObjectClassAPrioriDelta = null;
    RefinedResourceSchema refinedSchema = projCtx.getRefinedResourceSchema();
    List<QName> auxOcNames = new ArrayList<>();
    List<RefinedObjectClassDefinition> auxOcDefs = new ArrayList<>();
    ObjectDelta<ShadowType> projDelta = projCtx.getDelta();
    if (projDelta != null) {
        auxiliaryObjectClassAPrioriDelta = projDelta.findPropertyDelta(auxiliaryObjectClassItemPath);
    }
    for (Entry<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>>> entry : squeezedAuxiliaryObjectClasses.entrySet()) {
        DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>> ivwoTriple = entry.getValue();
        LOGGER.trace("CONSOLIDATE auxiliary object classes ({})", new Object[] { discr });
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Auxiliary object class triple:\n{}", ivwoTriple.debugDump());
        }
        for (ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> ivwo : ivwoTriple.getAllValues()) {
            QName auxObjectClassName = ivwo.getItemValue().getValue();
            if (auxOcNames.contains(auxObjectClassName)) {
                continue;
            }
            auxOcNames.add(auxObjectClassName);
            RefinedObjectClassDefinition auxOcDef = refinedSchema.getRefinedDefinition(auxObjectClassName);
            if (auxOcDef == null) {
                LOGGER.error("Auxiliary object class definition {} for {} not found in the schema, but it should be there, dumping context:\n{}", auxObjectClassName, discr, context.debugDump());
                throw new IllegalStateException("Auxiliary object class definition " + auxObjectClassName + " for " + discr + " not found in the context, but it should be there");
            }
            auxOcDefs.add(auxOcDef);
        }
        ItemDelta<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> itemDelta = LensUtil.consolidateTripleToDelta(auxiliaryObjectClassItemPath, ivwoTriple, auxiliaryObjectClassPropertyDef, auxiliaryObjectClassAPrioriDelta, projCtx.getObjectNew(), null, null, addUnchangedValues, completeAccount, false, discr.toHumanReadableDescription(), false);
        PropertyDelta<QName> propDelta = (PropertyDelta) itemDelta;
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Auxiliary object class delta:\n{}", propDelta.debugDump());
        }
        if (!propDelta.isEmpty()) {
            objectDelta.addModification(propDelta);
        }
    }
    RefinedObjectClassDefinition structuralObjectClassDefinition = projCtx.getStructuralObjectClassDefinition();
    if (structuralObjectClassDefinition == null) {
        LOGGER.error("Structural object class definition for {} not found in the context, but it should be there, dumping context:\n{}", discr, context.debugDump());
        throw new IllegalStateException("Structural object class definition for " + discr + " not found in the context, but it should be there");
    }
    RefinedObjectClassDefinition rOcDef = new CompositeRefinedObjectClassDefinitionImpl(structuralObjectClassDefinition, auxOcDefs);
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("Object class definition for {} consolidation:\n{}", discr, rOcDef.debugDump());
    }
    // with the data in ItemValueWithOrigin triples.
    for (Map.Entry<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> entry : squeezedAttributes.entrySet()) {
        QName attributeName = entry.getKey();
        DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>> triple = entry.getValue();
        PropertyDelta<?> propDelta = consolidateAttribute(rOcDef, discr, existingDelta, projCtx, addUnchangedValues, completeAccount, attributeName, (DeltaSetTriple) triple);
        if (propDelta != null) {
            objectDelta.addModification(propDelta);
        }
    }
    // ASSOCIATIONS
    for (Entry<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> entry : squeezedAssociations.entrySet()) {
        QName associationName = entry.getKey();
        DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> triple = entry.getValue();
        ContainerDelta<ShadowAssociationType> containerDelta = consolidateAssociation(rOcDef, discr, existingDelta, projCtx, addUnchangedValues, completeAccount, associationName, triple);
        if (containerDelta != null) {
            objectDelta.addModification(containerDelta);
        }
    }
    return objectDelta;
}
Also used : PrismValue(com.evolveum.midpoint.prism.PrismValue) Construction(com.evolveum.midpoint.model.impl.lens.Construction) ChangeType(com.evolveum.midpoint.prism.delta.ChangeType) ConfigurationException(com.evolveum.midpoint.util.exception.ConfigurationException) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) Autowired(org.springframework.beans.factory.annotation.Autowired) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue) com.evolveum.midpoint.common.refinery(com.evolveum.midpoint.common.refinery) LensContext(com.evolveum.midpoint.model.impl.lens.LensContext) PrismValueDeltaSetTriple(com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple) Map(java.util.Map) PrismValueDeltaSetTripleProducer(com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) PrismProperty(com.evolveum.midpoint.prism.PrismProperty) Mapping(com.evolveum.midpoint.model.common.mapping.Mapping) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) InternalsConfig.consistencyChecks(com.evolveum.midpoint.schema.internals.InternalsConfig.consistencyChecks) Collection(java.util.Collection) Task(com.evolveum.midpoint.task.api.Task) MatchingRuleRegistry(com.evolveum.midpoint.prism.match.MatchingRuleRegistry) ObjectUtils(org.apache.commons.lang.ObjectUtils) ResourceShadowDiscriminator(com.evolveum.midpoint.schema.ResourceShadowDiscriminator) List(java.util.List) FocusType(com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType) Entry(java.util.Map.Entry) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) CommunicationException(com.evolveum.midpoint.util.exception.CommunicationException) QName(javax.xml.namespace.QName) MappingStrengthType(com.evolveum.midpoint.xml.ns._public.common.common_3.MappingStrengthType) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) PolicyViolationException(com.evolveum.midpoint.util.exception.PolicyViolationException) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) ItemDefinition(com.evolveum.midpoint.prism.ItemDefinition) Trace(com.evolveum.midpoint.util.logging.Trace) HashMap(java.util.HashMap) ExpressionEvaluationException(com.evolveum.midpoint.util.exception.ExpressionEvaluationException) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) ArrayList(java.util.ArrayList) SecurityViolationException(com.evolveum.midpoint.util.exception.SecurityViolationException) DeltaSetTriple(com.evolveum.midpoint.prism.delta.DeltaSetTriple) PrismContext(com.evolveum.midpoint.prism.PrismContext) PrismContainerDefinition(com.evolveum.midpoint.prism.PrismContainerDefinition) ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) ContainerDelta(com.evolveum.midpoint.prism.delta.ContainerDelta) LensUtil(com.evolveum.midpoint.model.impl.lens.LensUtil) PrismPropertyDefinition(com.evolveum.midpoint.prism.PrismPropertyDefinition) Iterator(java.util.Iterator) ShadowAssociationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType) PrismObject(com.evolveum.midpoint.prism.PrismObject) SynchronizationPolicyDecision(com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision) ItemPath(com.evolveum.midpoint.prism.path.ItemPath) LensProjectionContext(com.evolveum.midpoint.model.impl.lens.LensProjectionContext) Component(org.springframework.stereotype.Component) PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) LayerType(com.evolveum.midpoint.xml.ns._public.common.common_3.LayerType) PrismReference(com.evolveum.midpoint.prism.PrismReference) Comparator(java.util.Comparator) TraceManager(com.evolveum.midpoint.util.logging.TraceManager) PrismValueDeltaSetTriple(com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple) DeltaSetTriple(com.evolveum.midpoint.prism.delta.DeltaSetTriple) ArrayList(java.util.ArrayList) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue) MappingStrengthType(com.evolveum.midpoint.xml.ns._public.common.common_3.MappingStrengthType) ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) Collection(java.util.Collection) ResourceShadowDiscriminator(com.evolveum.midpoint.schema.ResourceShadowDiscriminator) Map(java.util.Map) HashMap(java.util.HashMap) PrismPropertyDefinition(com.evolveum.midpoint.prism.PrismPropertyDefinition) PrismValueDeltaSetTripleProducer(com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) ShadowAssociationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType) PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) PrismValueDeltaSetTriple(com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple) QName(javax.xml.namespace.QName) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) PrismContainerDefinition(com.evolveum.midpoint.prism.PrismContainerDefinition) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 70 with PropertyDelta

use of com.evolveum.midpoint.prism.delta.PropertyDelta 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)

Aggregations

PropertyDelta (com.evolveum.midpoint.prism.delta.PropertyDelta)83 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)51 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)36 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)25 QName (javax.xml.namespace.QName)24 Test (org.testng.annotations.Test)24 ArrayList (java.util.ArrayList)22 Task (com.evolveum.midpoint.task.api.Task)21 ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)19 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)18 ObjectDelta (com.evolveum.midpoint.prism.delta.ObjectDelta)16 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)11 SystemException (com.evolveum.midpoint.util.exception.SystemException)11 ObjectType (com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType)11 Collection (java.util.Collection)11 PrismPropertyValue (com.evolveum.midpoint.prism.PrismPropertyValue)10 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)10 ObjectAlreadyExistsException (com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException)10 SecurityViolationException (com.evolveum.midpoint.util.exception.SecurityViolationException)9 PolicyViolationException (com.evolveum.midpoint.util.exception.PolicyViolationException)8