Search in sources :

Example 6 with MatchingRule

use of com.evolveum.midpoint.prism.match.MatchingRule in project midpoint by Evolveum.

the class ShadowManager method fixShadow.

/**
	 * Re-reads the shadow, re-evaluates the identifiers and stored values, updates them if necessary. Returns
	 * fixed shadow.  
	 */
public PrismObject<ShadowType> fixShadow(ProvisioningContext ctx, PrismObject<ShadowType> origRepoShadow, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, ConfigurationException, CommunicationException, ExpressionEvaluationException {
    PrismObject<ShadowType> currentRepoShadow = repositoryService.getObject(ShadowType.class, origRepoShadow.getOid(), null, parentResult);
    ProvisioningContext shadowCtx = ctx.spawn(currentRepoShadow);
    RefinedObjectClassDefinition ocDef = shadowCtx.getObjectClassDefinition();
    PrismContainer<Containerable> attributesContainer = currentRepoShadow.findContainer(ShadowType.F_ATTRIBUTES);
    if (attributesContainer != null && attributesContainer.getValue() != null) {
        ObjectDelta<ShadowType> shadowDelta = currentRepoShadow.createModifyDelta();
        for (Item<?, ?> item : attributesContainer.getValue().getItems()) {
            if (item instanceof PrismProperty<?>) {
                PrismProperty<?> attrProperty = (PrismProperty<?>) item;
                RefinedAttributeDefinition<Object> attrDef = ocDef.findAttributeDefinition(attrProperty.getElementName());
                if (attrDef == null) {
                    // No definition for this property, it should not be in the shadow
                    PropertyDelta<?> oldRepoAttrPropDelta = attrProperty.createDelta();
                    oldRepoAttrPropDelta.addValuesToDelete((Collection) PrismPropertyValue.cloneCollection(attrProperty.getValues()));
                    shadowDelta.addModification(oldRepoAttrPropDelta);
                } else {
                    MatchingRule matchingRule = matchingRuleRegistry.getMatchingRule(attrDef.getMatchingRuleQName(), attrDef.getTypeName());
                    List<PrismPropertyValue> valuesToAdd = null;
                    List<PrismPropertyValue> valuesToDelete = null;
                    for (PrismPropertyValue attrVal : attrProperty.getValues()) {
                        Object currentRealValue = attrVal.getValue();
                        Object normalizedRealValue = matchingRule.normalize(currentRealValue);
                        if (!normalizedRealValue.equals(currentRealValue)) {
                            if (attrDef.isSingleValue()) {
                                shadowDelta.addModificationReplaceProperty(attrProperty.getPath(), normalizedRealValue);
                                break;
                            } else {
                                if (valuesToAdd == null) {
                                    valuesToAdd = new ArrayList<>();
                                }
                                valuesToAdd.add(new PrismPropertyValue(normalizedRealValue));
                                if (valuesToDelete == null) {
                                    valuesToDelete = new ArrayList<>();
                                }
                                valuesToDelete.add(new PrismPropertyValue(currentRealValue));
                            }
                        }
                    }
                    PropertyDelta attrDelta = attrProperty.createDelta(attrProperty.getPath());
                    if (valuesToAdd != null) {
                        attrDelta.addValuesToAdd(valuesToAdd);
                    }
                    if (valuesToDelete != null) {
                        attrDelta.addValuesToDelete(valuesToDelete);
                    }
                    shadowDelta.addModification(attrDelta);
                }
            }
        }
        if (!shadowDelta.isEmpty()) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Fixing shadow {} with delta:\n{}", origRepoShadow, shadowDelta.debugDump());
            }
            try {
                repositoryService.modifyObject(ShadowType.class, origRepoShadow.getOid(), shadowDelta.getModifications(), parentResult);
            } catch (ObjectAlreadyExistsException e) {
                // This should not happen for shadows
                throw new SystemException(e.getMessage(), e);
            }
            shadowDelta.applyTo(currentRepoShadow);
        } else {
            LOGGER.trace("No need to fixing shadow {} (empty delta)", origRepoShadow);
        }
    } else {
        LOGGER.trace("No need to fixing shadow {} (no atttributes)", origRepoShadow);
    }
    return currentRepoShadow;
}
Also used : RefinedObjectClassDefinition(com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition) PrismProperty(com.evolveum.midpoint.prism.PrismProperty) SystemException(com.evolveum.midpoint.util.exception.SystemException) Containerable(com.evolveum.midpoint.prism.Containerable) PrismObject(com.evolveum.midpoint.prism.PrismObject) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) MatchingRule(com.evolveum.midpoint.prism.match.MatchingRule) ObjectAlreadyExistsException(com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue)

Example 7 with MatchingRule

use of com.evolveum.midpoint.prism.match.MatchingRule 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 8 with MatchingRule

use of com.evolveum.midpoint.prism.match.MatchingRule 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

MatchingRule (com.evolveum.midpoint.prism.match.MatchingRule)8 QName (javax.xml.namespace.QName)6 RefinedObjectClassDefinition (com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition)4 PropertyDelta (com.evolveum.midpoint.prism.delta.PropertyDelta)4 RefinedResourceSchema (com.evolveum.midpoint.common.refinery.RefinedResourceSchema)3 Containerable (com.evolveum.midpoint.prism.Containerable)3 AbstractModelIntegrationTest (com.evolveum.midpoint.model.test.AbstractModelIntegrationTest)2 PrismObject (com.evolveum.midpoint.prism.PrismObject)2 PrismProperty (com.evolveum.midpoint.prism.PrismProperty)2 PrismPropertyValue (com.evolveum.midpoint.prism.PrismPropertyValue)2 StringIgnoreCaseMatchingRule (com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule)2 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)2 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)2 ObjectQuery (com.evolveum.midpoint.prism.query.ObjectQuery)2 PrismAsserts.assertEqualsPolyString (com.evolveum.midpoint.prism.util.PrismAsserts.assertEqualsPolyString)2 ResultHandler (com.evolveum.midpoint.schema.ResultHandler)2 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)2 ObjectAlreadyExistsException (com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException)2 SystemException (com.evolveum.midpoint.util.exception.SystemException)2 GenericObjectType (com.evolveum.midpoint.xml.ns._public.common.common_3.GenericObjectType)2