Skip to content

Commit

Permalink
Fixing use of matching rules for duplicate values (MID-2307, MID-2927)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed May 5, 2016
1 parent 51dc9e8 commit 78acd87
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 60 deletions.
Expand Up @@ -19,13 +19,15 @@
import java.util.Collection;

import com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer;
import com.evolveum.midpoint.model.impl.lens.projector.ValueMatcher;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.exception.SchemaException;

/**
* @author semancik
Expand All @@ -45,11 +47,6 @@ public ItemValueWithOrigin(V propertyValue,
this.construction = accountConstruction;
}

@Deprecated
public V getPropertyValue() {
return itemValue;
}

// the same as above, but with correct name
public V getItemValue() {
return itemValue;
Expand All @@ -72,11 +69,17 @@ public boolean isValid() {
return construction.isValid();
}

public boolean equalsRealValue(V pvalue) {
public <T> boolean equalsRealValue(V pvalue, ValueMatcher<T> valueMatcher) throws SchemaException {
if (itemValue == null) {
return false;
}
return itemValue.equalsRealValue(pvalue);
if (valueMatcher == null) {
return itemValue.equalsRealValue(pvalue);
} else {
// this must be a property, otherwise there would be no matcher
return valueMatcher.match(((PrismPropertyValue<T>)itemValue).getValue(),
((PrismPropertyValue<T>)pvalue).getValue());
}
}

public ItemValueWithOrigin<V,D> clone() {
Expand Down
Expand Up @@ -234,7 +234,7 @@ ItemDelta<V,D> consolidateTripleToDelta(
});
}

Collection<V> allValues = collectAllValues(triple);
Collection<V> allValues = collectAllValues(triple, valueMatcher);

final MutableBoolean itemHasStrongMutable = new MutableBoolean(false);
SimpleVisitor<I> visitor = new SimpleVisitor<I>() {
Expand All @@ -258,11 +258,11 @@ public void visit(I pvwo) {
// The first set that the value is present determines the result.
// TODO shouldn't we use valueMatcher here? [med]
Collection<ItemValueWithOrigin<V,D>> zeroPvwos =
collectPvwosFromSet(value, triple.getZeroSet());
collectPvwosFromSet(value, triple.getZeroSet(), valueMatcher);
Collection<ItemValueWithOrigin<V,D>> plusPvwos =
collectPvwosFromSet(value, triple.getPlusSet());
collectPvwosFromSet(value, triple.getPlusSet(), valueMatcher);
Collection<ItemValueWithOrigin<V,D>> minusPvwos =
collectPvwosFromSet(value, triple.getMinusSet());
collectPvwosFromSet(value, triple.getMinusSet(), valueMatcher);

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("PVWOs for value {}:\nzero = {}\nplus = {}\nminus = {}",
Expand Down Expand Up @@ -492,8 +492,8 @@ private static <V extends PrismValue, D extends ItemDefinition> Collection<V> ad
Collection<V> values = new ArrayList<V>();
for (ItemValueWithOrigin<V,D> pvwo: pvwos) {
if (pvwo.getMapping().getStrength() == MappingStrengthType.WEAK && applyWeak) {
if (origin == null || origin == pvwo.getPropertyValue().getOriginType()) {
values.add((V)pvwo.getPropertyValue().clone());
if (origin == null || origin == pvwo.getItemValue().getOriginType()) {
values.add((V)pvwo.getItemValue().clone());
}
}
}
Expand All @@ -511,32 +511,47 @@ private static <V extends PrismValue, D extends ItemDefinition> boolean hasValue
}
}

private static <V extends PrismValue, D extends ItemDefinition> Collection<V> collectAllValues(DeltaSetTriple<? extends ItemValueWithOrigin<V,D>> triple) {
private static <V extends PrismValue, D extends ItemDefinition> Collection<V> collectAllValues
(DeltaSetTriple<? extends ItemValueWithOrigin<V,D>> triple, ValueMatcher<?> valueMatcher) throws SchemaException {
Collection<V> allValues = new HashSet<>();
collectAllValuesFromSet(allValues, triple.getZeroSet());
collectAllValuesFromSet(allValues, triple.getPlusSet());
collectAllValuesFromSet(allValues, triple.getMinusSet());
collectAllValuesFromSet(allValues, triple.getZeroSet(), valueMatcher);
collectAllValuesFromSet(allValues, triple.getPlusSet(), valueMatcher);
collectAllValuesFromSet(allValues, triple.getMinusSet(), valueMatcher);
return allValues;
}

private static <V extends PrismValue, D extends ItemDefinition> void collectAllValuesFromSet(Collection<V> allValues,
Collection<? extends ItemValueWithOrigin<V,D>> collection) {
private static <V extends PrismValue, D extends ItemDefinition, T> void collectAllValuesFromSet(Collection<V> allValues,
Collection<? extends ItemValueWithOrigin<V,D>> collection, ValueMatcher<T> valueMatcher) throws SchemaException {
if (collection == null) {
return;
}
for (ItemValueWithOrigin<V,D> pvwo : collection) {
V pval = pvwo.getPropertyValue();
if (!PrismValue.containsRealValue(allValues, pval)) {
allValues.add(pval);
V pval = pvwo.getItemValue();
if (valueMatcher == null) {
if (!PrismValue.containsRealValue(allValues, pval)) {
allValues.add(pval);
}
} else {
boolean found = false;
for (V valueFromAllvalues: allValues) {
if (valueMatcher.match(((PrismPropertyValue<T>)valueFromAllvalues).getValue(),
((PrismPropertyValue<T>)pval).getValue())) {
found = true;
break;
}
}
if (!found) {
allValues.add(pval);
}
}
}
}

private static <V extends PrismValue, D extends ItemDefinition> Collection<ItemValueWithOrigin<V,D>> collectPvwosFromSet(V pvalue,
Collection<? extends ItemValueWithOrigin<V,D>> deltaSet) {
Collection<? extends ItemValueWithOrigin<V,D>> deltaSet, ValueMatcher<?> valueMatcher) throws SchemaException {
Collection<ItemValueWithOrigin<V,D>> pvwos = new ArrayList<>();
for (ItemValueWithOrigin<V,D> setPvwo : deltaSet) {
if (setPvwo.equalsRealValue(pvalue)) {
if (setPvwo.equalsRealValue(pvalue, valueMatcher)) {
pvwos.add(setPvwo);
}
}
Expand Down
Expand Up @@ -489,8 +489,8 @@ private PrismContainerDefinition<ShadowAssociationType> getAssociationDefinition
private <V extends PrismValue,D extends ItemDefinition> ItemDelta<V,D> consolidateItem(RefinedObjectClassDefinition rOcDef,
ResourceShadowDiscriminator discr, ObjectDelta<ShadowType> existingDelta, LensProjectionContext projCtx,
boolean addUnchangedValues, boolean completeShadow, boolean isExclusiveStrong,
ItemPath itemPath, D itemDefinition,
DeltaSetTriple<ItemValueWithOrigin<V,D>> triple, ValueMatcher<?> valueMatcher, Comparator<V> comparator, String itemDesc)
ItemPath itemPath, D itemDefinition, DeltaSetTriple<ItemValueWithOrigin<V,D>> triple,
ValueMatcher<?> valueMatcher, Comparator<V> comparator, String itemDesc)
throws SchemaException, ExpressionEvaluationException, PolicyViolationException {

boolean forceAddUnchangedValues = false;
Expand Down
Expand Up @@ -774,18 +774,6 @@ private boolean isInAssociationValues(ValueMatcher valueMatcher, ShadowAssociati
return false;
}

private boolean isInPvwoValues(Object value,
Collection<ItemValueWithOrigin<? extends PrismPropertyValue<?>,PrismPropertyDefinition<?>>> shouldBePvwos) {
for (ItemValueWithOrigin<? extends PrismPropertyValue<?>,PrismPropertyDefinition<?>> shouldBePvwo : shouldBePvwos) {
PrismPropertyValue<?> shouldBePPValue = shouldBePvwo.getPropertyValue();
Object shouldBeValue = shouldBePPValue.getValue();
if (shouldBeValue.equals(value)) {
return true;
}
}
return false;
}

private <T> boolean isInPvwoValues(ValueMatcher<T> valueMatcher, T value,
Collection<ItemValueWithOrigin<PrismPropertyValue<T>,PrismPropertyDefinition<T>>> shouldBePvwos) {

Expand All @@ -797,7 +785,7 @@ private <T> boolean isInPvwoValues(ValueMatcher<T> valueMatcher, T value,
if (!shouldBePvwo.isValid()) {
continue;
}
PrismPropertyValue<T> shouldBePPValue = shouldBePvwo.getPropertyValue();
PrismPropertyValue<T> shouldBePPValue = shouldBePvwo.getItemValue();
T shouldBeValue = shouldBePPValue.getValue();
if (matchValue(value, shouldBeValue, valueMatcher)) {
return true;
Expand Down
Expand Up @@ -1471,11 +1471,19 @@ private void collectAttributeAndEntitlementChanges(ProvisioningContext ctx,
if (operations == null) {
operations = new ArrayList<Operation>();
}
RefinedObjectClassDefinition objectClassDefinition = ctx.getObjectClassDefinition();
for (ItemDelta itemDelta : objectChange) {
if (isAttributeDelta(itemDelta) || SchemaConstants.PATH_PASSWORD.equivalent(itemDelta.getParentPath())) {
if (itemDelta instanceof PropertyDelta) {
PropertyModificationOperation attributeModification = new PropertyModificationOperation(
(PropertyDelta) itemDelta);
RefinedAttributeDefinition<Object> attrDef = objectClassDefinition.findAttributeDefinition(itemDelta.getElementName());
if (attrDef != null) {
attributeModification.setMatchingRuleQName(attrDef.getMatchingRuleQName());
if (itemDelta.getDefinition() == null) {
itemDelta.setDefinition(attrDef);
}
}
operations.add(attributeModification);
} else if (itemDelta instanceof ContainerDelta) {
// skip the container delta - most probably password change
Expand Down
Expand Up @@ -246,10 +246,10 @@ public static <T> PropertyDelta<T> narrowPropertyDelta(PropertyDelta<T> property
matchingRuleQName = ((RefinedAttributeDefinition)propertyDef).getMatchingRuleQName();
}
MatchingRule<T> matchingRule = null;
if (matchingRuleQName != null) {
if (matchingRuleQName != null && propertyDef != null) {
matchingRule = matchingRuleRegistry.getMatchingRule(matchingRuleQName, propertyDef.getTypeName());
}
LOGGER.trace("Narrowing attr def={}, matchingRule={}", propertyDef, matchingRule);
LOGGER.trace("Narrowing attr def={}, matchingRule={} ({})", propertyDef, matchingRule, matchingRuleQName);
PropertyDelta<T> filteredDelta = propertyDelta.narrow(currentShadow, matchingRule);
if (LOGGER.isTraceEnabled() && !filteredDelta.equals(propertyDelta)) {
LOGGER.trace("Narrowed delta: {}", filteredDelta.debugDump());
Expand Down

0 comments on commit 78acd87

Please sign in to comment.