Skip to content

Commit

Permalink
"Assignment modification" constraint + preliminary support in approvals.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Oct 10, 2017
1 parent 63b2e4e commit 41b6fd4
Show file tree
Hide file tree
Showing 13 changed files with 428 additions and 219 deletions.
Expand Up @@ -1624,16 +1624,27 @@ public ObjectDelta<T> subtract(@NotNull Collection<ItemPath> paths) {
return rv;
}

public static class FactorOutResult<T extends Objectable> {
public static class FactorOutResultMulti<T extends Objectable> {
public final ObjectDelta<T> remainder;
public final List<ObjectDelta<T>> offsprings = new ArrayList<>();

public FactorOutResult(ObjectDelta<T> remainder) {
public FactorOutResultMulti(ObjectDelta<T> remainder) {
this.remainder = remainder;
}
}

public FactorOutResult<T> factorOut(Collection<ItemPath> paths, boolean cloneDelta) {
public static class FactorOutResultSingle<T extends Objectable> {
public final ObjectDelta<T> remainder;
public final ObjectDelta<T> offspring;

public FactorOutResultSingle(ObjectDelta<T> remainder, ObjectDelta<T> offspring) {
this.remainder = remainder;
this.offspring = offspring;
}
}

@NotNull
public FactorOutResultSingle<T> factorOut(Collection<ItemPath> paths, boolean cloneDelta) {
if (isAdd()) {
return factorOutForAddDelta(paths, cloneDelta);
} else if (isDelete()) {
Expand All @@ -1643,7 +1654,8 @@ public FactorOutResult<T> factorOut(Collection<ItemPath> paths, boolean cloneDel
}
}

public FactorOutResult<T> factorOutValues(ItemPath path, boolean cloneDelta) throws SchemaException {
@NotNull
public FactorOutResultMulti<T> factorOutValues(ItemPath path, boolean cloneDelta) throws SchemaException {
if (isAdd()) {
return factorOutValuesForAddDelta(path, cloneDelta);
} else if (isDelete()) {
Expand All @@ -1662,9 +1674,9 @@ public FactorOutResult<T> factorOutValues(ItemPath path, boolean cloneDelta) thr
* involving splitting value-to-be-added into remainder and offspring delta. It's probably doable,
* but some conditions would have to be met, e.g. inducement to be added must have an ID.
*/
private FactorOutResult<T> factorOutForModifyDelta(Collection<ItemPath> paths, boolean cloneDelta) {
private FactorOutResultSingle<T> factorOutForModifyDelta(Collection<ItemPath> paths, boolean cloneDelta) {
ObjectDelta<T> remainder = cloneIfRequested(cloneDelta);
FactorOutResult<T> rv = new FactorOutResult<>(remainder);
ObjectDelta<T> offspring = null;
List<ItemDelta<?, ?>> modificationsFound = new ArrayList<>();
for (Iterator<? extends ItemDelta<?, ?>> iterator = remainder.modifications.iterator(); iterator.hasNext(); ) {
ItemDelta<?, ?> modification = iterator.next();
Expand All @@ -1674,14 +1686,13 @@ private FactorOutResult<T> factorOutForModifyDelta(Collection<ItemPath> paths, b
}
}
if (!modificationsFound.isEmpty()) {
ObjectDelta<T> offspring = new ObjectDelta<>(objectTypeClass, ChangeType.MODIFY, prismContext);
offspring = new ObjectDelta<>(objectTypeClass, ChangeType.MODIFY, prismContext);
modificationsFound.forEach(offspring::addModification);
rv.offsprings.add(offspring);
}
return rv;
return new FactorOutResultSingle<>(remainder, offspring);
}

private FactorOutResult<T> factorOutForAddDelta(Collection<ItemPath> paths, boolean cloneDelta) {
private FactorOutResultSingle<T> factorOutForAddDelta(Collection<ItemPath> paths, boolean cloneDelta) {
List<Item<?, ?>> itemsFound = new ArrayList<>();
for (ItemPath path : paths) {
Item<?, ?> item = objectToAdd.findItem(path);
Expand All @@ -1690,17 +1701,15 @@ private FactorOutResult<T> factorOutForAddDelta(Collection<ItemPath> paths, bool
}
}
if (itemsFound.isEmpty()) {
return new FactorOutResult<>(this);
return new FactorOutResultSingle<>(this, null);
}
ObjectDelta<T> remainder = cloneIfRequested(cloneDelta);
FactorOutResult<T> rv = new FactorOutResult<>(remainder);
ObjectDelta<T> offspring = new ObjectDelta<>(objectTypeClass, ChangeType.MODIFY, prismContext);
for (Item<?, ?> item : itemsFound) {
remainder.getObjectToAdd().remove(item);
offspring.addModification(ItemDelta.createAddDeltaFor(item));
}
rv.offsprings.add(offspring);
return rv;
return new FactorOutResultSingle<>(remainder, offspring);
}

private ObjectDelta<T> cloneIfRequested(boolean cloneDelta) {
Expand All @@ -1716,9 +1725,9 @@ private ObjectDelta<T> cloneIfRequested(boolean cloneDelta) {
* involving splitting value-to-be-added into remainder and offspring delta. It's probably doable,
* but some conditions would have to be met, e.g. inducement to be added must have an ID.
*/
private FactorOutResult<T> factorOutValuesForModifyDelta(ItemPath path, boolean cloneDelta) throws SchemaException {
private FactorOutResultMulti<T> factorOutValuesForModifyDelta(ItemPath path, boolean cloneDelta) throws SchemaException {
ObjectDelta<T> remainder = cloneIfRequested(cloneDelta);
FactorOutResult<T> rv = new FactorOutResult<>(remainder);
FactorOutResultMulti<T> rv = new FactorOutResultMulti<>(remainder);

MultiValuedMap<Long, ItemDelta<?, ?>> modificationsForId = new ArrayListValuedHashMap<>();
PrismObjectDefinition<T> objDef = objectTypeClass != null ? prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(objectTypeClass) : null;
Expand Down Expand Up @@ -1766,7 +1775,7 @@ private FactorOutResult<T> factorOutValuesForModifyDelta(ItemPath path, boolean
return rv;
}

private ItemDelta createNewDelta(FactorOutResult<T> rv, ItemDelta<?, ?> modification)
private ItemDelta createNewDelta(FactorOutResultMulti<T> rv, ItemDelta<?, ?> modification)
throws SchemaException {
ObjectDelta<T> offspring = new ObjectDelta<>(objectTypeClass, ChangeType.MODIFY, prismContext);
ItemDelta delta = modification.getDefinition().instantiate().createDelta(modification.getPath());
Expand All @@ -1775,14 +1784,14 @@ private ItemDelta createNewDelta(FactorOutResult<T> rv, ItemDelta<?, ?> modifica
return delta;
}

private FactorOutResult<T> factorOutValuesForAddDelta(ItemPath path, boolean cloneDelta) {
private FactorOutResultMulti<T> factorOutValuesForAddDelta(ItemPath path, boolean cloneDelta) {
Item<?, ?> item = objectToAdd.findItem(path);
if (item == null || item.isEmpty()) {
return new FactorOutResult<>(this);
return new FactorOutResultMulti<>(this);
}
ObjectDelta<T> remainder = cloneIfRequested(cloneDelta);
remainder.getObjectToAdd().remove(item);
FactorOutResult<T> rv = new FactorOutResult<>(remainder);
FactorOutResultMulti<T> rv = new FactorOutResultMulti<>(remainder);
for (PrismValue value : item.getValues()) {
ObjectDelta<T> offspring = new ObjectDelta<>(objectTypeClass, ChangeType.MODIFY, prismContext);
offspring.addModification(ItemDelta.createAddDeltaFor(item, value));
Expand Down
Expand Up @@ -62,7 +62,7 @@ public void testAssignmentSameNullIdApplyToObject() throws Exception {
PrismObject<UserType> user = PrismTestUtil.parseObject(USER_JACK_FILE);

//Delta
PrismContainerValue<AssignmentType> assignmentValue = new PrismContainerValue<AssignmentType>(getPrismContext());
PrismContainerValue<AssignmentType> assignmentValue = new PrismContainerValue<>(getPrismContext());
// The value id is null
assignmentValue.setPropertyRealValue(AssignmentType.F_DESCRIPTION, "jamalalicha patlama paprtala", getPrismContext());

Expand Down Expand Up @@ -91,7 +91,7 @@ public void testAddInducementConstructionSameNullIdApplyToObject() throws Except
PrismObject<RoleType> role = PrismTestUtil.parseObject(ROLE_CONSTRUCTION_FILE);

//Delta
PrismContainerValue<AssignmentType> inducementValue = new PrismContainerValue<AssignmentType>(getPrismContext());
PrismContainerValue<AssignmentType> inducementValue = new PrismContainerValue<>(getPrismContext());
// The value id is null
inducementValue.setPropertyRealValue(AssignmentType.F_DESCRIPTION, "jamalalicha patlama paprtala", getPrismContext());

Expand Down Expand Up @@ -328,7 +328,7 @@ public void testSubtractAssignmentFromAddDelta() throws Exception {
// WHEN
PrismContainerDefinition<AssignmentType> assignmentDef = PrismTestUtil.getSchemaRegistry()
.findContainerDefinitionByCompileTimeClass(AssignmentType.class).clone();
((PrismContainerDefinitionImpl) assignmentDef).setMaxOccurs(1);
assignmentDef.setMaxOccurs(1);
PrismContainer<AssignmentType> assignmentContainer = assignmentDef.instantiate();

PrismContainerValue<AssignmentType> assignmentValue =
Expand Down Expand Up @@ -360,14 +360,14 @@ public void testSubtractAssignmentFromModifyDelta() throws Exception {
user.asObjectable().getAssignment().get(0).setId(9999L);
AssignmentType assignment9999 = new AssignmentType();
assignment9999.setId(9999L);
ObjectDelta<UserType> delta = (ObjectDelta<UserType>) DeltaBuilder.deltaFor(UserType.class, getPrismContext())
ObjectDelta<UserType> delta = DeltaBuilder.deltaFor(UserType.class, getPrismContext())
.item(UserType.F_ASSIGNMENT).delete(assignment9999)
.asObjectDelta(user.getOid());
.asObjectDeltaCast(user.getOid());

// WHEN
PrismContainerDefinition<AssignmentType> assignmentDef = PrismTestUtil.getSchemaRegistry()
.findContainerDefinitionByCompileTimeClass(AssignmentType.class).clone();
((PrismContainerDefinitionImpl) assignmentDef).setMaxOccurs(1);
assignmentDef.setMaxOccurs(1);
PrismContainer<AssignmentType> assignmentContainer = assignmentDef.instantiate();

PrismContainerValue<AssignmentType> assignmentValue =
Expand Down Expand Up @@ -401,18 +401,18 @@ public void testFactorAddDeltaForItem() throws Exception {
ObjectDelta<UserType> addDelta = ObjectDelta.createAddDelta(user);

// WHEN
ObjectDelta.FactorOutResult<UserType> out = addDelta.factorOut(singleton(new ItemPath(UserType.F_ASSIGNMENT)), true);
ObjectDelta.FactorOutResultSingle<UserType> out = addDelta.factorOut(singleton(new ItemPath(UserType.F_ASSIGNMENT)), true);

// THEN
System.out.println("Delta before factorOut:\n" + addDelta.debugDump() + "\n");
System.out.println("Delta after factorOut:\n" + out.remainder.debugDump() + "\n");
System.out.println("Offspring deltas:\n" + DebugUtil.debugDump(out.offsprings) + "\n");
System.out.println("Offspring delta:\n" + DebugUtil.debugDump(out.offspring) + "\n");

assertTrue("Remaining delta is not an ADD delta", out.remainder.isAdd());
assertEquals("Wrong # of remaining assignments", 0, out.remainder.getObjectToAdd().asObjectable().getAssignment().size());
assertEquals("Wrong # of offspring deltas", 1, out.offsprings.size());
assertEquals("Wrong # of modifications in offspring", 1, out.offsprings.get(0).getModifications().size());
assertEquals("Wrong # of assignments to add", 3, out.offsprings.get(0).getModifications().iterator().next().getValuesToAdd().size());
assertNotNull("Missing offspring delta", out.offspring);
assertEquals("Wrong # of modifications in offspring", 1, out.offspring.getModifications().size());
assertEquals("Wrong # of assignments to add", 3, out.offspring.getModifications().iterator().next().getValuesToAdd().size());
}

// subtract of single-valued PCV from multivalued one
Expand All @@ -426,17 +426,17 @@ public void testFactorAddDeltaForItems() throws Exception {
ObjectDelta<UserType> addDelta = ObjectDelta.createAddDelta(user);

// WHEN
ObjectDelta.FactorOutResult<UserType> out = addDelta.factorOut(asList(new ItemPath(UserType.F_GIVEN_NAME), new ItemPath(UserType.F_FAMILY_NAME)), true);
ObjectDelta.FactorOutResultSingle<UserType> out = addDelta.factorOut(asList(new ItemPath(UserType.F_GIVEN_NAME), new ItemPath(UserType.F_FAMILY_NAME)), true);

// THEN
System.out.println("Delta before factorOut:\n" + addDelta.debugDump() + "\n");
System.out.println("Delta after factorOut:\n" + out.remainder.debugDump() + "\n");
System.out.println("Offspring deltas:\n" + DebugUtil.debugDump(out.offsprings) + "\n");
System.out.println("Offspring delta:\n" + DebugUtil.debugDump(out.offspring) + "\n");

assertTrue("Remaining delta is not an ADD delta", out.remainder.isAdd());
assertEquals("Wrong # of remaining assignments", 3, out.remainder.getObjectToAdd().asObjectable().getAssignment().size());
assertEquals("Wrong # of offspring deltas", 1, out.offsprings.size());
assertEquals("Wrong # of modifications in offspring", 2, out.offsprings.get(0).getModifications().size());
assertNotNull("Missing offspring delta", out.offspring);
assertEquals("Wrong # of modifications in offspring", 2, out.offspring.getModifications().size());
}

@Test
Expand All @@ -449,7 +449,7 @@ public void testFactorAddDeltaForItemValues() throws Exception {
ObjectDelta<UserType> addDelta = ObjectDelta.createAddDelta(user);

// WHEN
ObjectDelta.FactorOutResult<UserType> out = addDelta.factorOutValues(new ItemPath(UserType.F_ASSIGNMENT), true);
ObjectDelta.FactorOutResultMulti<UserType> out = addDelta.factorOutValues(new ItemPath(UserType.F_ASSIGNMENT), true);

// THEN
System.out.println("Delta before factorOut:\n" + addDelta.debugDump() + "\n");
Expand Down Expand Up @@ -480,17 +480,17 @@ public void testFactorModifyDeltaForItem() throws Exception {
.asObjectDeltaCast("oid1");

// WHEN
ObjectDelta.FactorOutResult<UserType> out = delta.factorOut(singleton(new ItemPath(UserType.F_ASSIGNMENT)), true);
ObjectDelta.FactorOutResultSingle<UserType> out = delta.factorOut(singleton(new ItemPath(UserType.F_ASSIGNMENT)), true);

// THEN
System.out.println("Delta before operation:\n" + delta.debugDump() + "\n");
System.out.println("Delta after factorOut:\n" + out.remainder.debugDump() + "\n");
System.out.println("Offspring deltas:\n" + DebugUtil.debugDump(out.offsprings) + "\n");
System.out.println("Offspring delta:\n" + DebugUtil.debugDump(out.offspring) + "\n");

assertTrue("Remaining delta is not a MODIFY delta", out.remainder.isModify());
assertEquals("Wrong # of remaining modifications", 1, out.remainder.getModifications().size());
assertEquals("Wrong # of offspring deltas", 1, out.offsprings.size());
assertEquals("Wrong # of modifications in offspring 0", 2, out.offsprings.get(0).getModifications().size());
assertNotNull("Missing offspring delta", out.offspring);
assertEquals("Wrong # of modifications in offspring 0", 2, out.offspring.getModifications().size());
}

@Test
Expand All @@ -510,7 +510,7 @@ public void testFactorModifyDeltaForItemValues() throws Exception {
.asObjectDeltaCast("oid1");

// WHEN
ObjectDelta.FactorOutResult<UserType> out = delta.factorOutValues(new ItemPath(UserType.F_ASSIGNMENT), true);
ObjectDelta.FactorOutResultMulti<UserType> out = delta.factorOutValues(new ItemPath(UserType.F_ASSIGNMENT), true);

// THEN
System.out.println("Delta before operation:\n" + delta.debugDump() + "\n");
Expand Down
Expand Up @@ -33,12 +33,13 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public interface EvaluatedAssignment<F extends FocusType> extends DebugDumpable {

AssignmentType getAssignmentType();

Long getAssignmentId();

Collection<Authorization> getAuthorizations();

Collection<AdminGuiConfigurationType> getAdminGuiConfigurations();
Expand Down
Expand Up @@ -105,6 +105,12 @@ public AssignmentType getAssignmentType() {
return asContainerable(assignmentIdi.getSingleValue(evaluatedOld));
}

@Override
public Long getAssignmentId() {
Item<PrismContainerValue<AssignmentType>, PrismContainerDefinition<AssignmentType>> any = assignmentIdi.getAnyItem();
return any != null && !any.getValues().isEmpty() ? any.getValue(0).getId() : null;
}

@Override
public AssignmentType getAssignmentType(boolean old) {
return asContainerable(assignmentIdi.getSingleValue(old));
Expand Down
Expand Up @@ -72,12 +72,12 @@ public class PolicyRuleProcessor {
@Autowired private MappingEvaluator mappingEvaluator;
@Autowired private PolicyStateRecorder policyStateRecorder;

@Autowired private AssignmentConstraintEvaluator assignmentConstraintEvaluator;
@Autowired private AssignmentModificationConstraintEvaluator assignmentConstraintEvaluator;
@Autowired private HasAssignmentConstraintEvaluator hasAssignmentConstraintEvaluator;
@Autowired private ExclusionConstraintEvaluator exclusionConstraintEvaluator;
@Autowired private MultiplicityConstraintEvaluator multiplicityConstraintEvaluator;
@Autowired private PolicySituationConstraintEvaluator policySituationConstraintEvaluator;
@Autowired private ModificationConstraintEvaluator modificationConstraintEvaluator;
@Autowired private ObjectModificationConstraintEvaluator modificationConstraintEvaluator;
@Autowired private StateConstraintEvaluator stateConstraintEvaluator;
@Autowired private CompositeConstraintEvaluator compositeConstraintEvaluator;
@Autowired private TransitionConstraintEvaluator transitionConstraintEvaluator;
Expand Down

0 comments on commit 41b6fd4

Please sign in to comment.