Search in sources :

Example 1 with ItemMergeConfigurationType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.ItemMergeConfigurationType in project midpoint by Evolveum.

the class ObjectMerger method computeDefaultDeltas.

private <O extends ObjectType> void computeDefaultDeltas(final ObjectDelta<O> leftObjectDelta, final PrismObject<O> objectLeft, final PrismObject<O> objectRight, final List<ItemPath> processedPaths, MergeConfigurationType mergeConfiguration, final String mergeConfigurationName, final Task task, final OperationResult result) throws SchemaException, ConfigurationException, ExpressionEvaluationException, ObjectNotFoundException {
    final ItemMergeConfigurationType defaultItemMergeConfig = mergeConfiguration.getDefault();
    if (defaultItemMergeConfig != null) {
        try {
            Visitor visitor = new Visitor() {

                @Override
                public void visit(Visitable visitable) {
                    if (!(visitable instanceof Item)) {
                        return;
                    }
                    Item item = (Item) visitable;
                    ItemPath itemPath = item.getPath();
                    if (itemPath == null || itemPath.isEmpty()) {
                        return;
                    }
                    if (SchemaConstants.PATH_LINK_REF.equivalent(itemPath)) {
                        // Skip. There is a special processing for this.
                        return;
                    }
                    boolean found = false;
                    for (ItemPath processedPath : processedPaths) {
                        // Need to check for super-paths here.
                        // E.g. if we have already processed metadata, we do not want to process
                        // metadata/modifyTimestamp
                        CompareResult compareResult = processedPath.compareComplex(itemPath);
                        if (compareResult == CompareResult.EQUIVALENT || compareResult == CompareResult.SUBPATH) {
                            found = true;
                            break;
                        }
                    }
                    if (found) {
                        return;
                    }
                    processedPaths.add(itemPath);
                    if (item instanceof PrismContainer<?>) {
                        if (item.getDefinition().isSingleValue()) {
                            // we will handle every individual property there.
                            return;
                        } else {
                        // TODO: we may need special handling for multi-value containers
                        // such as assignment
                        }
                    }
                    ItemDelta itemDelta;
                    try {
                        itemDelta = mergeItem(objectLeft, objectRight, mergeConfigurationName, defaultItemMergeConfig, itemPath, task, result);
                    } catch (SchemaException | ConfigurationException | ExpressionEvaluationException | ObjectNotFoundException e) {
                        throw new TunnelException(e);
                    }
                    LOGGER.trace("Item {} delta (default): {}", itemPath, itemDelta);
                    if (itemDelta != null && !itemDelta.isEmpty()) {
                        leftObjectDelta.addModification(itemDelta);
                    }
                }
            };
            objectLeft.accept(visitor);
            objectRight.accept(visitor);
        } catch (TunnelException te) {
            if (te.getCause() instanceof SchemaException) {
                throw (SchemaException) te.getCause();
            } else if (te.getCause() instanceof ConfigurationException) {
                throw (ConfigurationException) te.getCause();
            } else if (te.getCause() instanceof ExpressionEvaluationException) {
                throw (ExpressionEvaluationException) te.getCause();
            } else if (te.getCause() instanceof ObjectNotFoundException) {
                throw (ObjectNotFoundException) te.getCause();
            } else {
                throw new SystemException("Unexpected exception: " + te, te);
            }
        }
    }
}
Also used : SchemaException(com.evolveum.midpoint.util.exception.SchemaException) ExpressionEvaluationException(com.evolveum.midpoint.util.exception.ExpressionEvaluationException) Visitor(com.evolveum.midpoint.prism.Visitor) Visitable(com.evolveum.midpoint.prism.Visitable) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) ItemMergeConfigurationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ItemMergeConfigurationType) CompareResult(com.evolveum.midpoint.prism.path.ItemPath.CompareResult) Item(com.evolveum.midpoint.prism.Item) TunnelException(com.evolveum.midpoint.util.exception.TunnelException) SystemException(com.evolveum.midpoint.util.exception.SystemException) ConfigurationException(com.evolveum.midpoint.util.exception.ConfigurationException) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) PrismContainer(com.evolveum.midpoint.prism.PrismContainer) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 2 with ItemMergeConfigurationType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.ItemMergeConfigurationType in project midpoint by Evolveum.

the class ObjectMerger method mergeItem.

private <O extends ObjectType, I extends Item> ItemDelta mergeItem(PrismObject<O> objectLeft, PrismObject<O> objectRight, String mergeConfigurationName, ItemMergeConfigurationType itemMergeConfig, ItemPath itemPath, Task task, OperationResult result) throws SchemaException, ConfigurationException, ExpressionEvaluationException, ObjectNotFoundException {
    I itemLeft = (I) objectLeft.findItem(itemPath);
    I itemRight = (I) objectRight.findItem(itemPath);
    if (itemLeft == null && itemRight == null) {
        return null;
    }
    ItemDefinition itemDefinition = null;
    if (itemLeft != null) {
        itemDefinition = itemLeft.getDefinition();
    } else {
        itemDefinition = itemRight.getDefinition();
    }
    if (itemDefinition.isOperational()) {
        // we do not want to modify them explicitly.
        return null;
    }
    Expression<PrismValue, ItemDefinition> valueExpression = null;
    if (itemMergeConfig.getValueExpression() != null) {
        ExpressionType expressionType = itemMergeConfig.getValueExpression();
        valueExpression = expressionFactory.makeExpression(expressionType, itemDefinition, "value expression for item " + itemPath + " in merge configuration " + mergeConfigurationName, task, result);
    }
    ItemDelta itemDelta = itemDefinition.createEmptyDelta(itemPath);
    MergeStategyType leftStrategy = itemMergeConfig.getLeft();
    MergeStategyType rightStrategy = itemMergeConfig.getRight();
    if (leftStrategy == null || leftStrategy == MergeStategyType.IGNORE) {
        if (rightStrategy == null || rightStrategy == MergeStategyType.IGNORE) {
            // IGNORE both
            if (itemLeft == null) {
                return null;
            } else {
                itemDelta.setValueToReplace();
                return itemDelta;
            }
        } else {
            // IGNORE left, TAKE/EXPRESSION right
            if (itemRight == null) {
                itemDelta.setValueToReplace();
            } else {
                Collection<PrismValue> valuesToTake = getValuesToTake(objectLeft, objectRight, SIDE_RIGHT, itemRight, rightStrategy, valueExpression, task, result);
                itemDelta.setValuesToReplace(valuesToTake);
            }
            return itemDelta;
        }
    } else {
        if (rightStrategy == null || rightStrategy == MergeStategyType.IGNORE) {
            if (leftStrategy == MergeStategyType.TAKE) {
                // TAKE left, IGNORE right
                return null;
            } else {
                // EXPRESSION left, IGNORE right
                Collection<PrismValue> valuesToLeave = getValuesToTake(objectLeft, objectRight, SIDE_LEFT, itemLeft, leftStrategy, valueExpression, task, result);
                List<PrismValue> currentLeftValues = itemLeft.getValues();
                Collection<PrismValue> leftValuesToRemove = diffValues(currentLeftValues, valuesToLeave);
                if (leftValuesToRemove != null && !leftValuesToRemove.isEmpty()) {
                    itemDelta.addValuesToDelete(leftValuesToRemove);
                    return itemDelta;
                } else {
                    return null;
                }
            }
        } else {
            // TAKE/EXPRESSION left, TAKE/EXPRESSION right
            if (itemLeft == null) {
                Collection<PrismValue> valuesToTake = getValuesToTake(objectLeft, objectRight, SIDE_RIGHT, itemRight, rightStrategy, valueExpression, task, result);
                itemDelta.addValuesToAdd(valuesToTake);
                return itemDelta;
            } else {
                // We want to add only those values that are not yet there.
                // E.g. adding assignments that are there can cause unnecessary churn
                Collection<PrismValue> leftValuesToLeave = getValuesToTake(objectLeft, objectRight, SIDE_LEFT, itemLeft, leftStrategy, valueExpression, task, result);
                Collection<PrismValue> rightValuesToTake = getValuesToTake(objectLeft, objectRight, SIDE_RIGHT, itemRight, rightStrategy, valueExpression, task, result);
                for (PrismValue rightValueToTake : rightValuesToTake) {
                    if (!PrismValue.collectionContainsEquivalentValue(leftValuesToLeave, rightValueToTake)) {
                        itemDelta.addValueToAdd(rightValueToTake);
                    }
                }
                List<PrismValue> currentLeftValues = itemLeft.getValues();
                Collection<PrismValue> leftValuesToRemove = diffValues(currentLeftValues, leftValuesToLeave);
                if (leftValuesToRemove != null && !leftValuesToRemove.isEmpty()) {
                    itemDelta.addValuesToDelete(leftValuesToRemove);
                }
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Merging item {} T/T case:\n  leftValuesToLeave: {}\n  rightValuesToTake: {}\n  leftValuesToRemove: {}\n itemDelta:\n{}", new Object[] { itemPath, leftValuesToLeave, rightValuesToTake, leftValuesToRemove, itemDelta.debugDump(2) });
                }
                return itemDelta;
            }
        }
    }
}
Also used : ItemDefinition(com.evolveum.midpoint.prism.ItemDefinition) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) MergeStategyType(com.evolveum.midpoint.xml.ns._public.common.common_3.MergeStategyType) ExpressionType(com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType) PrismValue(com.evolveum.midpoint.prism.PrismValue)

Aggregations

ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)2 Item (com.evolveum.midpoint.prism.Item)1 ItemDefinition (com.evolveum.midpoint.prism.ItemDefinition)1 PrismContainer (com.evolveum.midpoint.prism.PrismContainer)1 PrismValue (com.evolveum.midpoint.prism.PrismValue)1 Visitable (com.evolveum.midpoint.prism.Visitable)1 Visitor (com.evolveum.midpoint.prism.Visitor)1 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)1 CompareResult (com.evolveum.midpoint.prism.path.ItemPath.CompareResult)1 ConfigurationException (com.evolveum.midpoint.util.exception.ConfigurationException)1 ExpressionEvaluationException (com.evolveum.midpoint.util.exception.ExpressionEvaluationException)1 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)1 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)1 SystemException (com.evolveum.midpoint.util.exception.SystemException)1 TunnelException (com.evolveum.midpoint.util.exception.TunnelException)1 ExpressionType (com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType)1 ItemMergeConfigurationType (com.evolveum.midpoint.xml.ns._public.common.common_3.ItemMergeConfigurationType)1 MergeStategyType (com.evolveum.midpoint.xml.ns._public.common.common_3.MergeStategyType)1