/* * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.model.impl.lens; import com.evolveum.midpoint.common.Clock; import com.evolveum.midpoint.model.api.context.EvaluationOrder; import com.evolveum.midpoint.model.common.expression.script.ScriptExpressionEvaluationContext; import com.evolveum.midpoint.model.impl.lens.projector.AssignmentProcessor; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PlusMinusZero; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ActivationUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.collections4.Bag; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.bag.TreeBag; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.testng.annotations.Test; import javax.xml.namespace.QName; import java.io.File; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static com.evolveum.midpoint.test.IntegrationTestTools.displayObjectTypeCollection; import static com.evolveum.midpoint.test.util.TestUtil.assertSuccess; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.fail; /** * Comprehensive test of assignment evaluator and processor. * * MMR1 -----------I------------------------------* * ^ | * | I * | V * MR1 -----------I-------------*-----> MR3 MR4 * ^ MR2 --I---* | | | * | ^ I I I I * | | V V V V * R1 --I--> R2 O3 R4 R5 R6 * ^ * | * | * jack * * Straight line means assignment. * Line marked with "I" means inducement. * * Orders of these inducements are given by the levels of participants, so that each induced role belongs to jack, and each * induced metarole belongs to some role. So, * - inducement Rx->Ry is of order 1 * - inducement MRx->MRy is of order 1 * - inducement MRx->Ry is of order 2 * - inducement MMRx->MRy is of order 1 * * Each role has an authorization, GUI config, constructions, focus mappings, focus policy rules and target policy rules. * * Each assignment and each role can be selectively enabled/disabled (via activation) and has its condition matched (none/old/new/old+new). * * @author mederly */ @SuppressWarnings({ "FieldCanBeLocal", "SameParameterValue" }) public class TestAssignmentProcessor2 extends AbstractLensTest { private static int constructionLevels = 5; private static int focusMappingLevels = 5; private static int policyRulesLevels = 5; private static final boolean FIRST_PART = true; private static final boolean SECOND_PART = true; private static final boolean THIRD_PART = true; private static final boolean FOURTH_PART = true; private static final boolean FIFTH_PART = true; private static final File RESOURCE_DUMMY_EMPTY_FILE = new File(TEST_DIR, "resource-dummy-empty.xml"); private static final String RESOURCE_DUMMY_EMPTY_OID = "10000000-0000-0000-0000-00000000EEE4"; private static final String RESOURCE_DUMMY_EMPTY_INSTANCE_NAME = "empty"; @Autowired private AssignmentProcessor assignmentProcessor; @Autowired private Clock clock; // first part private RoleType role1, role2, role4, role5, role6; private OrgType org3; private RoleType metarole1, metarole2, metarole3, metarole4; private RoleType metametarole1; // second part private RoleType role7, role8, role9; private RoleType metarole7, metarole8, metarole9; private RoleType metametarole7; // third part private RoleType rolePirate, roleSailor, roleMan, roleWoman, roleHuman; private RoleType metaroleCrewMember, metarolePerson; // fourth part private OrgType org1, org11, org2, org21, org4, org41; // org3 is used in first part private RoleType roleAdmin; // fifth part private RoleType roleA1, roleA2, roleA3, roleA4, roleA5, roleA6, roleA7, roleA8; private List<ObjectType> objects; private static final String ROLE_R1_OID = getRoleOid("R1"); private static final String ROLE_R7_OID = getRoleOid("R7"); private static final String ROLE_MR1_OID = getRoleOid("MR1"); private static final String ROLE_PIRATE_OID = getRoleOid("Pirate"); private static final String ROLE_MAN_OID = getRoleOid("Man"); private static final String ORG11_OID = getRoleOid("org11"); private static final String ORG21_OID = getRoleOid("org21"); private static final String ORG41_OID = getRoleOid("org41"); private static final String ROLE_A1_OID = getRoleOid("A1"); @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); initDummyResourcePirate(RESOURCE_DUMMY_EMPTY_INSTANCE_NAME, RESOURCE_DUMMY_EMPTY_FILE, RESOURCE_DUMMY_EMPTY_OID, initTask, initResult); if (FIRST_PART) { createObjectsInFirstPart(false, initTask, initResult, null); } } @Test(enabled = FIRST_PART) public void test010AssignR1ToJack() throws Exception { final String TEST_NAME = "test010AssignR1ToJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R1_OID, null, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); @SuppressWarnings({ "unchecked", "raw" }) EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "R1 R2 O3 R4 R5 R6", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "MR1 MR2 MR3 MR4 MMR1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); assertOrgRef(evaluatedAssignment, "O3"); assertDelegation(evaluatedAssignment, null); // Constructions are named "role-level". We expect e.g. that from R1 we get a construction induced with order=1 (R1-1). String expectedItems = "R1-1 R2-1 O3-1 R4-1 R5-1 R6-1 MR1-2 MR2-2 MR3-2 MR4-2 MMR1-3"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "R1-0 MR1-1 MR3-1 MR4-1 MMR1-2", "R4-0 R5-0 R6-0 R2-0 O3-0 MR2-1"); assertAuthorizations(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); assertGuiConfig(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); } @Test(enabled = FIRST_PART) public void test020AssignMR1ToR1() throws Exception { final String TEST_NAME = "test020AssignMR1ToR1"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<RoleType> context = createContextForAssignment(RoleType.class, ROLE_R1_OID, RoleType.class, ROLE_MR1_OID, null, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); // assignment of construction R1-0 // assignment of focus mappings R1-0 // assignment of focus policy rules R1-0 // assignment of metarole MR1 (this will be checked) Collection<EvaluatedAssignmentImpl<RoleType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 4, 0, 0); List<EvaluatedAssignmentImpl<RoleType>> targetedAssignments = evaluatedAssignments.stream().filter(ea -> ea.getTarget() != null) .collect(Collectors.toList()); assertEquals("Wrong # of targeted assignments", 1, targetedAssignments.size()); EvaluatedAssignmentImpl<RoleType> evaluatedAssignment = targetedAssignments.get(0); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); // R4, R5, R6 could be optimized out assertTargets(evaluatedAssignment, true, "MR1 MR3 MR4", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "MMR1 R5 R4 R6", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "MR1 MR3 MR4"); assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, null); assertConstructions(evaluatedAssignment, "MR1-1 MR3-1 MMR1-2 MR4-1", null, null, null, null, null); assertFocusMappings(evaluatedAssignment, "MR1-1 MR3-1 MMR1-2 MR4-1"); assertFocusPolicyRules(evaluatedAssignment, "MR1-1 MR3-1 MMR1-2 MR4-1"); assertTargetPolicyRules(evaluatedAssignment, "MR1-0 MMR1-1", "MR3-0 MR4-0"); assertAuthorizations(evaluatedAssignment, "MR1 MR3 MR4"); assertGuiConfig(evaluatedAssignment, "MR1 MR3 MR4"); } @Test(enabled = FIRST_PART) public void test030AssignR1ToJackProjectorDisabled() throws Exception { final String TEST_NAME = "test030AssignR1ToJackProjectorDisabled"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R1_OID, null, a -> a.setActivation(ActivationUtil.createDisabled()), result); // WHEN projector.project(context, "", task, result); // THEN display("Output context", context); result.computeStatus(); assertSuccess("Projector failed (result)", result); // MID-3679 assertEquals("Wrong # of parentOrgRef entries", 0, context.getFocusContext().getObjectNew().asObjectable().getParentOrgRef().size()); assertEquals("Wrong # of roleMembershipRef entries", 0, context.getFocusContext().getObjectNew().asObjectable().getRoleMembershipRef().size()); } /** * As R1 is assigned with the relation=approver, jack will "see" only this role. * However, we must collect all relevant target policy rules. */ @Test(enabled = FIRST_PART) public void test040AssignR1ToJackAsApprover() throws Exception { final String TEST_NAME = "test040AssignR1ToJackAsApprover"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R1_OID, SchemaConstants.ORG_APPROVER, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, false, "R1 R2 O3 R4 R5 R6 MR1 MR2 MR3 MR4 MMR1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "R1"); assertOrgRef(evaluatedAssignment, null); assertDelegation(evaluatedAssignment, null); assertConstructions(evaluatedAssignment, "", null, null, null, null, null); assertFocusMappings(evaluatedAssignment, ""); assertFocusPolicyRules(evaluatedAssignment, ""); assertTargetPolicyRules(evaluatedAssignment, "R1-0 MR1-1 MMR1-2 MR4-1 MR3-1", "R2-0 MR2-1 O3-0 R4-0 R5-0 R6-0"); assertAuthorizations(evaluatedAssignment, ""); assertGuiConfig(evaluatedAssignment, ""); } /** * MMR1 -----------I------------------------------* * ^ | * | I * | V * MR1 -----------I-------------*-----> MR3 MR4 * ^ MR2 --I---* | | | * | ^ I I I I * | | V V V V * R1 --I--> R2 O3 R4 R5 R6 * ^ * | * | * jack --D--> barbossa * * (D = deputy assignment) * */ @Test(enabled = FIRST_PART) public void test050JackDeputyOfBarbossa() throws Exception { final String TEST_NAME = "test050JackDeputyOfBarbossa"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); AssignmentType policyRuleAssignment = new AssignmentType(prismContext); PolicyRuleType rule = new PolicyRuleType(prismContext); rule.setName("barbossa-0"); policyRuleAssignment.setPolicyRule(rule); @SuppressWarnings({"unchecked", "raw" }) ObjectDelta<ObjectType> objectDelta = (ObjectDelta<ObjectType>) DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add( ObjectTypeUtil.createAssignmentTo(ROLE_R1_OID, ObjectTypes.ROLE, prismContext), policyRuleAssignment) .asObjectDelta(USER_BARBOSSA_OID); executeChangesAssertSuccess(objectDelta, null, task, result); display("barbossa", getUser(USER_BARBOSSA_OID)); objects.add(getUser(USER_BARBOSSA_OID).asObjectable()); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, UserType.class, USER_BARBOSSA_OID, SchemaConstants.ORG_DEPUTY, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "R1 R2 O3 R4 R5 R6", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "barbossa MR1 MR2 MR3 MR4 MMR1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, ""); assertOrgRef(evaluatedAssignment, "O3"); assertDelegation(evaluatedAssignment, "barbossa R1 R2 O3 R4 R5 R6"); PrismReferenceValue barbossaRef = evaluatedAssignment.getDelegationRefVals().stream() .filter(v -> USER_BARBOSSA_OID.equals(v.getOid())).findFirst().orElseThrow( () -> new AssertionError("No barbossa ref in delegation ref vals")); assertEquals("Wrong relation for barbossa delegation", SchemaConstants.ORG_DEPUTY, barbossaRef.getRelation()); // Constructions are named "role-level". We expect e.g. that from R1 we get a construction induced with order=1 (R1-1). String expectedItems = "R1-1 R2-1 O3-1 R4-1 R5-1 R6-1 MR1-2 MR2-2 MR3-2 MR4-2 MMR1-3"; assertConstructions(evaluatedAssignment, "Brethren_account_construction Undead_monkey_account_construction " + expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, "barbossa-0 " + expectedItems); // Rules for other targets are empty, which is very probably OK. All rules are bound to target "barbossa". // There is no alternative target, as barbossa does not induce anything. assertTargetPolicyRules(evaluatedAssignment, "barbossa-0 R1-1 R2-1 MR2-2 O3-1 MR1-2 MR3-2 R5-1 R4-1 MMR1-3 MR4-2 R6-1", ""); assertAuthorizations(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); assertGuiConfig(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); } /** * MMR1 -----------I------------------------------* * ^ | * | I * | V * MR1 -----------I-------------*-----> MR3 MR4 * ^ MR2 --I---* | | | * | ^ I I I I * | | V V V V * R1 --I--> R2 O3 R4 R5 R6 * ^ * | * | * jack --D--> guybrush --D--> barbossa * * (D = deputy assignment) * */ @Test(enabled = FIRST_PART) public void test060JackDeputyOfGuybrushDeputyOfBarbossa() throws Exception { final String TEST_NAME = "test060JackDeputyOfGuybrushDeputyOfBarbossa"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); AssignmentType deputyOfBarbossaAssignment = ObjectTypeUtil.createAssignmentTo(USER_BARBOSSA_OID, ObjectTypes.USER, prismContext); deputyOfBarbossaAssignment.getTargetRef().setRelation(SchemaConstants.ORG_DEPUTY); AssignmentType policyRuleAssignment = new AssignmentType(prismContext); PolicyRuleType rule = new PolicyRuleType(prismContext); rule.setName("guybrush-0"); policyRuleAssignment.setPolicyRule(rule); @SuppressWarnings({"unchecked", "raw" }) ObjectDelta<ObjectType> objectDelta = (ObjectDelta<ObjectType>) DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add(deputyOfBarbossaAssignment, policyRuleAssignment) .asObjectDelta(USER_GUYBRUSH_OID); executeChangesAssertSuccess(objectDelta, null, task, result); display("guybrush", getUser(USER_GUYBRUSH_OID)); objects.add(getUser(USER_GUYBRUSH_OID).asObjectable()); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, UserType.class, USER_GUYBRUSH_OID, SchemaConstants.ORG_DEPUTY, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "R1 R2 O3 R4 R5 R6", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "guybrush barbossa MR1 MR2 MR3 MR4 MMR1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, ""); assertOrgRef(evaluatedAssignment, "O3"); assertDelegation(evaluatedAssignment, "guybrush barbossa R1 R2 O3 R4 R5 R6"); PrismReferenceValue guybrushRef = evaluatedAssignment.getDelegationRefVals().stream() .filter(v -> USER_GUYBRUSH_OID.equals(v.getOid())).findFirst().orElseThrow( () -> new AssertionError("No guybrush ref in delegation ref vals")); assertEquals("Wrong relation for guybrush delegation", SchemaConstants.ORG_DEPUTY, guybrushRef.getRelation()); String expectedItems = "R1-1 R2-1 O3-1 R4-1 R5-1 R6-1 MR1-2 MR2-2 MR3-2 MR4-2 MMR1-3"; assertConstructions(evaluatedAssignment, "Brethren_account_construction Undead_monkey_account_construction " + expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, "guybrush-0 barbossa-0 " + expectedItems); // guybrush-0 is the rule assigned to the target (guybrush) - seems OK // barbossa-0 and Rx-y are rules attached to "indirect target" (barbossa, delegator of guybrush). // TODO it is not quite clear if these are to be considered direct or indirect targets // let's consider it OK for the moment assertTargetPolicyRules(evaluatedAssignment, "guybrush-0", "barbossa-0 R1-1 R2-1 MR2-2 O3-1 MR1-2 MR3-2 R5-1 R4-1 MMR1-3 MR4-2 R6-1"); assertAuthorizations(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); assertGuiConfig(evaluatedAssignment, "R1 R2 O3 R4 R5 R6"); } /** * MMR1 -----------I------------------------------* * ^ | * | I * | V * MR1 -----------I-------------*-----> MR3 MR4 * ^ MR2 --I---* | | | * | ^ I I I I * | | V V V V * R1 --I--> R2 O3 R4 R5 R6 * ^ * A * | * jack --D--> barbossa * * (D = deputy assignment) (A = approver) * */ @Test(enabled = FIRST_PART) public void test070JackDeputyOfBarbossaApproverOfR1() throws Exception { final String TEST_NAME = "test070JackDeputyOfBarbossaApproverOfR1"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); unassignAllRoles(USER_JACK_OID); unassignAllRoles(USER_GUYBRUSH_OID); unassignAllRoles(USER_BARBOSSA_OID); // barbossa has a policy rule barbossa-0 from test050 assignRole(USER_BARBOSSA_OID, ROLE_R1_OID, SchemaConstants.ORG_APPROVER, task, result); display("barbossa", getUser(USER_BARBOSSA_OID)); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, UserType.class, USER_BARBOSSA_OID, SchemaConstants.ORG_DEPUTY, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "barbossa R1 R2 O3 R4 R5 R6 MR1 MR2 MR3 MR4 MMR1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, ""); assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, "barbossa R1"); PrismReferenceValue barbossaRef = evaluatedAssignment.getDelegationRefVals().stream() .filter(v -> USER_BARBOSSA_OID.equals(v.getOid())).findFirst().orElseThrow( () -> new AssertionError("No barbossa ref in delegation ref vals")); assertEquals("Wrong relation for barbossa delegation", SchemaConstants.ORG_DEPUTY, barbossaRef.getRelation()); PrismReferenceValue r1Ref = evaluatedAssignment.getDelegationRefVals().stream() .filter(v -> ROLE_R1_OID.equals(v.getOid())).findFirst().orElseThrow( () -> new AssertionError("No R1 ref in delegation ref vals")); assertEquals("Wrong relation for R1 delegation", SchemaConstants.ORG_APPROVER, r1Ref.getRelation()); // Constructions are named "role-level". We expect e.g. that from R1 we get a construction induced with order=1 (R1-1). assertConstructions(evaluatedAssignment, "Brethren_account_construction Undead_monkey_account_construction", null, null, null, null, null); assertFocusMappings(evaluatedAssignment, ""); assertFocusPolicyRules(evaluatedAssignment, "barbossa-0"); // Rules for other targets are empty, which is very probably OK. All rules are bound to target "barbossa". // There is no alternative target, as barbossa does not induce anything. assertTargetPolicyRules(evaluatedAssignment, "barbossa-0", ""); assertAuthorizations(evaluatedAssignment, ""); assertGuiConfig(evaluatedAssignment, ""); } /** * Now disable some roles. Their administrative status is simply set to DISABLED. * * MMR1(D)---------I------------------------------* * ^ | * | I * | V * MR1 -----------I-------------*-----> MR3(D) MR4 * ^ MR2 --I---* | | | * | ^ I I I I * | | V V V V * R1 --I--> R2(D) O3 R4(D) R5 R6 * ^ * | * | * jack */ @Test(enabled = FIRST_PART) public void test100DisableSomeRoles() throws Exception { final String TEST_NAME = "test100DisableSomeRoles"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN createObjectsInFirstPart(true, task, result, () -> disableRoles("MMR1 R2 MR3 R4")); // THEN // TODO check e.g. membershipRef for roles } @Test(enabled = FIRST_PART) public void test110AssignR1ToJack() throws Exception { final String TEST_NAME = "test010AssignR1ToJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R1_OID, null, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "R1", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "MR1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "R1"); assertOrgRef(evaluatedAssignment, null); assertDelegation(evaluatedAssignment, null); // Constructions are named "role-level". We expect e.g. that from R1 we get a construction induced with order=1 (R1-1). String expectedItems = "R1-1 MR1-2"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "R1-0 MR1-1", ""); assertAuthorizations(evaluatedAssignment, "R1"); assertGuiConfig(evaluatedAssignment, "R1"); } /** * In a similar way, let's disable some assignments. Their administrative status is simply set to DISABLED. * * MMR1 -----------I------------------------------* * ^ | * | I * | V * MR1 -----------I-------------*-(D)-> MR3 MR4 * ^ MR2 --I---* | | | * | ^ I I I I(D) * | | V V V V * R1-I(D)-> R2 O3 R4 R5 R6 * ^ * | * | * jack */ @Test(enabled = FIRST_PART) public void test150DisableSomeAssignments() throws Exception { final String TEST_NAME = "test150DisableSomeAssignments"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN createObjectsInFirstPart(true, task, result, () -> disableAssignments("MR4-R6 MR1-MR3 R1-R2")); // THEN } @Test(enabled = FIRST_PART) public void test160AssignR1ToJack() throws Exception { final String TEST_NAME = "test160AssignR1ToJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R1_OID, null, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "R1 R4", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "MR1 MMR1 MR4", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "R1 R4"); assertOrgRef(evaluatedAssignment, null); assertDelegation(evaluatedAssignment, null); String expectedItems = "R1-1 MR1-2 MMR1-3 MR4-2 R4-1"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "R1-0 MR1-1 MMR1-2 MR4-1", "R4-0"); assertAuthorizations(evaluatedAssignment, "R1 R4"); assertGuiConfig(evaluatedAssignment, "R1 R4"); } /** * Let's attach some conditions to assignments and roles. "+" condition means that it will be satisfied only in jack's new state. * "-" condition will be satisfied only in jack's old state. "0" condition will be never satisfied. * * MMR1------------I------------------------------* * ^ | * (+) I * | V * (+)MR1 -----------I-------------*-----> MR3(0) MR4(-) * ^ MR2 --I---* | | | * (+) ^ (+) I I I I * | | V V V V * R1 --I--> R2 O3 R4(D) R5 R6 * ^ (-) * | * | * jack */ @Test(enabled = FIRST_PART) public void test200AddConditions() throws Exception { final String TEST_NAME = "test200AddConditions"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN createObjectsInFirstPart(true, task, result, () -> { disableRoles("R4"); addConditionToRoles("MR1+ MR30 MR4-"); addConditionToAssignments("R1-MR1+ MR1-MMR1+ R1-R2- MR2-O3+"); }); // THEN // TODO check e.g. membershipRef for roles } @Test(enabled = FIRST_PART) public void test210AssignR1ToJack() throws Exception { final String TEST_NAME = "test210AssignR1ToJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R1_OID, null, null, result); context.getFocusContext().swallowToPrimaryDelta( DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_NAME).replace(PolyString.fromOrig("jack1")) .asItemDelta()); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); // R4 is not in plusInvalid, because only directly assigned targets are listed among targets (see validityOverride) assertTargets(evaluatedAssignment, true, "R1", null, "", null, "R2", null); assertTargets(evaluatedAssignment, false, "", null, "MR1 MMR1", null, "MR2", null); assertMembershipRef(evaluatedAssignment, "R1"); assertOrgRef(evaluatedAssignment, null); assertDelegation(evaluatedAssignment, null); // R4-1 is not in plusInvalid (see above) assertConstructions(evaluatedAssignment, "R1-1", null, "MR1-2 MMR1-3", null, "R2-1 MR2-2", null); assertFocusMappings(evaluatedAssignment, "R1-1 MR1-2 MMR1-3"); assertFocusPolicyRules(evaluatedAssignment, "R1-1 MR1-2 MMR1-3"); assertTargetPolicyRules(evaluatedAssignment, "R1-0 MR1-1 MMR1-2", ""); assertAuthorizations(evaluatedAssignment, "R1"); assertGuiConfig(evaluatedAssignment, "R1"); } /** * Testing targets with multiple incoming paths. * * MMR7 -------I--------* * ^^ | * || | * |+--------+ | * | | V * MR7 MR8 MR9 * ^ ^ | * | | | * | | V * R7 --I--> R8 R9 * ^ * | * | * jack * */ @Test(enabled = SECOND_PART) public void test300AssignR7ToJack() throws Exception { final String TEST_NAME = "test300AssignR7ToJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); createObjectsInSecondPart(false, task, result, null); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_R7_OID, null, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); /* We expect some duplicates, namely: Constructions: DeltaSetTriple: zero: description: R7-1 description: R8-1 description: R9-1 description: R9-1 description: MR7-2 description: MR8-2 description: MR9-2 description: MR9-2 description: MMR7-3 description: MMR7-3 plus: minus: Roles: DeltaSetTriple: zero: EvaluatedAssignmentTarget: name: R7 name: R8 name: R9 name: R9 name: MR7 name: MR8 name: MR9 name: MR9 name: MMR7 name: MMR7 plus: minus: Membership: PRV(object=role:99999999-0000-0000-0000-0000000000R7(R7)) PRV(object=role:99999999-0000-0000-0000-0000000000R8(R8)) PRV(object=role:99999999-0000-0000-0000-0000000000R9(R9)) PRV(object=role:99999999-0000-0000-0000-0000000000R9(R9)) Authorizations: [R7]) [R8]) [R9]) [R9]) Focus Mappings: M(R7-1: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(R8-1: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(R9-1: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(R9-1: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(MR7-2: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(MR8-2: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(MR9-2: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(MR9-2: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(MMR7-3: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) M(MMR7-3: {...common/common-3}description = PVDeltaSetTriple(zero: [PPV(String:jack)]; plus: []; minus: []; )) Target: role:99999999-0000-0000-0000-0000000000R7(R7) focusPolicyRules: [ name: R7-1 name: R8-1 name: R9-1 name: R9-1 name: MR7-2 name: MR8-2 name: MR9-2 name: MR9-2 name: MMR7-3 name: MMR7-3 ] thisTargetPolicyRules: [ name: R7-0 name: MR7-1 name: MMR7-2 name: MR9-1 ] otherTargetsPolicyRules: [ name: R8-0 name: R9-0 name: R9-0 name: MR8-1 name: MR9-1 name: MMR7-2 ] For all path-sensitive items (constructions, targets, focus mappings, policy rules) it is OK, because the items will differ in assignment path; this might be relevant (e.g. w.r.t. validity, or further processing of e.g. constructions or policy rules). Simple "scalar" results, like membership, authorizations or gui config, should not contain duplicates. */ assertTargets(evaluatedAssignment, true, "R7 R8 R9 R9", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "MR7 MR8 MR9 MR9 MMR7 MMR7", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "R7 R8 R9"); assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, ""); String expectedItems = "R7-1 R8-1 R9-1 R9-1 MR7-2 MR8-2 MR9-2 MR9-2 MMR7-3 MMR7-3"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "R7-0 MR7-1 MMR7-2 MR9-1", "R8-0 R9-0 R9-0 MR8-1 MR9-1 MMR7-2"); assertAuthorizations(evaluatedAssignment, "R7 R8 R9"); assertGuiConfig(evaluatedAssignment, "R7 R8 R9"); } /** * Testing assignment path variables * * MetaroleCrewMember (C3) -----I-----> MetarolePerson (C4) --I--+ * ^ ^ ^ ^ | * | | | | | * | | | | V * (C1) Pirate --I--> Sailor (C2) Man Woman Human (C5) * ^ | * | +----------------------------------+ * | | (added later) * jack * * Assume these constructions: * - C1 giving each Pirate some account (attached via inducement) * - C2 giving each Sailor some account (attached via inducement) * - C3 giving each crew member some account (attached via inducement of order 2) * - C4 giving each person some account (attached via inducement of order 2) * - C5 giving each Human some account (attached via inducement) */ @Test(enabled = THIRD_PART) public void test400AssignJackPirate() throws Exception { final String TEST_NAME = "test400AssignJackPirate"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); createObjectsInThirdPart(false, task, result, () -> { createCustomConstruction(rolePirate, "C1", 1); createCustomConstruction(roleSailor, "C2", 1); createCustomConstruction(metaroleCrewMember, "C3", 2); createCustomConstruction(metarolePerson, "C4", 2); createCustomConstruction(roleHuman, "C5", 1); addConditionToRoles("Pirate! Sailor! MetaroleCrewMember! MetarolePerson! Man! Human!"); addConditionToAssignments("Pirate-Sailor! Pirate-MetaroleCrewMember! Sailor-MetaroleCrewMember! MetaroleCrewMember-MetarolePerson! Man-MetarolePerson! MetarolePerson-Human!"); }); LensContext<UserType> context = createContextForRoleAssignment(USER_JACK_OID, ROLE_PIRATE_OID, null, null, result); // WHEN recording = true; assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); recording = false; // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "Pirate Sailor Human Human", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "MetaroleCrewMember MetaroleCrewMember MetarolePerson MetarolePerson", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "Pirate Sailor Human"); assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, ""); String expectedItems = "Pirate-1 Sailor-1 MetaroleCrewMember-2 MetaroleCrewMember-2 MetarolePerson-2 MetarolePerson-2 Human-1 Human-1"; assertConstructions(evaluatedAssignment, expectedItems + " C1 C2 C3 C3 C4 C4 C5 C5", null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "Pirate-0 MetaroleCrewMember-1 MetarolePerson-1", "Sailor-0 MetaroleCrewMember-1 MetarolePerson-1 Human-0 Human-0"); assertAuthorizations(evaluatedAssignment, "Pirate Sailor Human"); assertGuiConfig(evaluatedAssignment, "Pirate Sailor Human"); dump("Pirate!", 0); dump("Sailor!", 0); dump("MetaroleCrewMember!", 1); dump("MetaroleCrewMember!", 0); dump("MetarolePerson!", 1); dump("MetarolePerson!", 0); dump("Human!", 1); dump("Human!", 0); dump("Pirate-Sailor!", 0); dump("Pirate-MetaroleCrewMember!", 0); dump("Sailor-MetaroleCrewMember!", 0); dump("MetaroleCrewMember-MetarolePerson!", 1); dump("MetaroleCrewMember-MetarolePerson!", 0); dump("MetarolePerson-Human!", 1); dump("MetarolePerson-Human!", 0); dump("C1", 0); dump("C2", 0); dump("C3", 1); dump("C3", 0); dump("C4", 1); dump("C4", 0); dump("C5", 1); dump("C5", 0); runs.values().forEach(r -> r.assertFocus("jack").assertFocusAssignment("->Pirate")); getRunInfo("Pirate!", 0) .assertThisAssignment("->Pirate") .assertImmediateAssignment(null) .assertSource("jack") .assertImmediateRole(null) .assertAssignmentPath(1); getRunInfo("Sailor!", 0) .assertThisAssignment("->Sailor") .assertImmediateAssignment("->Pirate") .assertSource("Pirate") .assertImmediateRole(null) .assertAssignmentPath(2); // swap indices if internals of evaluator change and "Pirate" branch is executed first getRunInfo("MetaroleCrewMember!", 1) .assertThisAssignment("->MetaroleCrewMember") .assertImmediateAssignment("->Pirate") .assertSource("Pirate") .assertImmediateRole(null) .assertAssignmentPath(2); getRunInfo("MetaroleCrewMember!", 0) .assertThisAssignment("->MetaroleCrewMember") .assertImmediateAssignment("->Sailor") .assertSource("Sailor") .assertImmediateRole("Pirate") .assertAssignmentPath(3); getRunInfo("MetarolePerson!", 1) .assertThisAssignment("->MetarolePerson") .assertImmediateAssignment("->MetaroleCrewMember") .assertSource("MetaroleCrewMember") .assertImmediateRole("Pirate") .assertAssignmentPath(3); getRunInfo("MetarolePerson!", 0) .assertThisAssignment("->MetarolePerson") .assertImmediateAssignment("->MetaroleCrewMember") .assertSource("MetaroleCrewMember") .assertImmediateRole("Sailor") .assertAssignmentPath(4); getRunInfo("Human!", 1) .assertThisAssignment("->Human") .assertImmediateAssignment("->MetarolePerson") .assertSource("MetarolePerson") .assertImmediateRole("MetaroleCrewMember") .assertAssignmentPath(4); getRunInfo("Human!", 0) .assertThisAssignment("->Human") .assertImmediateAssignment("->MetarolePerson") .assertSource("MetarolePerson") .assertImmediateRole("MetaroleCrewMember") .assertAssignmentPath(5); // assignments getRunInfo("Pirate-Sailor!", 0) .assertThisAssignment("->Sailor") .assertImmediateAssignment("->Pirate") .assertSource("Pirate") .assertImmediateRole(null) .assertAssignmentPath(2); getRunInfo("Pirate-MetaroleCrewMember!", 0) .assertThisAssignment("->MetaroleCrewMember") .assertImmediateAssignment("->Pirate") .assertSource("Pirate") .assertImmediateRole(null) .assertAssignmentPath(2); getRunInfo("Sailor-MetaroleCrewMember!", 0) .assertThisAssignment("->MetaroleCrewMember") .assertImmediateAssignment("->Sailor") .assertSource("Sailor") .assertImmediateRole("Pirate") .assertAssignmentPath(3); getRunInfo("MetaroleCrewMember-MetarolePerson!", 1) .assertThisAssignment("->MetarolePerson") .assertImmediateAssignment("->MetaroleCrewMember") .assertSource("MetaroleCrewMember") .assertImmediateRole("Pirate") .assertAssignmentPath(3); getRunInfo("MetaroleCrewMember-MetarolePerson!", 0) .assertThisAssignment("->MetarolePerson") .assertImmediateAssignment("->MetaroleCrewMember") .assertSource("MetaroleCrewMember") .assertImmediateRole("Sailor") .assertAssignmentPath(4); getRunInfo("MetarolePerson-Human!", 1) .assertThisAssignment("->Human") .assertImmediateAssignment("->MetarolePerson") .assertSource("MetarolePerson") .assertImmediateRole("MetaroleCrewMember") .assertAssignmentPath(4); getRunInfo("MetarolePerson-Human!", 0) .assertThisAssignment("->Human") .assertImmediateAssignment("->MetarolePerson") .assertSource("MetarolePerson") .assertImmediateRole("MetaroleCrewMember") .assertAssignmentPath(5); getRunInfo("C1", 0) .assertImmediateAssignment("->Pirate") .assertSource("Pirate") .assertThisObject("Pirate") .assertImmediateRole(null) .assertAssignmentPath(2); getRunInfo("C2", 0) .assertImmediateAssignment("->Sailor") .assertSource("Sailor") .assertThisObject("Sailor") .assertImmediateRole("Pirate") .assertAssignmentPath(3); getRunInfo("C3", 1) .assertImmediateAssignment("->MetaroleCrewMember") .assertSource("MetaroleCrewMember") .assertThisObject("Pirate") .assertImmediateRole("Pirate") .assertAssignmentPath(3); getRunInfo("C3", 0) .assertImmediateAssignment("->MetaroleCrewMember") .assertSource("MetaroleCrewMember") .assertThisObject("Sailor") .assertImmediateRole("Sailor") .assertAssignmentPath(4); getRunInfo("C4", 1) .assertImmediateAssignment("->MetarolePerson") .assertSource("MetarolePerson") .assertThisObject("MetaroleCrewMember") // TODO .assertImmediateRole("MetaroleCrewMember") .assertAssignmentPath(4); getRunInfo("C4", 0) .assertImmediateAssignment("->MetarolePerson") .assertSource("MetarolePerson") .assertThisObject("MetaroleCrewMember") // TODO .assertImmediateRole("MetaroleCrewMember") .assertAssignmentPath(5); getRunInfo("C5", 1) .assertImmediateAssignment("->Human") .assertSource("Human") .assertThisObject("Human") .assertImmediateRole("MetarolePerson") .assertAssignmentPath(5); getRunInfo("C5", 0) .assertImmediateAssignment("->Human") .assertSource("Human") .assertThisObject("Human") .assertImmediateRole("MetarolePerson") .assertAssignmentPath(6); } private void dump(String runName, int index) { System.out.println(getRunInfo(runName, index).dump()); } private RunInfo getRunInfo(String runName, int index) { return getRunInfos(runName).stream().filter(r -> r.index == index) .findFirst() .orElseThrow(() -> new AssertionError("No run " + runName + " with index " + index)); } private Collection<RunInfo> getRunInfos(String name) { return CollectionUtils.emptyIfNull(runs.get(name)); } private RunInfo getRunInfo(String name) { Collection<RunInfo> runs = getRunInfos(name); assertEquals("Wrong # of run infos for " + name, 1, runs.size()); return runs.iterator().next(); } private void showEvaluations(EvaluatedAssignmentImpl<UserType> evaluatedAssignment, String name, int expectedConstructions, Task task, OperationResult result) throws Exception { List<Construction<UserType>> constructions = getConstructions(evaluatedAssignment, name); assertEquals("Wrong # of constructions: " + name, expectedConstructions, constructions.size()); for (int i = 0; i < constructions.size(); i++) { Construction<UserType> construction = constructions.get(i); System.out.println("Evaluating " + name + " #" + (i+1)); construction.evaluate(task, result); System.out.println("Done"); } } private static boolean recording() { return recording && ScriptExpressionEvaluationContext.getThreadLocal().isEvaluateNew(); } private static class RunInfo { private String name; private int index; private AssignmentType assignment; private AssignmentType thisAssignment; private AssignmentType immediateAssignment; private AssignmentType focusAssignment; private FocusType source; private FocusType immediateRole; private FocusType thisObject; private FocusType focus; private AssignmentPathImpl assignmentPath; private String dump() { String p = name + "#" + (index+1); StringBuilder sb = new StringBuilder(); sb.append("------------------------------------------------------------------------------------\n"); sb.append(p).append(" ").append("assignment: ").append(assignment).append("\n"); sb.append(p).append(" ").append("thisAssignment: ").append(thisAssignment).append("\n"); sb.append(p).append(" ").append("immediateAssignment: ").append(immediateAssignment).append("\n"); sb.append(p).append(" ").append("focusAssignment: ").append(focusAssignment).append("\n"); sb.append(p).append(" ").append("source: ").append(source).append("\n"); sb.append(p).append(" ").append("immediateRole: ").append(immediateRole).append("\n"); sb.append(p).append(" ").append("thisObject: ").append(thisObject).append("\n"); sb.append(p).append(" ").append("focus: ").append(focus).append("\n"); sb.append(p).append(" ").append("assignmentPath: ").append(shortString(assignmentPath)).append("\n"); return sb.toString(); } private String shortString(AssignmentPathImpl assignmentPath) { StringBuilder sb = new StringBuilder(); boolean first = true; for (AssignmentPathSegmentImpl segment : assignmentPath.getSegments()) { if (first) { first = false; } else { sb.append("; "); } sb.append(segment.getSource().getName()); if (segment.getTarget() != null) { sb.append(" -> ").append(segment.getTarget().getName()); } } return sb.toString(); } public RunInfo assertThisAssignment(String name) { return assertAssignment(thisAssignment, name); } private RunInfo assertAssignment(AssignmentType assignment, String name) { if (name == null) { assertNull("Assignment is not null", assignment); } else { name = name.substring(2); assertEquals("Wrong target OID in assignment", getRoleOid(name), assignment.getTargetRef().getOid()); } return this; } public RunInfo assertImmediateAssignment(String name) { return assertAssignment(immediateAssignment, name); } public RunInfo assertFocusAssignment(String name) { return assertAssignment(focusAssignment, name); } public RunInfo assertSource(String name) { return assertObject(source, name); } public RunInfo assertThisObject(String name) { return assertObject(thisObject, name); } public RunInfo assertFocus(String name) { return assertObject(focus, name); } public RunInfo assertImmediateRole(String name) { return assertObject(immediateRole, name); } public RunInfo assertObject(ObjectType object, String name) { if (name == null) { assertNull("Object is not null", object); } else { assertEquals("Wrong object", name, object.getName().getOrig()); } return this; } public RunInfo assertAssignmentPath(int expected) { assertEquals("Wrong length of assignmentPath", expected, assignmentPath.size()); return this; } } private static boolean recording = false; private static MultiValuedMap<String,RunInfo> runs = new ArrayListValuedHashMap<>(); private static RunInfo currentRun; // called from the script public static void startCallback(String desc) { if (recording()) { System.out.println("Starting execution: " + desc); currentRun = new RunInfo(); currentRun.name = desc; currentRun.index = CollectionUtils.emptyIfNull(runs.get(desc)).size(); } } private static final List<String> RECORDED_VARIABLES = Arrays.asList( ExpressionConstants.VAR_ASSIGNMENT.getLocalPart(), ExpressionConstants.VAR_FOCUS_ASSIGNMENT.getLocalPart(), ExpressionConstants.VAR_IMMEDIATE_ASSIGNMENT.getLocalPart(), ExpressionConstants.VAR_THIS_ASSIGNMENT.getLocalPart(), ExpressionConstants.VAR_FOCUS.getLocalPart(), ExpressionConstants.VAR_ORDER_ONE_OBJECT.getLocalPart(), ExpressionConstants.VAR_IMMEDIATE_ROLE.getLocalPart(), ExpressionConstants.VAR_SOURCE.getLocalPart(), ExpressionConstants.VAR_ASSIGNMENT_PATH.getLocalPart()); @SuppressWarnings("unchecked") public static void variableCallback(String name, Object value, String desc) { if (recording()) { if (RECORDED_VARIABLES.contains(name)) { System.out.println(desc + ": name = " + name + ", value = " + value); if (ExpressionConstants.VAR_ASSIGNMENT.getLocalPart().equals(name)) { currentRun.assignment = (AssignmentType) value; } else if (ExpressionConstants.VAR_FOCUS_ASSIGNMENT.getLocalPart().equals(name)) { currentRun.focusAssignment = (AssignmentType) value; } else if (ExpressionConstants.VAR_IMMEDIATE_ASSIGNMENT.getLocalPart().equals(name)) currentRun.immediateAssignment = (AssignmentType) value; else if (ExpressionConstants.VAR_THIS_ASSIGNMENT.getLocalPart().equals(name)) { currentRun.thisAssignment = (AssignmentType) value; } else if (ExpressionConstants.VAR_FOCUS.getLocalPart().equals(name)) { currentRun.focus = (FocusType) value; } else if (ExpressionConstants.VAR_ORDER_ONE_OBJECT.getLocalPart().equals(name)) { currentRun.thisObject = (FocusType) value; } else if (ExpressionConstants.VAR_IMMEDIATE_ROLE.getLocalPart().equals(name)) { currentRun.immediateRole = (FocusType) value; } else if (ExpressionConstants.VAR_SOURCE.getLocalPart().equals(name)) { currentRun.source = (FocusType) value; } else if (ExpressionConstants.VAR_ASSIGNMENT_PATH.getLocalPart().equals(name)) { currentRun.assignmentPath = (AssignmentPathImpl) value; } } } } public static void finishCallback(String desc) { if (recording()) { System.out.println("Finishing execution: " + desc); runs.put(desc, currentRun); } } /** * Testing non-scalar constraints (MID-3815) * * Org1 -----I----+ Org2 -----I----+ * ^ | (orderConstraints 1..N) ^ | (orderConstraints: manager: 1) * | | (reset summary to 1) | | (reset default to 0) * | V | V * Org11 Admin Org21 Admin * ^ ^ * | (manager) * | | * jack jack * * */ @Test(enabled = FOURTH_PART) public void test500AssignJackOrg11() throws Exception { final String TEST_NAME = "test500AssignJackOrg11"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); createObjectsInFourthPart(false, task, result, null); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, OrgType.class, ORG11_OID, null, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "org11 Admin", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "org1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "org11 Admin"); assertOrgRef(evaluatedAssignment, "org11"); assertDelegation(evaluatedAssignment, ""); String expectedItems = "org11-1 org1-2 Admin-1"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "org11-0 org1-1", "Admin-0"); assertAuthorizations(evaluatedAssignment, "org11 Admin"); assertGuiConfig(evaluatedAssignment, "org11 Admin"); } /** * * Org1 -----I----+ * ^ | (orderConstraints 1..N) * | | (reset summary to 1) * | V * Org11 Admin * ^ * | * (manager) * | * jack * */ @Test(enabled = FOURTH_PART) public void test505AssignJackOrg11AsManager() throws Exception { final String TEST_NAME = "test505AssignJackOrg11AsManager"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, OrgType.class, ORG11_OID, SchemaConstants.ORG_MANAGER, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "org11 Admin", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "org1", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "org11 Admin"); assertOrgRef(evaluatedAssignment, "org11"); assertDelegation(evaluatedAssignment, ""); String expectedItems = "org11-1 org1-2 Admin-1"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "org11-0 org1-1", "Admin-0"); assertAuthorizations(evaluatedAssignment, "org11 Admin"); assertGuiConfig(evaluatedAssignment, "org11 Admin"); } /** * * Org1 -----I----+ * ^ | (orderConstraints 1..N) * | | (reset summary to 1) * | V * Org11 Admin * ^ * | * (approver) * | * jack * */ @Test(enabled = FOURTH_PART) public void test507AssignJackOrg11AsApprover() throws Exception { final String TEST_NAME = "test507AssignJackOrg11AsApprover"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, OrgType.class, ORG11_OID, SchemaConstants.ORG_APPROVER, null, result); // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "org11 org1 Admin", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "org11"); // approver assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, ""); assertConstructions(evaluatedAssignment, "", null, null, null, null, null); assertFocusMappings(evaluatedAssignment, ""); assertFocusPolicyRules(evaluatedAssignment, ""); assertTargetPolicyRules(evaluatedAssignment, "org11-0 org1-1", "Admin-0"); assertAuthorizations(evaluatedAssignment, ""); assertGuiConfig(evaluatedAssignment, ""); } /** * Org2 -----I----+ * ^ | (orderConstraints: manager: 1) * | | (reset default to 0) * | V * Org21 Admin * ^ * | * | * jack * * Target policy rules from Admin are not taken into account. (That's probably OK, * because Admin is not matched for the focus neither.) */ @Test(enabled = FOURTH_PART) public void test510AssignJackOrg21() throws Exception { final String TEST_NAME = "test510AssignJackOrg21"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, OrgType.class, ORG21_OID, null, null, result); // intentionally unqualified // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "org21", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "org2 Admin", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "org21"); assertOrgRef(evaluatedAssignment, "org21"); assertDelegation(evaluatedAssignment, ""); String expectedItems = "org21-1 org2-2"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "org21-0 org2-1", ""); assertAuthorizations(evaluatedAssignment, "org21"); assertGuiConfig(evaluatedAssignment, "org21"); } /** * Org2 -----I----+ * ^ | (orderConstraints: manager: 1) * | | (reset default to 0) * | V * Org21 Admin * ^ * (manager) * | * jack */ @Test(enabled = FOURTH_PART) public void test515AssignJackOrg21AsManager() throws Exception { final String TEST_NAME = "test515AssignJackOrg21AsManager"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, OrgType.class, ORG21_OID, new QName("manager"), null, result); // intentionally unqualified // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "org21 Admin", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "org2", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "org21 Admin"); assertOrgRef(evaluatedAssignment, "org21"); assertDelegation(evaluatedAssignment, ""); String expectedItems = "org21-1 org2-2 Admin-1"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "org21-0 org2-1", "Admin-0"); assertAuthorizations(evaluatedAssignment, "org21 Admin"); assertGuiConfig(evaluatedAssignment, "org21 Admin"); } /** * Org4 -----I----+ * ^ | (orderConstraints: any) * | | (focusType = UserType) * | | (reset approver to 0) * | | (reset default to 1) * | V * Org41 Admin * ^ * (approver) * | * jack * * As for target evaluation order, it is: * @ org41: (zero) * @ org4: (default:1) * @ admin: changed from @org4 by the same vector as the normal evaluation order * * Because normal evaluation order was changed from: approver:1, default:1 to approver: 0, default: 1 (i.e. "- 1 approver"), * the target evaluation order would be: default:1, approver:-1, which is nonsense. * * For such invalid cases we define target evaluation order as undefined. * * Therefore, Admin-0 is not among target policy rules. */ @Test(enabled = FOURTH_PART) public void test520AssignJackOrg41AsApprover() throws Exception { final String TEST_NAME = "test520AssignJackOrg41AsApprover"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, OrgType.class, ORG41_OID, new QName("approver"), null, result); // intentionally unqualified // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "Admin", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "org41 org4", null, null, null, null, null); assertMembershipRef(evaluatedAssignment, "org41 Admin"); assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, ""); String expectedItems = "Admin-1"; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "org4-1 org41-0", ""); assertAuthorizations(evaluatedAssignment, "Admin"); assertGuiConfig(evaluatedAssignment, "Admin"); } /** * "Go back N" inducements in the presence of various relations. * Each target has a note about expected evaluation order ("a", "ab", "abc", ...). * * abde/A6 ----[I]----+ * | | * (e) | * | V * abc/A3 ----[I]----+ A5/abd ...... A7/abd----[I]----+ * | | | | * (c) |(d) | * | V | | * A2/ab ....... A4/ab | * | | * (b) | * | | * A1/a <.........same evaluation order......... A8/a * ^ * (a) * | * jack */ @Test(enabled = FIFTH_PART) public void test600AssignA1ToJack() throws Exception { final String TEST_NAME = "test600AssignA1ToJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestAssignmentProcessor.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); createObjectsInFifthPart(false, task, result, null); LensContext<UserType> context = createContextForAssignment(UserType.class, USER_JACK_OID, RoleType.class, ROLE_A1_OID, new QName("a"), null, result); // intentionally unqualified // WHEN assignmentProcessor.processAssignmentsProjections(context, clock.currentTimeXMLGregorianCalendar(), task, result); // THEN display("Output context", context); display("Evaluated assignment triple", context.getEvaluatedAssignmentTriple()); result.computeStatus(); assertSuccess("Assignment processor failed (result)", result); Collection<EvaluatedAssignmentImpl<UserType>> evaluatedAssignments = assertAssignmentTripleSetSize(context, 0, 1, 0); EvaluatedAssignmentImpl<UserType> evaluatedAssignment = evaluatedAssignments.iterator().next(); assertEquals("Wrong evaluatedAssignment.isValid", true, evaluatedAssignment.isValid()); assertTargets(evaluatedAssignment, true, "", null, null, null, null, null); assertTargets(evaluatedAssignment, false, "A1 A2 A3 A4 A5 A6 A7 A8", null, null, null, null, null); assertTargetPath(evaluatedAssignment, "A1", "a"); assertTargetPath(evaluatedAssignment, "A2", "a b"); assertTargetPath(evaluatedAssignment, "A3", "a b c"); assertTargetPath(evaluatedAssignment, "A4", "a b"); assertTargetPath(evaluatedAssignment, "A5", "a b d"); assertTargetPath(evaluatedAssignment, "A6", "a b d e"); assertTargetPath(evaluatedAssignment, "A7", "a b d"); assertTargetPath(evaluatedAssignment, "A8", "a"); assertMembershipRef(evaluatedAssignment, "A1"); assertOrgRef(evaluatedAssignment, ""); assertDelegation(evaluatedAssignment, ""); String expectedItems = ""; assertConstructions(evaluatedAssignment, expectedItems, null, null, null, null, null); assertFocusMappings(evaluatedAssignment, expectedItems); assertFocusPolicyRules(evaluatedAssignment, expectedItems); assertTargetPolicyRules(evaluatedAssignment, "A1-0", "A8-0"); // a bit questionable but seems OK assertAuthorizations(evaluatedAssignment, ""); assertGuiConfig(evaluatedAssignment, ""); } //region ============================================================= helper methods (preparing scenarios) private void createObjectsInFirstPart(boolean deleteFirst, Task task, OperationResult result, Runnable adjustment) throws Exception { role1 = createRole(1, 1); role1.setDelegable(true); role2 = createRole(1, 2); org3 = createOrg(3); role4 = createRole(1, 4); role5 = createRole(1, 5); role6 = createRole(1, 6); metarole1 = createRole(2, 1); metarole2 = createRole(2, 2); metarole3 = createRole(2, 3); metarole4 = createRole(2, 4); metametarole1 = createRole(3, 1); assign(role1, metarole1); assign(role2, metarole2); assign(metarole1, metametarole1); induce(role1, role2, 1); induce(metarole1, metarole3, 1); induce(metarole1, role4, 2); induce(metarole2, org3, 2); induce(metarole3, role5, 2); induce(metarole4, role6, 2); induce(metametarole1, metarole4, 2); objects = new ArrayList<>( Arrays.asList(role1, role2, org3, role4, role5, role6, metarole1, metarole2, metarole3, metarole4, metametarole1)); createObjects(deleteFirst, task, result, adjustment); } private void createObjectsInSecondPart(boolean deleteFirst, Task task, OperationResult result, Runnable adjustment) throws Exception { role7 = createRole(1, 7); role7.setDelegable(true); role8 = createRole(1, 8); role9 = createRole(1, 9); metarole7 = createRole(2, 7); metarole8 = createRole(2, 8); metarole9 = createRole(2, 9); metametarole7 = createRole(3, 7); assign(role7, metarole7); assign(role8, metarole8); assign(metarole7, metametarole7); assign(metarole8, metametarole7); induce(role7, role8, 1); induce(metametarole7, metarole9, 2); induce(metarole9, role9, 2); objects = new ArrayList<>( Arrays.asList(role7, role8, role9, metarole7, metarole8, metarole9, metametarole7)); createObjects(deleteFirst, task, result, adjustment); } private void createObjectsInThirdPart(boolean deleteFirst, Task task, OperationResult result, Runnable adjustment) throws Exception { rolePirate = createRole("Pirate"); rolePirate.setDelegable(true); roleSailor = createRole("Sailor"); metaroleCrewMember = createRole("MetaroleCrewMember"); metarolePerson = createRole("MetarolePerson"); roleMan = createRole("Man"); roleWoman = createRole("Woman"); roleHuman = createRole("Human"); assign(rolePirate, metaroleCrewMember); assign(roleSailor, metaroleCrewMember); induce(rolePirate, roleSailor, 1); assign(roleMan, metarolePerson); assign(roleWoman, metarolePerson); induce(metaroleCrewMember, metarolePerson, 1); induce(metarolePerson, roleHuman, 2); objects = new ArrayList<>( Arrays.asList(rolePirate, roleSailor, metaroleCrewMember, metarolePerson, roleMan, roleWoman, roleHuman)); createObjects(deleteFirst, task, result, adjustment); } private void createObjectsInFourthPart(boolean deleteFirst, Task task, OperationResult result, Runnable adjustment) throws Exception { org1 = createOrg("org1"); org11 = createOrg("org11"); org2 = createOrg("org2"); org21 = createOrg("org21"); org4 = createOrg("org4"); org41 = createOrg("org41"); roleAdmin = createRole("Admin"); assign(org11, org1); assign(org21, org2); // org1->roleAdmin AssignmentType inducement = ObjectTypeUtil.createAssignmentTo(roleAdmin.asPrismObject()) .beginOrderConstraint() .orderMin("1") .orderMax("unbounded") .resetOrder(1) .end(); org1.getInducement().add(inducement); // org2->roleAdmin AssignmentType inducement2 = ObjectTypeUtil.createAssignmentTo(roleAdmin.asPrismObject()) .beginOrderConstraint() .order(1) .relation(SchemaConstants.ORG_MANAGER) .<AssignmentType>end() .beginOrderConstraint() .resetOrder(0) .relation(SchemaConstants.ORG_DEFAULT) .end(); org2.getInducement().add(inducement2); /* * Org4 -----I----+ * ^ | (orderConstraints: everything goes) * | | (focusType = UserType) * | | (reset approver to 0) * | | (reset default to 1) * | V * Org41 Admin */ assign(org41, org4); AssignmentType inducement4 = ObjectTypeUtil.createAssignmentTo(roleAdmin.asPrismObject()) .beginOrderConstraint() .orderMin("0") .orderMax("unbounded") .resetOrder(0) .relation(SchemaConstants.ORG_APPROVER) .<AssignmentType>end() .beginOrderConstraint() .orderMin("0") .orderMax("unbounded") .resetOrder(1) .relation(SchemaConstants.ORG_DEFAULT) .<AssignmentType>end() .focusType(UserType.COMPLEX_TYPE); org4.getInducement().add(inducement4); objects = new ArrayList<>(Arrays.asList(roleAdmin, org1, org11, org2, org21, org4, org41)); createObjects(deleteFirst, task, result, adjustment); } private void createObjectsInFifthPart(boolean deleteFirst, Task task, OperationResult result, Runnable adjustment) throws Exception { constructionLevels = focusMappingLevels = policyRulesLevels = 2; roleA1 = createRole("A1"); roleA2 = createRole("A2"); roleA3 = createRole("A3"); roleA4 = createRole("A4"); roleA5 = createRole("A5"); roleA6 = createRole("A6"); roleA7 = createRole("A7"); roleA8 = createRole("A8"); assign(roleA1, roleA2, new QName("b")); assign(roleA2, roleA3, new QName("c")); induce(roleA3, roleA4, 2); assign(roleA4, roleA5, new QName("d")); assign(roleA5, roleA6, new QName("e")); induce(roleA6, roleA7, 2); induce(roleA7, roleA8, 3); objects = new ArrayList<>( Arrays.asList(roleA1, roleA2, roleA3, roleA4, roleA5, roleA6, roleA7, roleA8)); createObjects(deleteFirst, task, result, adjustment); } private void createCustomConstruction(RoleType role, String name, int order) { ConstructionType c = new ConstructionType(prismContext); c.setDescription(name); c.setResourceRef(ObjectTypeUtil.createObjectRef(RESOURCE_DUMMY_EMPTY_OID, ObjectTypes.RESOURCE)); ResourceAttributeDefinitionType nameDef = new ResourceAttributeDefinitionType(); nameDef.setRef(new ItemPath(new QName(SchemaConstants.NS_ICF_SCHEMA, "name")).asItemPathType()); MappingType outbound = new MappingType(); outbound.setName(name); ExpressionType expression = new ExpressionType(); ScriptExpressionEvaluatorType script = new ScriptExpressionEvaluatorType(); script.setCode( "import com.evolveum.midpoint.model.impl.lens.TestAssignmentProcessor2\n\n" + "TestAssignmentProcessor2.startCallback('" + name + "')\n" + "this.binding.variables.each {k,v -> TestAssignmentProcessor2.variableCallback(k, v, '" + name + "')}\n" + "TestAssignmentProcessor2.finishCallback('" + name + "')\n" + "return null"); expression.getExpressionEvaluator().add(new ObjectFactory().createScript(script)); outbound.setExpression(expression); nameDef.setOutbound(outbound); c.getAttribute().add(nameDef); AssignmentType a = new AssignmentType(prismContext); a.setDescription("Assignment for " + c.getDescription()); a.setConstruction(c); addAssignmentOrInducement(role, order, a); } private void createObjects(boolean deleteFirst, Task task, OperationResult result, Runnable adjustment) throws Exception { if (adjustment != null) { adjustment.run(); } // TODO implement repoAddObjects with overwrite option if (deleteFirst) { for (ObjectType role : objects) { repositoryService.deleteObject(role.getClass(), role.getOid(), result); } } repoAddObjects(objects, result); recomputeAndRefreshObjects(objects, task, result); displayObjectTypeCollection("objects", objects); } // methods for creation-time manipulation with roles and assignments private void disableRoles(String text) { for (String name : getList(text)) { AbstractRoleType role = findRole(name); if (role.getActivation() == null) { role.setActivation(new ActivationType(prismContext)); } role.getActivation().setAdministrativeStatus(ActivationStatusType.DISABLED); } } private void disableAssignments(String text) { for (String assignmentText : getList(text)) { AssignmentType assignment = findAssignmentOrInducement(assignmentText); if (assignment.getActivation() == null) { assignment.setActivation(new ActivationType(prismContext)); } assignment.getActivation().setAdministrativeStatus(ActivationStatusType.DISABLED); } } private void addConditionToRoles(String text) { for (String item : getList(text)) { String name = StringUtils.substring(item, 0, -1); char conditionType = item.charAt(item.length() - 1); AbstractRoleType role = findRole(name); role.setCondition(createCondition(item, conditionType)); } } private void addConditionToAssignments(String text) { for (String item : getList(text)) { String assignmentText = StringUtils.substring(item, 0,-1); char conditionType = item.charAt(item.length() - 1); AssignmentType assignment = findAssignmentOrInducement(assignmentText); assignment.setCondition(createCondition(item, conditionType)); } } private MappingType createCondition(String conditionName, char conditionType) { ScriptExpressionEvaluatorType script = new ScriptExpressionEvaluatorType(); switch (conditionType) { case '+': script.setCode("basic.stringify(name) == 'jack1'"); break; case '-': script.setCode("basic.stringify(name) == 'jack'"); break; case '0': script.setCode("basic.stringify(name) == 'never there'"); break; case '!': script.setCode(createDumpConditionCode(conditionName)); break; default: throw new AssertionError(conditionType); } ExpressionType expression = new ExpressionType(); expression.getExpressionEvaluator().add(new ObjectFactory().createScript(script)); VariableBindingDefinitionType source = new VariableBindingDefinitionType(); source.setPath(new ItemPath(UserType.F_NAME).asItemPathType()); MappingType rv = new MappingType(); rv.setName(conditionName); rv.setExpression(expression); rv.getSource().add(source); return rv; } private String createDumpConditionCode(String text) { return "import com.evolveum.midpoint.model.impl.lens.TestAssignmentProcessor2\n\n" + "TestAssignmentProcessor2.startCallback('" + text + "')\n" + "this.binding.variables.each {k,v -> TestAssignmentProcessor2.variableCallback(k, v, '" + text + "')}\n" + "TestAssignmentProcessor2.finishCallback('" + text + "')\n" + "return true"; } private void induce(AbstractRoleType source, AbstractRoleType target, int inducementOrder) { AssignmentType inducement = ObjectTypeUtil.createAssignmentTo(target.asPrismObject()); if (inducementOrder > 1) { inducement.setOrder(inducementOrder); } source.getInducement().add(inducement); } private void assign(AbstractRoleType source, AbstractRoleType target) { AssignmentType assignment = ObjectTypeUtil.createAssignmentTo(target.asPrismObject()); source.getAssignment().add(assignment); } private void assign(AbstractRoleType source, AbstractRoleType target, QName relation) { AssignmentType assignment = ObjectTypeUtil.createAssignmentTo(target.asPrismObject()); assignment.getTargetRef().setRelation(relation); source.getAssignment().add(assignment); } private RoleType createRole(int level, int number) { return prepareAbstractRole(new RoleType(prismContext), createName("R", level, number)); } private RoleType createRole(String name) { return prepareAbstractRole(new RoleType(prismContext), name); } private String createName(String prefix, int level, int number) { return StringUtils.repeat('M', level-1) + prefix + number; } private OrgType createOrg(int number) { return prepareAbstractRole(new OrgType(prismContext), createName("O", 1, number)); } private OrgType createOrg(String name) { return prepareAbstractRole(new OrgType(prismContext), name); } private <R extends AbstractRoleType> R prepareAbstractRole(R abstractRole, String name) { String oid = getRoleOid(name); abstractRole.setName(PolyStringType.fromOrig(name)); abstractRole.setOid(oid); // constructions for (int i = 0; i <= constructionLevels; i++) { ConstructionType c = new ConstructionType(prismContext); c.setDescription(name + "-" + i); c.setResourceRef(ObjectTypeUtil.createObjectRef(RESOURCE_DUMMY_EMPTY_OID, ObjectTypes.RESOURCE)); AssignmentType a = new AssignmentType(prismContext); a.setDescription("Assignment for " + c.getDescription()); a.setConstruction(c); addAssignmentOrInducement(abstractRole, i, a); } // focus mappings for (int i = 0; i <= focusMappingLevels; i++) { MappingType mapping = new MappingType(); mapping.setName(name + "-" + i); VariableBindingDefinitionType source = new VariableBindingDefinitionType(); source.setPath(new ItemPath(UserType.F_NAME).asItemPathType()); mapping.getSource().add(source); VariableBindingDefinitionType target = new VariableBindingDefinitionType(); target.setPath(new ItemPath(UserType.F_DESCRIPTION).asItemPathType()); mapping.setTarget(target); MappingsType mappings = new MappingsType(prismContext); mappings.getMapping().add(mapping); AssignmentType a = new AssignmentType(prismContext); a.setFocusMappings(mappings); addAssignmentOrInducement(abstractRole, i, a); } // policy rules for (int i = 0; i <= policyRulesLevels; i++) { PolicyRuleType rule = new PolicyRuleType(prismContext); rule.setName(name + "-" + i); AssignmentType a = new AssignmentType(prismContext); a.setPolicyRule(rule); addAssignmentOrInducement(abstractRole, i, a); } // authorization AuthorizationType authorization = new AuthorizationType(prismContext); authorization.getAction().add(name); abstractRole.getAuthorization().add(authorization); // admin gui config AdminGuiConfigurationType guiConfig = new AdminGuiConfigurationType(); guiConfig.setPreferredDataLanguage(name); abstractRole.setAdminGuiConfiguration(guiConfig); return abstractRole; } private <R extends AbstractRoleType> void addAssignmentOrInducement(R abstractRole, int order, AssignmentType assignment) { if (order == 0) { abstractRole.getAssignment().add(assignment); } else { assignment.setOrder(order); abstractRole.getInducement().add(assignment); } } private static String getRoleOid(String name) { name = name.substring(0, Math.min(12, name.length())); return "99999999-0000-0000-0000-" + StringUtils.repeat('0', 12-name.length()) + name; } //endregion //region ============================================================= helper methods (asserts) private void assertTargetPath(EvaluatedAssignmentImpl<UserType> evaluatedAssignment, String targetName, String expectedPath) { EvaluatedAssignmentTargetImpl target = evaluatedAssignment.getRoles().getAllValues().stream() .filter(tgt -> targetName.equals(tgt.getTarget().getName().getOrig())) .findFirst().orElseThrow(() -> new AssertionError("Target " + targetName + " is not present")); String realPath = getStringRepresentation(target.getAssignmentPath()); System.out.println("Path for " + targetName + " is: " + realPath); assertEquals("Wrong evaluation order for " + targetName, expectedPath, realPath); } private String getStringRepresentation(AssignmentPathImpl path) { return getStringRepresentation(path.last().getEvaluationOrder()); } private String getStringRepresentation(EvaluationOrder order) { List<String> names = new ArrayList<>(); for (QName relation : order.getRelations()) { int count = order.getMatchingRelationOrder(relation); if (count == 0) { continue; } else if (count < 0) { fail("Negative count for " + relation + " in " + order); } while (count-- > 0) { names.add(relation.getLocalPart()); } } names.sort(String::compareTo); return StringUtils.join(names, " "); } private void assertMembershipRef(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String text) { assertPrismRefValues("membershipRef", evaluatedAssignment.getMembershipRefVals(), findObjects(text)); } private void assertDelegation(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String text) { assertPrismRefValues("delegationRef", evaluatedAssignment.getDelegationRefVals(), findObjects(text)); } private void assertOrgRef(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String text) { assertPrismRefValues("orgRef", evaluatedAssignment.getOrgRefVals(), findObjects(text)); } private void assertAuthorizations(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String text) { assertUnsortedListsEquals("Wrong authorizations", getList(text), evaluatedAssignment.getAuthorizations(), a -> a.getAction().get(0)); } private void assertGuiConfig(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String text) { assertUnsortedListsEquals("Wrong gui configurations", getList(text), evaluatedAssignment.getAdminGuiConfigurations(), g -> g.getPreferredDataLanguage()); } private <T> void assertUnsortedListsEquals(String message, Collection<String> expected, Collection<T> real, Function<T, String> nameExtractor) { Bag<String> expectedAsBag = new TreeBag<>(CollectionUtils.emptyIfNull(expected)); Bag<String> realAsBag = new TreeBag<>(real.stream().map(nameExtractor).collect(Collectors.toList())); assertEquals(message, expectedAsBag, realAsBag); } private void assertFocusMappings(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String expectedItems) { assertFocusMappings(evaluatedAssignment, getList(expectedItems)); } private void assertFocusMappings(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, Collection<String> expectedItems) { assertUnsortedListsEquals("Wrong focus mappings", expectedItems, evaluatedAssignment.getFocusMappings(), m -> m.getMappingType().getName()); // TODO look at the content of the mappings (e.g. zero, plus, minus sets) } private void assertFocusPolicyRules(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String expectedItems) { assertFocusPolicyRules(evaluatedAssignment, getList(expectedItems)); } private void assertFocusPolicyRules(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, Collection<String> expectedItems) { assertUnsortedListsEquals("Wrong focus policy rules", expectedItems, evaluatedAssignment.getFocusPolicyRules(), r -> r.getName()); } private void assertTargetPolicyRules(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String expectedThisTargetItems, String expectedOtherTargetsItems) { assertTargetPolicyRules(evaluatedAssignment, getList(expectedThisTargetItems), getList(expectedOtherTargetsItems)); } private void assertTargetPolicyRules(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, Collection<String> expectedThisTargetItems, Collection<String> expectedOtherTargetsItems) { expectedOtherTargetsItems = CollectionUtils.emptyIfNull(expectedOtherTargetsItems); expectedThisTargetItems = CollectionUtils.emptyIfNull(expectedThisTargetItems); assertUnsortedListsEquals("Wrong other targets policy rules", expectedOtherTargetsItems, evaluatedAssignment.getOtherTargetsPolicyRules(), r -> r.getName()); assertUnsortedListsEquals("Wrong this target policy rules", expectedThisTargetItems, evaluatedAssignment.getThisTargetPolicyRules(), r -> r.getName()); } private void assertTargets(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, Boolean evaluateConstructions, String zeroValid, String zeroInvalid, String plusValid, String plusInvalid, String minusValid, String minusInvalid) { assertTargets(evaluatedAssignment, evaluateConstructions, getList(zeroValid), getList(zeroInvalid), getList(plusValid), getList(plusInvalid), getList(minusValid), getList(minusInvalid)); } private void assertTargets(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, Boolean evaluateConstructions, List<String> zeroValid, List<String> zeroInvalid, List<String> plusValid, List<String> plusInvalid, List<String> minusValid, List<String> minusInvalid) { assertTargets("zero", evaluatedAssignment.getRoles().getZeroSet(), evaluateConstructions, zeroValid, zeroInvalid); assertTargets("plus", evaluatedAssignment.getRoles().getPlusSet(), evaluateConstructions, plusValid, plusInvalid); assertTargets("minus", evaluatedAssignment.getRoles().getMinusSet(), evaluateConstructions, minusValid, minusInvalid); } private void assertTargets(String type, Collection<EvaluatedAssignmentTargetImpl> targets, Boolean evaluateConstructions, List<String> expectedValid, List<String> expectedInvalid) { targets = CollectionUtils.emptyIfNull(targets); Collection<EvaluatedAssignmentTargetImpl> realValid = targets.stream() .filter(t -> t.isValid() && matchesConstructions(t, evaluateConstructions)).collect(Collectors.toList()); Collection<EvaluatedAssignmentTargetImpl> realInvalid = targets.stream() .filter(t -> !t.isValid() && matchesConstructions(t, evaluateConstructions)).collect(Collectors.toList()); String ec = evaluateConstructions != null ? " (evaluateConstructions: " + evaluateConstructions + ")" : ""; assertUnsortedListsEquals("Wrong valid targets in " + type + " set" + ec, expectedValid, realValid, t -> t.getTarget().getName().getOrig()); assertUnsortedListsEquals("Wrong invalid targets in " + type + " set" + ec, expectedInvalid, realInvalid, t -> t.getTarget().getName().getOrig()); } private boolean matchesConstructions(EvaluatedAssignmentTargetImpl t, Boolean evaluateConstructions) { return evaluateConstructions == null || t.isEvaluateConstructions() == evaluateConstructions; } private void assertConstructions(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, String zeroValid, String zeroInvalid, String plusValid, String plusInvalid, String minusValid, String minusInvalid) { assertConstructions(evaluatedAssignment, getList(zeroValid), getList(zeroInvalid), getList(plusValid), getList(plusInvalid), getList(minusValid), getList(minusInvalid)); } private void assertConstructions(EvaluatedAssignmentImpl<? extends FocusType> evaluatedAssignment, List<String> zeroValid, List<String> zeroInvalid, List<String> plusValid, List<String> plusInvalid, List<String> minusValid, List<String> minusInvalid) { assertConstructions("zero", evaluatedAssignment.getConstructionSet(PlusMinusZero.ZERO), zeroValid, zeroInvalid); assertConstructions("plus", evaluatedAssignment.getConstructionSet(PlusMinusZero.PLUS), plusValid, plusInvalid); assertConstructions("minus", evaluatedAssignment.getConstructionSet(PlusMinusZero.MINUS), minusValid, minusInvalid); } private void assertConstructions(String type, Collection<? extends Construction<? extends FocusType>> constructions, List<String> valid0, List<String> invalid0) { constructions = CollectionUtils.emptyIfNull(constructions); Collection<String> expectedValid = CollectionUtils.emptyIfNull(valid0); Collection<String> expectedInvalid = CollectionUtils.emptyIfNull(invalid0); Collection<Construction<? extends FocusType>> realValid = constructions.stream().filter(c -> c.isValid()).collect(Collectors.toList()); Collection<Construction<? extends FocusType>> realInvalid = constructions.stream().filter(c -> !c.isValid()).collect(Collectors.toList()); assertUnsortedListsEquals("Wrong valid constructions in " + type + " set", expectedValid, realValid, c -> c.getDescription()); assertUnsortedListsEquals("Wrong invalid constructions in " + type + " set", expectedInvalid, realInvalid, c -> c.getDescription()); } @SuppressWarnings("unchecked") private <F extends FocusType> Collection<EvaluatedAssignmentImpl<F>> assertAssignmentTripleSetSize(LensContext<F> context, int zero, int plus, int minus) { assertEquals("Wrong size of assignment triple zero set", zero, CollectionUtils.size(context.getEvaluatedAssignmentTriple().getZeroSet())); assertEquals("Wrong size of assignment triple plus set", plus, CollectionUtils.size(context.getEvaluatedAssignmentTriple().getPlusSet())); assertEquals("Wrong size of assignment triple minus set", minus, CollectionUtils.size(context.getEvaluatedAssignmentTriple().getMinusSet())); return (Collection) context.getEvaluatedAssignmentTriple().getAllValues(); } //endregion //region ============================================================= helper methods (misc) private <F extends FocusType> List<Construction<F>> getConstructions(EvaluatedAssignmentImpl<F> evaluatedAssignment, String name) { return evaluatedAssignment.getConstructionTriple().getAllValues().stream() .filter(c -> name.equals(c.getDescription())) .collect(Collectors.toList()); } private AssignmentType findAssignmentOrInducement(String assignmentText) { String[] split = StringUtils.split(assignmentText, "-"); AbstractRoleType source = findRole(split[0]); AbstractRoleType target = findRole(split[1]); return findAssignmentOrInducement(source, target); } private AssignmentType findAssignmentOrInducement(AbstractRoleType source, AbstractRoleType target) { return Stream.concat(source.getAssignment().stream(), source.getInducement().stream()) .filter(a -> a.getTargetRef() != null && target.getOid().equals(a.getTargetRef().getOid())) .findFirst() .orElseThrow(() -> new IllegalStateException(source + " contains no assignment/inducement to " + target)); } private AbstractRoleType findRole(String name) { return (AbstractRoleType) findObject(name); } private ObjectType findObject(String name) { return objects.stream().filter(r -> name.equals(r.getName().getOrig())).findFirst() .orElseThrow(() -> new IllegalStateException("No role " + name)); } private List<ObjectType> findObjects(String text) { return getList(text).stream().map(n -> findObject(n)).collect(Collectors.toList()); } private List<String> getList(String text) { if (text == null) { return Collections.emptyList(); } List<String> rv = new ArrayList<>(); for (String t : StringUtils.split(text)) { rv.add(t.replace('_', ' ')); } return rv; } //endregion }