Skip to content

Commit

Permalink
Assignment conditions fixed, more tests, diag improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Jul 31, 2014
1 parent 1c57aa0 commit c93a8ee
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 16 deletions.
Expand Up @@ -32,6 +32,7 @@
import com.evolveum.midpoint.schema.util.ObjectResolver;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
Expand Down Expand Up @@ -65,6 +66,7 @@ public class ScriptExpression {
private Collection<FunctionLibrary> functions;

private static final Trace LOGGER = TraceManager.getTrace(ScriptExpression.class);
private static final int MAX_CODE_CHARS = 42;

ScriptExpression(ScriptEvaluator evaluator, ScriptExpressionEvaluatorType scriptType) {
this.scriptType = scriptType;
Expand Down Expand Up @@ -166,7 +168,7 @@ private String formatVariables(ExpressionVariables variables) {
}

private String formatCode() {
return scriptType.getCode();
return DebugUtil.excerpt(scriptType.getCode().replaceAll("[\\s\\r\\n]+", " "), MAX_CODE_CHARS);
}

public ItemPath parsePath(String path) {
Expand All @@ -184,4 +186,9 @@ public ItemPath parsePath(String path) {
// return xPathHolder.toItemPath();
}

@Override
public String toString() {
return "ScriptExpression(" + formatCode() + ")";
}

}
Expand Up @@ -255,17 +255,22 @@ private void evaluateAssignment(EvaluatedAssignment<F> evalAssignment, Assignmen

MappingType conditionType = assignmentType.getCondition();
if (conditionType != null) {
PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> conditionTriple = evaluateMappingAsCondition(conditionType, source, task, result);
PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> conditionTriple = evaluateMappingAsCondition(conditionType,
assignmentType, source, task, result);
boolean condOld = ExpressionUtil.computeConditionResult(conditionTriple.getNonPositiveValues());
boolean condNew = ExpressionUtil.computeConditionResult(conditionTriple.getNonNegativeValues());
PlusMinusZero condMode = ExpressionUtil.computeConditionResultMode(condOld, condNew);
if (condMode == null || (condMode == PlusMinusZero.ZERO && !condNew)) {
LOGGER.trace("Skipping evaluation of "+assignmentType+" because of condition result");
LOGGER.trace("Skipping evaluation of "+assignmentType+" because of condition result ({} -> {}: {})",
new Object[]{ condOld, condNew, condMode });
assignmentPath.remove(assignmentPathSegment);
evalAssignment.setValid(false);
return;
}
PlusMinusZero origMode = mode;
mode = PlusMinusZero.compute(mode, condMode);
LOGGER.trace("Evaluated condition in assignment {} -> {}: {} + {} = {}", new Object[]{
condOld, condNew, origMode, condMode, mode });
}

boolean isValid = LensUtil.isValid(assignmentType, now, activationComputer);
Expand Down Expand Up @@ -426,15 +431,21 @@ private boolean evaluateAbstractRole(EvaluatedAssignment<F> assignment, Assignme

MappingType conditionType = roleType.getCondition();
if (conditionType != null) {
PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> conditionTriple = evaluateMappingAsCondition(conditionType, source, task, result);
PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> conditionTriple = evaluateMappingAsCondition(conditionType,
null, source, task, result);
boolean condOld = ExpressionUtil.computeConditionResult(conditionTriple.getNonPositiveValues());
boolean condNew = ExpressionUtil.computeConditionResult(conditionTriple.getNonNegativeValues());
PlusMinusZero condMode = ExpressionUtil.computeConditionResultMode(condOld, condNew);
if (condMode == null || (condMode == PlusMinusZero.ZERO && !condNew)) {
LOGGER.trace("Skipping evaluation of "+roleType+" because of condition result");
LOGGER.trace("Skipping evaluation of "+roleType+" because of condition result ({} -> {}: {})",
new Object[]{ condOld, condNew, condMode });
return false;
}
PlusMinusZero origMode = mode;
mode = PlusMinusZero.compute(mode, condMode);
LOGGER.trace("Evaluated condition in {}: {} -> {}: {} + {} = {}", new Object[]{
roleType, condOld, condNew, origMode, condMode, mode });

}

int evaluationOrder = assignmentPath.getEvaluationOrder();
Expand Down Expand Up @@ -560,9 +571,16 @@ private void checkSchema(AssignmentType assignmentType, String sourceDescription
}
}

public PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> evaluateMappingAsCondition(MappingType conditionType, ObjectType source, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
public PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> evaluateMappingAsCondition(MappingType conditionType,
AssignmentType sourceAssignment, ObjectType source, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
String desc;
if (sourceAssignment == null) {
desc = "condition in " + source;
} else {
desc = "condition in assignment in " + source;
}
Mapping<? extends PrismPropertyValue<Boolean>> mapping = mappingFactory.createMapping(conditionType,
"condition in " + source);
desc);

mapping.addVariableDefinition(ExpressionConstants.VAR_USER, focusOdo);
mapping.addVariableDefinition(ExpressionConstants.VAR_FOCUS, focusOdo);
Expand Down
Expand Up @@ -127,8 +127,20 @@ public String debugDump() {
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.debugDumpLabel(sb, "AssignmentPath", indent);
sb.append("\n");
DebugUtil.debugDump(segments, indent + 1);
if (segments == null || segments.isEmpty()) {
sb.append(" (empty)");
} else {
sb.append(" (").append(segments.size()).append(")");
if (DebugUtil.isDetailedDebugDump()) {
DebugUtil.debugDump(sb, segments, indent + 1, false);
} else {
for (AssignmentPathSegment segment: segments) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 1);
sb.append(segment.toString());
}
}
}
return sb.toString();
}

Expand Down
Expand Up @@ -546,7 +546,7 @@ public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.debugDumpLabel(sb, "Construction", indent);
if (refinedObjectClassDefinition == null) {
sb.append("null");
sb.append(" (no object class definition)");
} else {
sb.append(refinedObjectClassDefinition.getShadowDiscriminator());
}
Expand All @@ -566,8 +566,10 @@ public String debugDump(int indent) {
sb.append(mapping.debugDump(indent+2));
}
}
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "assignmentPath", assignmentPath, indent + 1);
if (assignmentPath != null) {
sb.append("\n");
sb.append(assignmentPath.debugDump(indent+1));
}
return sb.toString();
}

Expand Down
Expand Up @@ -1065,6 +1065,32 @@ public void test540JackAssignRoleWannabe() throws Exception {
result.computeStatus();
TestUtil.assertSuccess(result);

assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result);
assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME);
}

/**
* Remove honorifixSuffix. This triggers a condition in Wannabe role inducement.
* But as the whole role has false condition nothing should happen.
*/
@Test
public void test541JackRemoveHonorificSuffixWannabe() throws Exception {
final String TEST_NAME = "test541JackRemoveHonorificSuffixWannabe";
TestUtil.displayTestTile(this, TEST_NAME);
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);

Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

// WHEN
TestUtil.displayWhen(TEST_NAME);
modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_SUFFIX, task, result);

// THEN
TestUtil.displayThen(TEST_NAME);
result.computeStatus();
TestUtil.assertSuccess(result);

assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result);
assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME);
}
Expand All @@ -1073,8 +1099,8 @@ public void test540JackAssignRoleWannabe() throws Exception {
* Modify employeeType. This triggers a condition in Wannabe role.
*/
@Test
public void test541JackModifyEmployeeTypeWannabe() throws Exception {
final String TEST_NAME = "test541JackModifyEmployeeTypeWannabe";
public void test542JackModifyEmployeeTypeWannabe() throws Exception {
final String TEST_NAME = "test542JackModifyEmployeeTypeWannabe";
TestUtil.displayTestTile(this, TEST_NAME);
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);

Expand All @@ -1095,6 +1121,86 @@ public void test541JackModifyEmployeeTypeWannabe() throws Exception {
assertDefaultDummyAccountAttribute(ACCOUNT_JACK_DUMMY_USERNAME, "title", "Wannabe Cpt. Where's the rum?");
}

/**
* Remove honorifixPrefix. This triggers a condition in Wannabe role and should remove an account.
*/
@Test
public void test543JackRemoveHonorificPrefixWannabe() throws Exception {
final String TEST_NAME = "test543JackRemoveHonorificPrefixWannabe";
TestUtil.displayTestTile(this, TEST_NAME);
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);

Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

// WHEN
TestUtil.displayWhen(TEST_NAME);
modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_PREFIX, task, result);

// THEN
TestUtil.displayThen(TEST_NAME);
result.computeStatus();
TestUtil.assertSuccess(result);

assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result);
assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME);
}

/**
* Set honorifixSuffix. This triggers conditions and adds a sub-role Honorable Wannabe.
*/
@Test
public void test544JackSetHonorificSuffixWannabe() throws Exception {
final String TEST_NAME = "test544JackSetHonorificSuffixWannabe";
TestUtil.displayTestTile(this, TEST_NAME);
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);

Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

// WHEN
TestUtil.displayWhen(TEST_NAME);
modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_SUFFIX, task, result,
PrismTestUtil.createPolyString("PhD."));

// THEN
TestUtil.displayThen(TEST_NAME);
result.computeStatus();
TestUtil.assertSuccess(result);

assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result);
assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true);
assertDefaultDummyAccountAttribute(ACCOUNT_JACK_DUMMY_USERNAME,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_QUOTE_NAME, "Arr!", "Whatever. -- jack");
}

/**
* Restore honorifixPrefix. The title should be replaced again.
*/
@Test
public void test545JackRestoreHonorificPrefixWannabe() throws Exception {
final String TEST_NAME = "test545JackRestoreHonorificPrefixWannabe";
TestUtil.displayTestTile(this, TEST_NAME);
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);

Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

// WHEN
TestUtil.displayWhen(TEST_NAME);
modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_PREFIX, task, result,
PrismTestUtil.createPolyString("captain"));

// THEN
TestUtil.displayThen(TEST_NAME);
result.computeStatus();
TestUtil.assertSuccess(result);

assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result);
assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true);
assertDefaultDummyAccountAttribute(ACCOUNT_JACK_DUMMY_USERNAME, "title", "Wannabe captain Where's the rum?");
}

/**
* The account should be gone - regardless of the condition state.
*/
Expand Down
3 changes: 1 addition & 2 deletions model/model-intest/src/test/resources/common/user-jack.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2013 Evolveum
~ Copyright (c) 2010-2014 Evolveum
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,7 +33,6 @@
<familyName>Sparrow</familyName>
<additionalName>Jackie</additionalName>
<honorificPrefix>Cpt.</honorificPrefix>

<honorificSuffix>PhD.</honorificSuffix>
<emailAddress>jack.sparrow@evolveum.com</emailAddress>
<telephoneNumber>555-1234</telephoneNumber>
Expand Down
1 change: 1 addition & 0 deletions model/model-intest/src/test/resources/logback-test.xml
Expand Up @@ -50,6 +50,7 @@
<logger name="com.evolveum.midpoint.model.impl.lens.ChangeExecutor" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.lens.ShadowConstraintsChecker" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.lens.LensUtil" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.lens.AssignmentEvaluator" level="TRACE" />
<logger name="com.evolveum.midpoint.model.impl.expr" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.util" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.sync" level="DEBUG" />
Expand Down

0 comments on commit c93a8ee

Please sign in to comment.