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);
}
}
}
}
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;
}
}
}
}
Aggregations