Skip to content

Commit

Permalink
Fix for MID-2212.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Feb 12, 2015
1 parent 885b0de commit 38aed86
Show file tree
Hide file tree
Showing 9 changed files with 464 additions and 50 deletions.
Expand Up @@ -498,6 +498,11 @@ public String toHumanReadableString() {
sb.append(DebugUtil.formatElementName(getTargetType()));
sb.append(")");
}
if (getRelation() != null) {
sb.append("[");
sb.append(getRelation().getLocalPart());
sb.append("]");
}
return sb.toString();
}

Expand Down
Expand Up @@ -23,6 +23,7 @@

import javax.xml.namespace.QName;

import com.evolveum.midpoint.util.QNameUtil;
import org.apache.commons.lang.StringUtils;
import org.testng.AssertJUnit;

Expand Down Expand Up @@ -87,7 +88,7 @@ public static <F extends FocusType> void assertNotAssigned(PrismObject<F> user,
}
}
}

public static <F extends FocusType> void assertAssignments(PrismObject<F> user, int expectedNumber) {
F userType = user.asObjectable();
assertEquals("Unexepected number of assignments in "+user+": "+userType.getAssignment(), expectedNumber, userType.getAssignment().size());
Expand Down Expand Up @@ -125,6 +126,20 @@ public static <F extends FocusType> void assertAssignedRole(PrismObject<F> user,
public static <F extends FocusType> void assertNotAssignedRole(PrismObject<F> user, String roleOid) {
assertNotAssigned(user, roleOid, RoleType.COMPLEX_TYPE);
}

public static <F extends FocusType> void assertNotAssignedOrg(PrismObject<F> user, String orgOid, QName relation) {
F userType = user.asObjectable();
for (AssignmentType assignmentType: userType.getAssignment()) {
ObjectReferenceType targetRef = assignmentType.getTargetRef();
if (targetRef != null) {
if (OrgType.COMPLEX_TYPE.equals(targetRef.getType())) {
if (orgOid.equals(targetRef.getOid()) && QNameUtil.match(targetRef.getRelation(), relation)) {
AssertJUnit.fail(user + " does have assigned OrgType "+orgOid+" with relation "+relation+" while not expecting it");
}
}
}
}
}

public static void assertAssignedOrg(PrismObject<UserType> user, String orgOid) {
assertAssigned(user, orgOid, OrgType.COMPLEX_TYPE);
Expand Down
Expand Up @@ -180,6 +180,10 @@ public String debugDump(int indent) {
DebugUtil.debugDumpLabel(sb, "EvaluatedAssignment", indent);
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "isValid", isValid, indent + 1);
if (forceRecon) {
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "forceRecon", forceRecon, indent + 1);
}
if (!constructions.isEmpty()) {
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "Constructions", constructions, indent+1);
Expand Down
Expand Up @@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
Expand Down Expand Up @@ -1116,32 +1117,85 @@ public <F extends ObjectType> void processOrgAssignments(LensContext<F> context,
return;
}

LOGGER.trace("Processing org assignments into parentOrgRef delta(s)");

Class<F> focusClass = focusContext.getObjectTypeClass();
PrismObjectDefinition<F> userDef = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(focusClass);
PrismReferenceDefinition orgRefDef = userDef.findReferenceDefinition(FocusType.F_PARENT_ORG_REF);
ItemPath orgRefPath = new ItemPath(FocusType.F_PARENT_ORG_REF);

// Plus
for (EvaluatedAssignment assignment: evaluatedAssignmentTriple.getPlusSet()) {
Collection<PrismReferenceValue> orgs = assignment.getOrgRefVals();
for (PrismReferenceValue org: orgs) {
ItemDelta orgRefDelta = orgRefDef.createEmptyDelta(orgRefPath);
orgRefDelta.addValueToAdd(org.toCannonical());
focusContext.swallowToProjectionWaveSecondaryDelta(orgRefDelta);
}
}

// Minus
for (EvaluatedAssignment assignment: evaluatedAssignmentTriple.getMinusSet()) {
Collection<PrismReferenceValue> orgs = assignment.getOrgRefVals();
for (PrismReferenceValue org: orgs) {
ItemDelta orgRefDelta = orgRefDef.createEmptyDelta(orgRefPath);
orgRefDelta.addValueToDelete(org.toCannonical());
focusContext.swallowToProjectionWaveSecondaryDelta(orgRefDelta);
}
}

// TODO: zero set if reconciliation?

// check if recon is needed
boolean forceRecon = false;
for (EvaluatedAssignment assignment: evaluatedAssignmentTriple.getAllValues()) {
if (assignment.isForceRecon()) {
forceRecon = true;
break;
}
}

if (!forceRecon) { // if no recon, we simply add/delete values as needed

LOGGER.trace("No reconciliation requested, processing plus and minus sets");

// A list of values that are _not_ to be removed - these are all the values from zero set,
// as well as values from plus set.
//
// Contrary to existing standard delta merge algorithm (where add+delete means "keep the current state"),
// we ignore any delete of values that should be existing or added.

Collection<PrismReferenceValue> notToBeDeletedCanonical = new HashSet<>();
for (EvaluatedAssignment assignment : evaluatedAssignmentTriple.getZeroSet()) {
Collection<PrismReferenceValue> orgs = assignment.getOrgRefVals();
for (PrismReferenceValue org : orgs) {
notToBeDeletedCanonical.add(org.toCannonical());
}
}

// Plus
for (EvaluatedAssignment assignment : evaluatedAssignmentTriple.getPlusSet()) {
Collection<PrismReferenceValue> orgs = assignment.getOrgRefVals();
for (PrismReferenceValue org : orgs) {
ItemDelta orgRefDelta = orgRefDef.createEmptyDelta(orgRefPath);
PrismReferenceValue orgCanonical = org.toCannonical();
orgRefDelta.addValueToAdd(orgCanonical);
focusContext.swallowToProjectionWaveSecondaryDelta(orgRefDelta);

notToBeDeletedCanonical.add(orgCanonical);
}
}

// Minus (except for these that are also in zero set)
for (EvaluatedAssignment assignment : evaluatedAssignmentTriple.getMinusSet()) {
Collection<PrismReferenceValue> orgs = assignment.getOrgRefVals();
for (PrismReferenceValue org : orgs) {
ItemDelta orgRefDelta = orgRefDef.createEmptyDelta(orgRefPath);
PrismReferenceValue orgCanonical = org.toCannonical();
if (notToBeDeletedCanonical.contains(orgCanonical)) {
LOGGER.trace("Not removing {} because it is in the zero or plus set", orgCanonical);
} else {
orgRefDelta.addValueToDelete(orgCanonical);
focusContext.swallowToProjectionWaveSecondaryDelta(orgRefDelta);
}
}
}

} else { // if reconciliation is requested, we recreate parentOrgRef from scratch

LOGGER.trace("Reconciliation requested, collecting all non-negative values");

ItemDelta orgRefDelta = orgRefDef.createEmptyDelta(orgRefPath);
Set<PrismReferenceValue> valuesToReplace = new HashSet<>();

for (EvaluatedAssignment assignment : evaluatedAssignmentTriple.getNonNegativeValues()) {
Collection<PrismReferenceValue> orgs = assignment.getOrgRefVals();
for (PrismReferenceValue org : orgs) {
PrismReferenceValue canonical = org.toCannonical();
valuesToReplace.add(canonical); // if valuesToReplace would be a list, we should check for duplicates!
}
}
orgRefDelta.setValuesToReplace(valuesToReplace);
focusContext.swallowToProjectionWaveSecondaryDelta(orgRefDelta);
}
}

public <F extends ObjectType> void checkForAssignmentConflicts(LensContext<F> context,
Expand Down
Expand Up @@ -296,6 +296,7 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra
protected static final String ORG_GOVERNOR_OFFICE_OID = "00000000-8888-6666-0000-100000000001";
protected static final String ORG_SCUMM_BAR_OID = "00000000-8888-6666-0000-100000000006";
protected static final String ORG_MINISTRY_OF_OFFENSE_OID = "00000000-8888-6666-0000-100000000003";
protected static final String ORG_MINISTRY_OF_DEFENSE_OID = "00000000-8888-6666-0000-100000000002";
protected static final String ORG_MINISTRY_OF_RUM_OID = "00000000-8888-6666-0000-100000000004";
protected static final String ORG_SWASHBUCKLER_SECTION_OID = "00000000-8888-6666-0000-100000000005";
protected static final String ORG_PROJECT_ROOT_OID = "00000000-8888-6666-0000-200000000000";
Expand Down

0 comments on commit 38aed86

Please sign in to comment.