Skip to content

Commit

Permalink
Some delta fixes (+tests). Storing iteration and iterationToken in fo…
Browse files Browse the repository at this point in the history
…cus.
  • Loading branch information
semancik committed Mar 31, 2014
1 parent 2042230 commit 6c8d0cd
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 66 deletions.
Expand Up @@ -40,6 +40,7 @@
import com.evolveum.midpoint.prism.path.IdItemPathSegment;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ItemPath.CompareResult;
import com.evolveum.midpoint.prism.path.ItemPathSegment;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
Expand Down Expand Up @@ -95,7 +96,11 @@ public ItemDelta(ItemPath path, ItemDefinition itemDefinition) {
if (path.isEmpty()) {
this.elementName = null;
} else {
this.elementName = ((NameItemPathSegment)path.last()).getName();
ItemPathSegment last = path.last();
if (!(last instanceof NameItemPathSegment)) {
throw new IllegalArgumentException("Invalid delta path "+path+". Delta path must always point to item, not to value");
}
this.elementName = ((NameItemPathSegment)last).getName();
this.parentPath = path.allExceptLast();
}
this.definition = itemDefinition;
Expand Down
Expand Up @@ -884,17 +884,6 @@ public static <O extends Objectable, C extends Containerable> ObjectDelta<O> cre
return createModificationDeleteContainer(type, oid, new ItemPath(containerName), prismContext, containerValues);
}

/**
* Supposed to work with containers that are completely identified by path (container ID present in path).
*/
public static <O extends Objectable, C extends Containerable> ObjectDelta<O> createModificationDeleteContainer(Class<O> type, String oid, ItemPath containerPath,
PrismContext prismContext) {
ObjectDelta<O> objectDelta = new ObjectDelta<O>(type, ChangeType.MODIFY, prismContext);
objectDelta.setOid(oid);
fillInModificationDeleteContainer(objectDelta, containerPath);
return objectDelta;
}

public static <O extends Objectable, C extends Containerable> ObjectDelta<O> createModificationDeleteContainer(Class<O> type, String oid, ItemPath containerPath,
PrismContext prismContext, PrismContainerValue<C>... containerValues) {
ObjectDelta<O> objectDelta = new ObjectDelta<O>(type, ChangeType.MODIFY, prismContext);
Expand All @@ -903,6 +892,11 @@ public static <O extends Objectable, C extends Containerable> ObjectDelta<O> cre
return objectDelta;
}

public static <O extends Objectable, C extends Containerable> ObjectDelta<O> createModificationDeleteContainer(Class<O> type, String oid,
QName containerName, PrismContext prismContext, C... containerValues) throws SchemaException {
return createModificationDeleteContainer(type, oid, new ItemPath(containerName), prismContext, containerValues);
}

public static <O extends Objectable, C extends Containerable> ObjectDelta<O> createModificationDeleteContainer(Class<O> type, String oid,
ItemPath propertyPath, PrismContext prismContext, C... containerValues) throws SchemaException {
ObjectDelta<O> objectDelta = new ObjectDelta<O>(type, ChangeType.MODIFY, prismContext);
Expand Down
Expand Up @@ -25,6 +25,7 @@

import com.evolveum.midpoint.prism.delta.*;
import com.evolveum.prism.xml.ns._public.types_2.ObjectReferenceType;

import org.testng.AssertJUnit;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
Expand Down Expand Up @@ -58,6 +59,57 @@ public void setupDebug() throws SchemaException, SAXException, IOException {
PrismTestUtil.resetPrismContext(new PrismInternalTestUtil());
}

@Test
public void testDeltaPaths() throws Exception {
System.out.println("\n\n===[ testDeltaPaths ]===\n");

PrismPropertyDefinition<String> descDefinition = new PrismPropertyDefinition<>(UserType.F_DESCRIPTION,
DOMUtil.XSD_STRING, PrismTestUtil.getPrismContext());
PropertyDelta<String> delta1 = new PropertyDelta<String>(descDefinition);
delta1.addValueToAdd(new PrismPropertyValue<String>("add1"));
assertPath(delta1, new ItemPath(UserType.F_DESCRIPTION));

PrismReferenceDefinition referenceDefinition = new PrismReferenceDefinition(UserType.F_PARENT_ORG_REF,
OBJECT_REFERENCE_TYPE_QNAME, PrismTestUtil.getPrismContext());
ReferenceDelta delta2 = new ReferenceDelta(referenceDefinition);
delta2.addValueToAdd(new PrismReferenceValue("oid1"));
assertPath(delta2, new ItemPath(UserType.F_PARENT_ORG_REF));

PrismContainerValue<AssignmentType> assignmentValue1 = new PrismContainerValue<AssignmentType>();
// The value id is null
assignmentValue1.setPropertyRealValue(AssignmentType.F_DESCRIPTION, "jamalalicha patlama paprtala");
ObjectDelta<UserType> assObjDelta1 = ObjectDelta.createModificationAddContainer(UserType.class, USER_FOO_OID,
UserType.F_ASSIGNMENT, PrismTestUtil.getPrismContext(), assignmentValue1);
ItemDelta<?> assDelta1 = assObjDelta1.getModifications().iterator().next();
assertPath(assDelta1, new ItemPath(UserType.F_ASSIGNMENT));

PrismContainerValue<AssignmentType> assignmentValue2 = new PrismContainerValue<AssignmentType>();
assignmentValue1.setId(USER_ASSIGNMENT_1_ID);
assignmentValue1.setPropertyRealValue(AssignmentType.F_DESCRIPTION, "jamalalicha patlama paprtala");
ObjectDelta<UserType> assObjDelta2 = ObjectDelta.createModificationAddContainer(UserType.class, USER_FOO_OID,
UserType.F_ASSIGNMENT, PrismTestUtil.getPrismContext(), assignmentValue2);
ItemDelta<?> assDelta2 = assObjDelta2.getModifications().iterator().next();
assertPath(assDelta2, new ItemPath(UserType.F_ASSIGNMENT));

PrismPropertyDefinition<String> assDescDefinition = new PrismPropertyDefinition<>(AssignmentType.F_DESCRIPTION,
DOMUtil.XSD_STRING, PrismTestUtil.getPrismContext());
ItemPath itemPathAssDescNoId = new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_DESCRIPTION);
PropertyDelta<String> propDelta2 = new PropertyDelta<String>(itemPathAssDescNoId, descDefinition);
assertPath(propDelta2, itemPathAssDescNoId);

ItemPath itemPathAssDesc1Id = new ItemPath(
new NameItemPathSegment(UserType.F_ASSIGNMENT),
new IdItemPathSegment(USER_ASSIGNMENT_1_ID),
new NameItemPathSegment(AssignmentType.F_DESCRIPTION));
PropertyDelta<String> propDelta3 = new PropertyDelta<String>(itemPathAssDesc1Id, descDefinition);
assertPath(propDelta3, itemPathAssDesc1Id);

}

private void assertPath(ItemDelta<?> delta, ItemPath expectedPath) {
assertEquals("Wrong path in "+delta, expectedPath, delta.getPath());
}

@Test
public void testPropertyDeltaMerge01() throws Exception {
System.out.println("\n\n===[ testPropertyDeltaMerge01 ]===\n");
Expand Down
Expand Up @@ -133,7 +133,7 @@ public void testAddInducementConstructionSameNullIdApplyToObject() throws Except
assertEquals("Unexpected number of inducement values", 2, assignment.size());
}

@Test(enabled=false) // work in progress
@Test
public void testDeleteInducementValidIdSameValueApplyToObject() throws Exception {
final String TEST_NAME = "testDeleteInducementValidIdSameValueApplyToObject";
displayTestTile(TEST_NAME);
Expand All @@ -148,11 +148,9 @@ public void testDeleteInducementValidIdSameValueApplyToObject() throws Exception
construction.setResourceRef(resourceRef);
AssignmentType inducement = new AssignmentType();
inducement.setConstruction(construction);
inducement.setId(ROLE_CONSTRUCTION_INDUCEMENT_ID);
ObjectDelta<RoleType> roleDelta = ObjectDelta.createModificationDeleteContainer(RoleType.class, ROLE_CONSTRUCTION_OID,
new ItemPath(
new NameItemPathSegment(RoleType.F_INDUCEMENT),
new IdItemPathSegment(ROLE_CONSTRUCTION_INDUCEMENT_ID)),
PrismTestUtil.getPrismContext(), inducement);
RoleType.F_INDUCEMENT, PrismTestUtil.getPrismContext(), inducement);

// WHEN
roleDelta.applyTo(role);
Expand All @@ -166,24 +164,19 @@ public void testDeleteInducementValidIdSameValueApplyToObject() throws Exception
assertNull("Unexpected inducement", assignment);
}

@Test(enabled=false) // work in progress
public void testDeleteInducementValidIdNoValueApplyToObject() throws Exception {
final String TEST_NAME = "testDeleteInducementValidIdNoValueApplyToObject";
@Test
public void testDeleteInducementValidIdEmptyValueApplyToObject() throws Exception {
final String TEST_NAME = "testDeleteInducementValidIdEmptyValueApplyToObject";
displayTestTile(TEST_NAME);

// GIVEN
PrismObject<RoleType> role = PrismTestUtil.parseObject(ROLE_CONSTRUCTION_FILE);

//Delta
ConstructionType construction = new ConstructionType();
ObjectReferenceType resourceRef = new ObjectReferenceType();
resourceRef.setOid(ROLE_CONSTRUCTION_RESOURCE_OID);
construction.setResourceRef(resourceRef);
AssignmentType inducement = new AssignmentType();
inducement.setId(ROLE_CONSTRUCTION_INDUCEMENT_ID);
ObjectDelta<RoleType> roleDelta = ObjectDelta.createModificationDeleteContainer(RoleType.class, ROLE_CONSTRUCTION_OID,
new ItemPath(
new NameItemPathSegment(RoleType.F_INDUCEMENT),
new IdItemPathSegment(ROLE_CONSTRUCTION_INDUCEMENT_ID)),
PrismTestUtil.getPrismContext());
RoleType.F_INDUCEMENT, PrismTestUtil.getPrismContext(), inducement);

// WHEN
roleDelta.applyTo(role);
Expand All @@ -197,7 +190,7 @@ public void testDeleteInducementValidIdNoValueApplyToObject() throws Exception {
assertNull("Unexpected inducement", assignment);
}

@Test(enabled=false) // work in progress
@Test
public void testDeleteInducementConstructionSameNullIdApplyToObject() throws Exception {
final String TEST_NAME = "testDeleteInducementConstructionSameNullIdApplyToObject";
displayTestTile(TEST_NAME);
Expand Down
Expand Up @@ -15,6 +15,8 @@
*/
package com.evolveum.midpoint.model.lens.projector;

import static com.evolveum.midpoint.common.InternalsConfig.consistencyChecks;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
Expand All @@ -34,6 +36,8 @@

import com.evolveum.midpoint.common.ActivationComputer;
import com.evolveum.midpoint.common.Clock;
import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition;
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.model.ModelObjectResolver;
import com.evolveum.midpoint.model.api.PolicyViolationException;
import com.evolveum.midpoint.model.common.expression.ExpressionFactory;
Expand All @@ -45,6 +49,7 @@
import com.evolveum.midpoint.model.lens.ItemValueWithOrigin;
import com.evolveum.midpoint.model.lens.LensContext;
import com.evolveum.midpoint.model.lens.LensFocusContext;
import com.evolveum.midpoint.model.lens.LensProjectionContext;
import com.evolveum.midpoint.model.lens.LensUtil;
import com.evolveum.midpoint.prism.ComplexTypeDefinition;
import com.evolveum.midpoint.model.trigger.RecomputeTriggerHandler;
Expand Down Expand Up @@ -286,18 +291,29 @@ private <F extends FocusType> void applyUserTemplate(LensContext<F> context, XML

int maxIterations = LensUtil.determineMaxIterations(userTemplate.getIteration());
int iteration = 0;
String iterationToken = null;
boolean wasResetIterationCounter = false;

ObjectDelta<F> userSecondaryDelta = focusContext.getProjectionWaveSecondaryDelta();
ObjectDelta<F> userPrimaryDelta = focusContext.getProjectionWavePrimaryDelta();
ObjectDeltaObject<F> userOdo = focusContext.getObjectDeltaObject();
PrismObjectDefinition<F> focusDefinition = getFocusDefinition(focusContext.getObjectTypeClass());
Collection<ItemDelta<? extends PrismValue>> itemDeltas = null;
XMLGregorianCalendar nextRecomputeTime = null;

PrismObject<F> focusCurrent = focusContext.getObjectCurrent();
if (focusCurrent != null) {
Integer focusIteration = focusCurrent.asObjectable().getIteration();
if (focusIteration != null) {
iteration = focusIteration;
}
iterationToken = focusCurrent.asObjectable().getIterationToken();
}

while (true) {

ExpressionVariables variables = Utils.getDefaultExpressionVariables(focusContext.getObjectNew(), null, null, null);
String iterationToken = LensUtil.formatIterationToken(context, focusContext,
iterationToken = LensUtil.formatIterationToken(context, focusContext,
userTemplate.getIteration(), iteration, expressionFactory, variables, task, result);

LOGGER.trace("Applying {} to {}, iteration {} ({})",
Expand Down Expand Up @@ -327,7 +343,9 @@ private <F extends FocusType> void applyUserTemplate(LensContext<F> context, XML
LOGGER.trace("Computed triple for {}:\n{}", itemPath, outputTriple.debugDump());
}
ItemDelta<? extends PrismValue> apropriItemDelta = null;
boolean addUnchangedValues = focusContext.isAdd();
// boolean addUnchangedValues = focusContext.isAdd();
// We need to add unchanged values otherwise the unconditional mappings will not be applies
boolean addUnchangedValues = true;
ItemDelta<? extends PrismValue> itemDelta = LensUtil.consolidateTripleToDelta(itemPath, (DeltaSetTriple)outputTriple,
focusDefinition.findItemDefinition(itemPath), apropriItemDelta, userOdo.getNewObject(), null,
addUnchangedValues, true, false, "object template "+userTemplate, true);
Expand Down Expand Up @@ -396,8 +414,16 @@ private <F extends FocusType> void applyUserTemplate(LensContext<F> context, XML
LOGGER.trace("Current focus does not satisfy constraints. Conflicting object: {}; iteration={}, maxIterations={}",
new Object[]{checker.getConflictingObject(), iteration, maxIterations});
conflictMessage = checker.getMessages();

if (iteration != 0 && !wasResetIterationCounter) {
wasResetIterationCounter = true;
iteration = 0;
iterationToken = null;
LOGGER.trace("Resetting iteration counter and token");
continue;
}
}

// Next iteration
iteration++;
iterationToken = null;
Expand Down Expand Up @@ -438,6 +464,8 @@ private <F extends FocusType> void applyUserTemplate(LensContext<F> context, XML
}
}

addIterationTokenDeltas(focusContext, iteration, iterationToken);

if (nextRecomputeTime != null) {

boolean alreadyHasTrigger = false;
Expand Down Expand Up @@ -663,5 +691,35 @@ private PrismContainerDefinition<ActivationType> getActivationDefinition() {
}
return activationDefinition;
}

/**
* Adds deltas for iteration and iterationToken to the focus if needed.
*/
private <F extends FocusType> void addIterationTokenDeltas(LensFocusContext<F> focusContext, int iteration, String iterationToken) throws SchemaException {
PrismObject<F> objectCurrent = focusContext.getObjectCurrent();
if (objectCurrent != null) {
Integer iterationOld = objectCurrent.asObjectable().getIteration();
String iterationTokenOld = objectCurrent.asObjectable().getIterationToken();
if (iterationOld != null && iterationOld == iteration &&
iterationTokenOld != null && iterationTokenOld.equals(iterationToken)) {
// Already stored
return;
}
}
PrismObjectDefinition<F> objDef = focusContext.getObjectDefinition();

PrismPropertyValue<Integer> iterationVal = new PrismPropertyValue<Integer>(iteration);
iterationVal.setOriginType(OriginType.USER_POLICY);
PropertyDelta<Integer> iterationDelta = PropertyDelta.createReplaceDelta(objDef,
FocusType.F_ITERATION, iterationVal);
focusContext.swallowToSecondaryDelta(iterationDelta);

PrismPropertyValue<String> iterationTokenVal = new PrismPropertyValue<String>(iterationToken);
iterationTokenVal.setOriginType(OriginType.USER_POLICY);
PropertyDelta<String> iterationTokenDelta = PropertyDelta.createReplaceDelta(objDef,
FocusType.F_ITERATION_TOKEN, iterationTokenVal);
focusContext.swallowToSecondaryDelta(iterationTokenDelta);

}

}
Expand Up @@ -248,7 +248,7 @@ public void test053ModifyUserBarbossaDisable() throws Exception {
display("Output context", context);

assertTrue(context.getFocusContext().getPrimaryDelta().getChangeType() == ChangeType.MODIFY);
assertEffectiveActivationDeltaOnly(context.getFocusContext().getSecondaryDelta(), "user secondary delta",
assertSideEffectiveDeltasOnly(context.getFocusContext().getSecondaryDelta(), "user secondary delta",
ActivationStatusType.DISABLED);
assertFalse("No account changes", context.getProjectionContexts().isEmpty());

Expand Down Expand Up @@ -339,7 +339,7 @@ private void assignAccountToJackAsync(String testName, boolean serialize) throws
private void assertJackAssignAccountContext(LensContext<UserType> context) {
assertTrue(context.getFocusContext().getPrimaryDelta().getChangeType() == ChangeType.MODIFY);
if (context.getFocusContext().getSecondaryDelta() != null) {
assertEffectiveActivationDeltaOnly(context.getFocusContext().getSecondaryDelta(), "user secondary delta",
assertSideEffectiveDeltasOnly(context.getFocusContext().getSecondaryDelta(), "user secondary delta",
ActivationStatusType.ENABLED);
}
assertFalse("No account changes", context.getProjectionContexts().isEmpty());
Expand Down

0 comments on commit 6c8d0cd

Please sign in to comment.