Skip to content

Commit

Permalink
Fixed handling of strong mappings (MID-2513). Extended tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Aug 25, 2015
1 parent cb1b66d commit 853936e
Show file tree
Hide file tree
Showing 37 changed files with 485 additions and 282 deletions.
Expand Up @@ -35,6 +35,7 @@
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator;
import com.evolveum.midpoint.model.api.PolicyViolationException;
import com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision;
import com.evolveum.midpoint.model.common.expression.Expression;
import com.evolveum.midpoint.model.common.expression.ExpressionEvaluationContext;
import com.evolveum.midpoint.model.common.expression.ExpressionFactory;
Expand Down Expand Up @@ -380,9 +381,8 @@ public void visit(I pvwo) {
continue;
}
if (filterExistingValues && !hasValue(itemExisting, value, valueMatcher, comparator)) {
// temporarily changed from .trace to .info in order to assist with problems like MID-2368
LOGGER.info("Value {} NOT deleted to delta for item {} the item does not have that value in {}",
new Object[]{value, itemPath, contextDescription});
LOGGER.trace("Value {} NOT deleted to delta for item {} the item does not have that value in {} (matcher: {})",
new Object[]{value, itemPath, contextDescription, valueMatcher});
continue;
}
LOGGER.trace("Value {} deleted to delta for item {} in {}",
Expand Down Expand Up @@ -618,11 +618,16 @@ public static <F extends ObjectType> void loadFullAccount(LensContext<F> context
return;
}
}
LOGGER.trace("Loading full resource object {} from provisioning", accCtx);

try{
GetOperationOptions getOptions = GetOperationOptions.createDoNotDiscovery();
getOptions.setAllowNotFound(true);

GetOperationOptions getOptions = GetOperationOptions.createAllowNotFound();
if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(context.getChannel())) {
LOGGER.trace("Loading full resource object {} from provisioning - with doNotDiscover to avoid loops", accCtx);
getOptions.setDoNotDiscovery(true);
} else {
LOGGER.trace("Loading full resource object {} from provisioning (discovery enabled)", accCtx);
}
try {
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(getOptions);
PrismObject<ShadowType> objectOld = provisioningService.getObject(ShadowType.class,
accCtx.getOid(), options,
Expand All @@ -632,12 +637,20 @@ public static <F extends ObjectType> void loadFullAccount(LensContext<F> context
ShadowType oldShadow = objectOld.asObjectable();
accCtx.determineFullShadowFlag(oldShadow.getFetchResult());

} catch (ObjectNotFoundException ex){
} catch (ObjectNotFoundException ex) {
LOGGER.trace("Load of full resource object {} ended with ObjectNotFoundException (options={})", accCtx, getOptions);
if (accCtx.isDelete()){
//this is OK, shadow was deleted, but we will continue in processing with old shadow..and set it as full so prevent from other full loading
accCtx.setFullShadow(true);
} else
throw ex;
} else {
accCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN);
if (GetOperationOptions.isDoNotDiscovery(getOptions)) {
LOGGER.error("Load of full resource object {} resulted in ObjectNotFoundException (discovery disabled to avoid loops)", accCtx, getOptions);
throw ex;
} else {
// Setting the context to broken should be enough here.
}
}
}

accCtx.recompute();
Expand Down
Expand Up @@ -252,20 +252,29 @@ public boolean isAuthoritative() {
// That may be a waste of resources if the weak mapping results in no change anyway.
// Let's be very very lazy about fetching the account from the resource.
if (!projCtx.hasFullShadow() &&
(hasActiveWeakMapping(squeezedAttributes, projCtx) || hasActiveWeakMapping(squeezedAssociations, projCtx))) {
(hasActiveWeakMapping(squeezedAttributes, projCtx) || hasActiveWeakMapping(squeezedAssociations, projCtx)
|| (hasActiveStrongMapping(squeezedAttributes, projCtx) || hasActiveStrongMapping(squeezedAssociations, projCtx)))) {
// Full account was not yet loaded. This will cause problems as
// the weak mapping may be applied even though it should not be
// applied
// and also same changes may be discarded because of unavailability
// of all
// account's attributes.Therefore load the account now, but with
// doNotDiscovery options..

// We also need to get account if there are strong mappings. Strong mappings
// should always be applied. So reading the account now will indirectly
// trigger reconciliation which makes sure that the strong mappings are
// applied.

// By getting accounts from provisioning, there might be a problem with
// resource availability. We need to know, if the account was read full
// or we have only the shadow from the repository. If we have only
// shadow, the weak mappings may applied even if they should not be.
LensUtil.loadFullAccount(context, projCtx, provisioningService, result);
if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return null;
}
}

boolean completeAccount = projCtx.hasFullShadow();
Expand Down Expand Up @@ -388,10 +397,12 @@ public int compare(PrismContainerValue<ShadowAssociationType> o1,
PrismContainerValue<ShadowAssociationType> o2) {

if (o1 == null && o2 == null){
LOGGER.trace("Comparing {} and {}: 0 (A)", o1, o2);
return 0;
}

if (o1 == null || o2 == null){
LOGGER.trace("Comparing {} and {}: 2 (B)", o1, o2);
return 1;
}

Expand All @@ -404,9 +415,11 @@ public int compare(PrismContainerValue<ShadowAssociationType> o1,
String oid1 = ref1 != null ? ref1.getOid() : null;
String oid2 = ref2 != null ? ref2.getOid() : null;
if (ObjectUtils.equals(oid1, oid2)) {
LOGGER.trace("Comparing {} and {}: 0 (C)", o1, o2);
return 0;
}

LOGGER.trace("Comparing {} and {}: 1 (D)", o1, o2);
return 1;
}
};
Expand Down Expand Up @@ -565,6 +578,23 @@ private <V extends PrismValue,D extends ItemDefinition> boolean hasActiveWeakMap
}
return false;
}

private <V extends PrismValue,D extends ItemDefinition> boolean hasActiveStrongMapping(
Map<QName, DeltaSetTriple<ItemValueWithOrigin<V,D>>> squeezedAttributes, LensProjectionContext accCtx) throws SchemaException {
for (Map.Entry<QName, DeltaSetTriple<ItemValueWithOrigin<V,D>>> entry : squeezedAttributes.entrySet()) {
DeltaSetTriple<ItemValueWithOrigin<V,D>> ivwoTriple = entry.getValue();
for (ItemValueWithOrigin<V,D> ivwo: ivwoTriple.getAllValues()) {
PrismValueDeltaSetTripleProducer<V,D> mapping = ivwo.getMapping();
if (mapping.getStrength() == MappingStrengthType.STRONG) {
// Do not optimize for "nothing changed" case here. We want to make
// sure that the values of strong mappings are applied even if nothing
// has changed.
return true;
}
}
}
return false;
}

private <F extends FocusType> void consolidateValuesModifyProjection(LensContext<F> context,
LensProjectionContext accCtx, OperationResult result)
Expand Down

0 comments on commit 853936e

Please sign in to comment.