diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ExceptionUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ExceptionUtil.java index ec2ba412922..55e2e253e25 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ExceptionUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ExceptionUtil.java @@ -55,21 +55,21 @@ public static boolean isSelected(ErrorSelectorType selector, Throwable exception return false; } if (exception instanceof CommunicationException) { - return selector.isNetwork() == Boolean.TRUE; + return Boolean.TRUE.equals(selector.isNetwork()); } if (exception instanceof SecurityViolationException) { - return selector.isSecurity() == Boolean.TRUE; + return Boolean.TRUE.equals(selector.isSecurity()); } if (exception instanceof PolicyViolationException) { - return selector.isPolicy() == Boolean.TRUE; + return Boolean.TRUE.equals(selector.isPolicy()); } if (exception instanceof SchemaException) { - return selector.isSchema() == Boolean.TRUE; + return Boolean.TRUE.equals(selector.isSchema()); } if (exception instanceof ConfigurationException || exception instanceof ExpressionEvaluationException) { - return selector.isConfiguration() == Boolean.TRUE; + return Boolean.TRUE.equals(selector.isConfiguration()); } - return selector.isGeneric() == Boolean.TRUE; + return Boolean.TRUE.equals(selector.isGeneric()); } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java index 62f94ca67d9..67a9c486c3d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java @@ -457,10 +457,10 @@ private void reconcileProjectionAttribute(QName attrName, // LOGGER.trace("{}", sb.toString()); // } - ValueMatcher valueMatcher = ValueMatcher.createMatcher(attributeDefinition, - matchingRuleRegistry); + ValueMatcher valueMatcher = ValueMatcher.createMatcher(attributeDefinition, matchingRuleRegistry); - boolean hasValue = false; + T realValueToReplace = null; + boolean hasRealValueToReplace = false; for (ItemValueWithOrigin,PrismPropertyDefinition> shouldBePvwo : shouldBePValues) { PrismValueDeltaSetTripleProducer shouldBeMapping = shouldBePvwo.getMapping(); if (shouldBeMapping == null) { @@ -473,25 +473,34 @@ private void reconcileProjectionAttribute(QName attrName, // value. Skip it. // we cannot override it as it might have been legally // changed directly on the projection resource object - LOGGER.trace("Skipping reconciliation of value {} of the attribute {}: the mapping is not strong" , shouldBeRealValue, attributeDefinition.getName().getLocalPart()); + LOGGER.trace("Skipping reconciliation of value {} of the attribute {}: the mapping is not strong", shouldBeRealValue, attributeDefinition.getName().getLocalPart()); continue; } if (!isInValues(valueMatcher, shouldBeRealValue, arePValues)) { if (attributeDefinition.isSingleValue()) { - if (hasValue) { - throw new SchemaException( - "Attempt to set more than one value for single-valued attribute " - + attrName + " in " + projCtx.getResourceShadowDiscriminator()); + // It is quite possible that there are more shouldBePValues with equivalent real values but different 'context'. + // We don't want to throw an exception if real values are in fact equivalent. + // TODO generalize this a bit (e.g. also for multivalued items) + if (hasRealValueToReplace) { + if (matchValue(shouldBeRealValue, realValueToReplace, valueMatcher)) { + LOGGER.trace("Value to replace for {} is already set, skipping it: {}", attrName, realValueToReplace); + continue; + } else { + String message = "Attempt to set more than one value for single-valued attribute " + + attrName + " in " + projCtx.getResourceShadowDiscriminator(); + LOGGER.debug("{}: value to be added: {}, existing value to replace: {}", message, shouldBeMapping, realValueToReplace); + throw new SchemaException(message); + } } + hasRealValueToReplace = true; + realValueToReplace = shouldBeRealValue; recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.REPLACE, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping"); } else { recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.ADD, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping"); } - hasValue = true; } - } decideIfTolerate(projCtx, attributeDefinition, arePValues, shouldBePValues, valueMatcher);