From 869876180973d644162012fa3d0001bcf1f76d84 Mon Sep 17 00:00:00 2001 From: honchar Date: Wed, 9 Mar 2016 14:23:00 +0100 Subject: [PATCH 1/4] Request a role panel: added properties to search --- .../evolveum/midpoint/web/component/search/SearchFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchFactory.java index fa855104f69..d81e163a83d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchFactory.java @@ -46,6 +46,9 @@ public class SearchFactory { new ItemPath(UserType.F_COST_CENTER))); SEARCHABLE_OBJECTS.put(RoleType.class, Arrays.asList( new ItemPath(RoleType.F_NAME), + new ItemPath(RoleType.F_DISPLAY_NAME), +// new ItemPath(RoleType.F_OWNER_REF), + new ItemPath(RoleType.F_REQUESTABLE), new ItemPath(RoleType.F_ROLE_TYPE))); //todo add other object types and properties which can be used in search From 161f98ef5b28ef5d16b8b76d7f14af8979ebd1af Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Thu, 10 Mar 2016 13:28:32 +0100 Subject: [PATCH 2/4] dynamic resource(s) - support for filters in construction (role assignments) --- .../midpoint/prism/PrismReferenceValue.java | 2 +- .../midpoint/schema/util/ObjectTypeUtil.java | 17 + .../functions/BasicExpressionFunctions.java | 13 + .../model/impl/lens/AssignmentEvaluator.java | 84 ++- .../model/impl/lens/Construction.java | 71 +- .../midpoint/model/impl/util/Utils.java | 27 + .../lens/TestAbstractAssignmentEvaluator.java | 678 ++++++++++++++++++ .../impl/lens/TestAssignmentEvaluator.java | 638 +--------------- .../lens/TestAssignmentEvaluatorDynamic.java | 137 ++++ .../resources/lens/role-corp-contractor.xml | 5 + .../resources/lens/role-corp-customer.xml | 5 + .../resources/lens/role-corp-employee.xml | 5 + .../resources/lens/role-corp-engineer.xml | 5 + .../role-corp-generic-metarole-dynamic.xml | 71 ++ .../lens/role-corp-job-metarole-dynamic.xml | 74 ++ .../test/resources/lens/role-corp-manager.xml | 5 + .../test/resources/lens/role-corp-visitor.xml | 5 + .../src/test/resources/schema/piracy.xsd | 17 + model/model-impl/testng-unit.xml | 1 + .../midpoint/repo/sql/AddGetObjectTest.java | 81 ++- .../common/embedded/REmbeddedReference.java | 3 +- samples/rest/modify-user-assign-role.xml | 12 + 22 files changed, 1304 insertions(+), 652 deletions(-) create mode 100644 model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAbstractAssignmentEvaluator.java create mode 100644 model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluatorDynamic.java create mode 100644 model/model-impl/src/test/resources/lens/role-corp-generic-metarole-dynamic.xml create mode 100644 model/model-impl/src/test/resources/lens/role-corp-job-metarole-dynamic.xml create mode 100644 samples/rest/modify-user-assign-role.xml diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java index 38132fdccab..ab2ff5fd1e7 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java @@ -324,7 +324,7 @@ public void checkConsistenceInternal(Itemable rootItem, boolean requireDefinitio @Override public boolean isEmpty() { - return oid == null && object == null; + return oid == null && object == null && filter == null; } /** diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java index 1fb62b7bddc..07426f51224 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java @@ -84,6 +84,23 @@ public static Collection getExtensionPropertyValues(ObjectType objectType } return property.getRealValues(); } + + public static Collection getExtensionReferenceValues(ObjectType objectType, QName propertyQname) { + PrismObject object = objectType.asPrismObject(); + PrismContainer extensionContainer = object.findContainer(ObjectType.F_EXTENSION); + if (extensionContainer == null) { + return null; + } + PrismReference property = extensionContainer.findReference(propertyQname); + if (property == null) { + return null; + } + Collection refs = new ArrayList(property.getValues().size()); + for (PrismReferenceValue refVal : property.getValues()){ + refs.add(refVal.asReferencable()); + } + return refs; + } public static ObjectReferenceType findRef(String oid, List refs) { diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/BasicExpressionFunctions.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/BasicExpressionFunctions.java index dc8367a7225..47e0fbe56ad 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/BasicExpressionFunctions.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/BasicExpressionFunctions.java @@ -48,6 +48,7 @@ import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.prism.path.ItemPath; @@ -354,6 +355,10 @@ public T getExtensionPropertyValue(ObjectType object, String namespace, Stri return getExtensionPropertyValue(object, new javax.xml.namespace.QName(namespace, localPart)); } + public Referencable getExtensionReferenceValue(ObjectType object, String namespace, String localPart) throws SchemaException { + return getExtensionReferenceValue(object, new javax.xml.namespace.QName(namespace, localPart)); + } + public T getExtensionPropertyValue(ObjectType object, groovy.xml.QName propertyQname) throws SchemaException { return getExtensionPropertyValue(object, propertyQname.getNamespaceURI(), propertyQname.getLocalPart()); } @@ -366,6 +371,14 @@ public T getExtensionPropertyValue(ObjectType object, javax.xml.namespace.QN return toSingle(values, "a multi-valued extension property "+propertyQname); } + public Referencable getExtensionReferenceValue(ObjectType object, javax.xml.namespace.QName propertyQname) throws SchemaException { + if (object == null) { + return null; + } + Collection values = ObjectTypeUtil.getExtensionReferenceValues(object, propertyQname); + return toSingle(values, "a multi-valued extension property "+propertyQname); + } + public T getPropertyValue(ObjectType object, String path) throws SchemaException { Collection values = getPropertyValues(object, path); return toSingle(values, "a multi-valued property "+path); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java index d097eead23b..d6fbf538a74 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java @@ -15,10 +15,6 @@ */ package com.evolveum.midpoint.model.impl.lens; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; @@ -26,31 +22,32 @@ import com.evolveum.midpoint.model.api.PolicyViolationException; import com.evolveum.midpoint.model.api.context.EvaluatedAssignment; import com.evolveum.midpoint.model.common.expression.ExpressionUtil; +import com.evolveum.midpoint.model.common.expression.ExpressionVariables; import com.evolveum.midpoint.model.common.expression.ItemDeltaItem; import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject; import com.evolveum.midpoint.model.common.mapping.Mapping; import com.evolveum.midpoint.model.common.mapping.MappingFactory; import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator; +import com.evolveum.midpoint.model.impl.util.Utils; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.OriginType; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContainerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.OriginType; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.delta.DeltaSetTriple; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PlusMinusZero; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.parser.QueryConvertor; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; @@ -60,29 +57,23 @@ import com.evolveum.midpoint.security.api.Authorization; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.util.Transformer; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExclusionPolicyConstraintType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType; import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyConstraintsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TimeIntervalStatusType; +import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; /** * @author semancik @@ -392,19 +383,30 @@ private void evaluateFocusMappings(EvaluatedAssignmentImpl evaluatedAssignmen private PrismObject resolveTarget(AssignmentType assignmentType, ObjectType source, String sourceDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { ObjectReferenceType targetRef = assignmentType.getTargetRef(); String oid = targetRef.getOid(); - if (oid == null) { - throw new SchemaException("The OID is null in assignment targetRef in "+source); - } + // Target is referenced, need to fetch it - Class clazz = null; - if (targetRef.getType() != null) { - clazz = (Class) prismContext.getSchemaRegistry().determineCompileTimeClass(targetRef.getType()); - if (clazz == null) { - throw new SchemaException("Cannot determine type from " + targetRef.getType() + " in target reference in " + assignmentType + " in " + sourceDescription); + Class clazz = null; + if (targetRef.getType() != null) { + clazz = (Class) prismContext.getSchemaRegistry().determineCompileTimeClass(targetRef.getType()); + if (clazz == null) { + throw new SchemaException("Cannot determine type from " + targetRef.getType() + " in target reference in " + assignmentType + " in " + sourceDescription); + } + } else { + throw new SchemaException("Missing type in target reference in " + assignmentType + " in " + sourceDescription); + } + + if (oid == null) { + + if (targetRef.getFilter() == null){ + throw new SchemaException("The OID and filter are both null in assignment targetRef in "+source); } - } else { - throw new SchemaException("Missing type in target reference in " + assignmentType + " in " + sourceDescription); + + PrismObject target = resolveTarget(clazz, source, targetRef.getFilter(), sourceDescription, task, result); + assignmentType.getTargetRef().setOid(target.getOid()); + // Handling ObjectNotFoundException - we just pass it to the caller + } + PrismObject target = null; target = repository.getObject(clazz, oid, null, result); if (target == null) { @@ -414,6 +416,34 @@ private PrismObject resolveTarget(AssignmentType assignmentType, ObjectType s return target; } + + private PrismObject resolveTarget(Class clazz, ObjectType source, SearchFilterType filter, String sourceDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException{ +// SearchFilterType filter = targetRef.getFilter(); + ExpressionVariables variables = Utils.getDefaultExpressionVariables(source, null, null, LensUtil.getSystemConfiguration(lensContext, repository, result).asObjectable()); + + ObjectFilter origFilter = QueryConvertor.parseFilter(filter, clazz, prismContext); + ObjectFilter evaluatedFilter = ExpressionUtil.evaluateFilterExpressions(origFilter, variables, getMappingFactory().getExpressionFactory(), prismContext, " evaluating resource filter expression ", task, result); + + if (evaluatedFilter == null){ + throw new SchemaException("The OID is null and filter could not be evaluated in assignment targetRef in "+source); + } + + + SearchResultList results = repository.searchObjects(clazz, ObjectQuery.createObjectQuery(evaluatedFilter), null, result); + + if (org.apache.commons.collections.CollectionUtils.isEmpty(results)){ + throw new IllegalArgumentException("Got null target from repository, filter:"+evaluatedFilter+", class:"+clazz+" (should not happen, probably a bug) in "+sourceDescription); + } + + if (results.size() > 1){ + throw new IllegalArgumentException("Got more than one target from repository, filter:"+evaluatedFilter+", class:"+clazz+" (should not happen, probably a bug) in "+sourceDescription); + } + + PrismObject target = (PrismObject) results.iterator().next(); + +// assignmentType.getTargetRef().setOid(target.getOid()); + return target; + } private void evaluateTarget(EvaluatedAssignmentImpl assignment, AssignmentPathSegment assignmentPathSegment, diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java index de857589a05..20a12edfd08 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java @@ -27,11 +27,14 @@ import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.model.common.expression.ExpressionUtil; +import com.evolveum.midpoint.model.common.expression.ExpressionVariables; import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject; import com.evolveum.midpoint.model.common.mapping.Mapping; import com.evolveum.midpoint.model.common.mapping.MappingFactory; import com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer; import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator; +import com.evolveum.midpoint.model.impl.util.Utils; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Definition; import com.evolveum.midpoint.prism.Item; @@ -47,7 +50,12 @@ import com.evolveum.midpoint.prism.OriginType; import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.parser.QueryConvertor; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.util.ItemPathUtil; +import com.evolveum.midpoint.schema.ResultHandler; +import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; import com.evolveum.midpoint.schema.result.OperationResult; @@ -80,6 +88,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; /** * Live class that contains "construction" - a definition how to construct a resource object. It in fact reflects @@ -310,6 +319,52 @@ public AssignmentPath getAssignmentPath() { public void setAssignmentPath(AssignmentPath assignmentPath) { this.assignmentPath = assignmentPath; } + + private ResourceType resolveTarget(String sourceDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException{ +// SearchFilterType filter = targetRef.getFilter(); + ExpressionVariables variables = Utils.getDefaultExpressionVariables(focusOdo.getNewObject().asObjectable(), null, null, null); + variables.addVariableDefinition(ExpressionConstants.VAR_IMMEDIATE_ROLE, assignmentPathVariables.getImmediateRole()); + variables.addVariableDefinition(ExpressionConstants.VAR_IMMEDIATE_ASSIGNMENT, assignmentPathVariables.getImmediateAssignment()); + variables.addVariableDefinition(ExpressionConstants.VAR_THIS_ASSIGNMENT, assignmentPathVariables.getThisAssignment()); + variables.addVariableDefinition(ExpressionConstants.VAR_FOCUS_ASSIGNMENT, assignmentPathVariables.getFocusAssignment()); + LOGGER.info("Expression valriables for filter evaluation: {}", variables); + + + ObjectFilter origFilter = QueryConvertor.parseFilter(constructionType.getResourceRef().getFilter(), ResourceType.class, prismContext); + LOGGER.info("Orig filter {}", origFilter); + ObjectFilter evaluatedFilter = ExpressionUtil.evaluateFilterExpressions(origFilter, variables, getMappingFactory().getExpressionFactory(), prismContext, " evaluating resource filter expression ", task, result); + LOGGER.info("evaluatedFilter filter {}", evaluatedFilter); + + if (evaluatedFilter == null){ + throw new SchemaException("The OID is null and filter could not be evaluated in assignment targetRef in "+source); + } + + + + final Collection> results = new ArrayList<>(); + ResultHandler handler = new ResultHandler() { + + @Override + public boolean handle(PrismObject object, OperationResult parentResult) { + LOGGER.info("Found object {}", object); + return results.add(object); + } + }; + objectResolver.searchIterative(ResourceType.class, ObjectQuery.createObjectQuery(evaluatedFilter), null, handler, task, result); + + if (org.apache.commons.collections.CollectionUtils.isEmpty(results)){ + throw new IllegalArgumentException("Got null target from repository, filter:"+evaluatedFilter+", class:"+ResourceType.class+" (should not happen, probably a bug) in "+sourceDescription); + } + + if (results.size() > 1){ + throw new IllegalArgumentException("Got more than one target from repository, filter:"+evaluatedFilter+", class:"+ResourceType.class+" (should not happen, probably a bug) in "+sourceDescription); + } + + PrismObject target = results.iterator().next(); + +// assignmentType.getTargetRef().setOid(target.getOid()); + return target.asObjectable(); + } public ResourceType getResource(Task task, OperationResult result) throws ObjectNotFoundException, SchemaException { if (resource == null) { @@ -317,23 +372,31 @@ public ResourceType getResource(Task task, OperationResult result) throws Object resource = constructionType.getResource(); } else if (constructionType.getResourceRef() != null) { try { - resource = LensUtil.getResource(lensContext, constructionType.getResourceRef().getOid(), objectResolver, task, result); + + if (constructionType.getResourceRef().getOid() == null){ + resource = resolveTarget(" resolving resource ", task, result); + } else { + resource = LensUtil.getResource(lensContext, constructionType.getResourceRef().getOid(), objectResolver, task, result); + } } catch (ObjectNotFoundException e) { throw new ObjectNotFoundException("Resource reference seems to be invalid in account construction in " + source + ": "+e.getMessage(), e); } catch (SecurityViolationException|CommunicationException|ConfigurationException e) { throw new SystemException("Couldn't fetch the resource in account construction in " + source + ": " + e.getMessage(), e); + } catch (ExpressionEvaluationException e) { + throw new SystemException("Couldn't evaluate filter expression for the resource in account construction in " + source + ": " + e.getMessage(), e); } } if (resource == null) { - throw new SchemaException("No resource set in account construction in " + source); + throw new SchemaException("No resource set in account construction in " + source + ", resource : " + constructionType.getResource() + ", resourceRef: " + constructionType.getResourceRef()); } + constructionType.getResourceRef().setOid(resource.getOid()); } return resource; } public void evaluate(Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { - evaluateKindIntentObjectClass(task, result); assignmentPathVariables = LensUtil.computeAssignmentPathVariables(assignmentPath); + evaluateKindIntentObjectClass(task, result); evaluateAttributes(task, result); evaluateAssociations(task, result); } @@ -347,7 +410,7 @@ private void evaluateKindIntentObjectClass(Task task, OperationResult result) th resourceOid = constructionType.getResource().getOid(); } ResourceType resource = getResource(task, result); - if (!resource.getOid().equals(resourceOid)) { + if (resourceOid != null && !resource.getOid().equals(resourceOid)) { throw new IllegalStateException("The specified resource and the resource in construction does not match"); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/Utils.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/Utils.java index 1182b1e907a..7a4fc76581a 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/Utils.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/Utils.java @@ -48,10 +48,13 @@ import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.parser.QueryConvertor; +import com.evolveum.midpoint.prism.query.InOidFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; +import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.provisioning.api.ProvisioningService; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.GetOperationOptions; @@ -121,6 +124,8 @@ private Utils() { // ObjectReferenceType resourceRef = shadow.getResourceRef(); // return provisioning.getObject(ResourceType.class, resourceRef.getOid(), null, null, result).asObjectable(); // } + + @Deprecated // use RepositoryService.objectSearchIterative instead public static void searchIterative(RepositoryService repositoryService, Class type, ObjectQuery query, @@ -315,6 +320,12 @@ private static void resolveRef(PrismReferenceValue refVal, RepositoryService rep result.recordFatalError("Missing definition of type of reference " + refName); return; } + + if (containExpression(objFilter)){ + result.recordSuccessIfUnknown(); + return; + } + try { ObjectQuery query = ObjectQuery.createObjectQuery(objFilter); objects = (List)repository.searchObjects(type, query, null, result); @@ -343,6 +354,22 @@ private static void resolveRef(PrismReferenceValue refVal, RepositoryService rep refVal.setOid(oid); result.recordSuccessIfUnknown(); } + + private static boolean containExpression(ObjectFilter filter){ + if (filter == null){ + return false; + } + + if (filter instanceof InOidFilter && ((InOidFilter) filter).getExpression() != null){ + return true; + } + + if (filter instanceof PropertyValueFilter && ((PropertyValueFilter) filter).getExpression() != null){ + return true; + } + + return false; + } public static ObjectClassComplexTypeDefinition determineObjectClass(RefinedResourceSchema refinedSchema, Task task) throws SchemaException { diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAbstractAssignmentEvaluator.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAbstractAssignmentEvaluator.java new file mode 100644 index 00000000000..68d95a43dbc --- /dev/null +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAbstractAssignmentEvaluator.java @@ -0,0 +1,678 @@ +package com.evolveum.midpoint.model.impl.lens; + +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.MINUS; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.PLUS; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.ZERO; +import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.xml.namespace.QName; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.common.ActivationComputer; +import com.evolveum.midpoint.common.Clock; +import com.evolveum.midpoint.model.common.expression.ItemDeltaItem; +import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject; +import com.evolveum.midpoint.model.common.mapping.Mapping; +import com.evolveum.midpoint.model.common.mapping.MappingFactory; +import com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer; +import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PlusMinusZero; +import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectResolver; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + + +@ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public abstract class TestAbstractAssignmentEvaluator extends AbstractLensTest{ + + @Autowired(required=true) + private RepositoryService repositoryService; + + @Autowired(required=true) + private ObjectResolver objectResolver; + + @Autowired(required=true) + private Clock clock; + + @Autowired(required=true) + private ActivationComputer activationComputer; + + @Autowired(required=true) + private MappingFactory mappingFactory; + + @Autowired(required=true) + private MappingEvaluator mappingEvaluator; + + + public abstract File[] getRoleCorpFiles(); + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + } + + + @Test + public void testDirect() throws Exception { + final String TEST_NAME = "testDirect"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_DIRECT_FILE); + + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); + userOdo.recompute(); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment", evaluatedAssignment.debugDump()); + assertEquals(1, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); + display("Evaluated construction", construction); + assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + @Test + public void testDirectExpression() throws Exception { + final String TEST_NAME = "testDirectExpression"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_DIRECT_EXPRESSION_FILE); + + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); + userOdo.recompute(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment", evaluatedAssignment); + assertEquals(1, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); + assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + @Test + public void testDirectExpressionReplaceDescription() throws Exception { + final String TEST_NAME = "testDirectExpressionReplaceDescription"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject user = userTypeJack.asPrismObject().clone(); + AssignmentType assignmentType = unmarshallValueFromFile(ASSIGNMENT_DIRECT_EXPRESSION_FILE, AssignmentType.class); + user.asObjectable().getAssignment().add(assignmentType.clone()); + + // We need to make sure that the assignment has a parent + PrismContainerDefinition assignmentContainerDefinition = user.getDefinition().findContainerDefinition(UserType.F_ASSIGNMENT); + PrismContainer assignmentContainer = assignmentContainerDefinition.instantiate(); + assignmentContainer.add(assignmentType.asPrismContainerValue().clone()); + + ItemPath path = new ItemPath( + new NameItemPathSegment(UserType.F_ASSIGNMENT), + new IdItemPathSegment(123L), + new NameItemPathSegment(AssignmentType.F_DESCRIPTION)); + ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, + path, prismContext, "captain"); + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); + userOdo.recompute(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.setSubItemDeltas((Collection)userDelta.getModifications()); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment); + assertEquals(1,evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(user); + + Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); + assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); + assertEquals(1,construction.getAttributeMappings().size()); + Mapping, PrismPropertyDefinition> attributeMapping = (Mapping, PrismPropertyDefinition>) construction.getAttributeMappings().iterator().next(); + PrismValueDeltaSetTriple> outputTriple = attributeMapping.getOutputTriple(); + PrismAsserts.assertTripleNoZero(outputTriple); + PrismAsserts.assertTriplePlus(outputTriple, "The best captain the world has ever seen"); + PrismAsserts.assertTripleMinus(outputTriple, "The best pirate the world has ever seen"); + + // the same using other words + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO); + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS, "The best captain the world has ever seen"); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS, "The best pirate the world has ever seen"); + assertNoConstruction(evaluatedAssignment, PLUS, "title"); + assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + @Test + public void testDirectExpressionReplaceDescriptionFromNull() throws Exception { + final String TEST_NAME = "testDirectExpressionReplaceDescriptionFromNull"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject user = userTypeJack.asPrismObject().clone(); + AssignmentType assignmentType = unmarshallValueFromFile(ASSIGNMENT_DIRECT_EXPRESSION_FILE, AssignmentType.class); + assignmentType.setDescription(null); + user.asObjectable().getAssignment().add(assignmentType.clone()); + + // We need to make sure that the assignment has a parent + PrismContainerDefinition assignmentContainerDefinition = user.getDefinition().findContainerDefinition(UserType.F_ASSIGNMENT); + PrismContainer assignmentContainer = assignmentContainerDefinition.instantiate(); + assignmentContainer.add(assignmentType.asPrismContainerValue().clone()); + + ItemPath path = new ItemPath( + new NameItemPathSegment(UserType.F_ASSIGNMENT), + new IdItemPathSegment(123L), + new NameItemPathSegment(AssignmentType.F_DESCRIPTION)); + ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, + path, prismContext, "sailor"); + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); + userOdo.recompute(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.setSubItemDeltas((Collection)userDelta.getModifications()); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment); + assertEquals(1,evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(user); + + Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); + assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); + assertEquals(1,construction.getAttributeMappings().size()); + PrismValueDeltaSetTripleProducer, PrismPropertyDefinition> attributeMapping = (PrismValueDeltaSetTripleProducer, PrismPropertyDefinition>) construction.getAttributeMappings().iterator().next(); + PrismValueDeltaSetTriple> outputTriple = attributeMapping.getOutputTriple(); + PrismAsserts.assertTripleNoZero(outputTriple); + PrismAsserts.assertTriplePlus(outputTriple, "The best sailor the world has ever seen"); + PrismAsserts.assertTripleMinus(outputTriple, "The best man the world has ever seen"); + + // the same using other words + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO); + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS, "The best sailor the world has ever seen"); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS, "The best man the world has ever seen"); + assertNoConstruction(evaluatedAssignment, PLUS, "title"); + assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + /* + + Explanation for roles structure (copied from role-corp-generic-metarole.xml) + + user-assignable roles: + + roles of unspecified type + - Visitor + - Customer + + roles of type: job + - Contractor + - Employee + - Engineer (induces Employee) + - Manager (induces Employee) + + metaroles: + + - Generic Metarole: assigned to Visitor and Customer [ induces ri:location attribute - from user/locality ] + - Job Metarole (induces Generic Metarole): assigned to Contractor, Employee, Engineer, Manager [ induces ri:title attribute - from role/name ] + + */ + + @Test + public void testRoleVisitor() throws Exception { + final String TEST_NAME = "testRoleVisitor"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_VISITOR_FILE); + + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); + userOdo.recompute(); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment.debugDump()); + assertEquals(1, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO); + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "title"); + assertNoConstruction(evaluatedAssignment, MINUS, "title"); + assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); + assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "location"); + assertNoConstruction(evaluatedAssignment, MINUS, "location"); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + @Test + public void testRoleEngineer() throws Exception { + final String TEST_NAME = "testRoleEngineer"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_ENGINEER_FILE); + + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); + userOdo.recompute(); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testRoleEngineer", task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment.debugDump()); + assertEquals(4, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee", "Engineer"); + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "title"); + assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); + assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "location"); + assertNoConstruction(evaluatedAssignment, MINUS, "location"); + + assertEquals("Wrong number of admin GUI configs", 1, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + @Test + public void testAddRoleEngineer() throws Exception { + final String TEST_NAME = "testAddRoleEngineer"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject user = userTypeJack.asPrismObject().clone(); + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_ENGINEER_FILE); + + AssignmentType assignmentForUser = assignmentType.clone(); + assignmentForUser.asPrismContainerValue().setParent(null); + ObjectDelta userDelta = ObjectDelta.createModificationAddContainer(UserType.class, USER_JACK_OID, UserType.F_ASSIGNMENT, prismContext, assignmentForUser.asPrismContainerValue()); + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); + userOdo.recompute(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment.debugDump()); + assertEquals("Wrong number of constructions", 4, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + /* + * Here we observe an important thing about AssignmentEvaluator/AssignmentProcessor. + * The evaluator does not consider whether the assignment as such is being added or deleted or stays present. + * In all these cases all the constructions go into the ZERO set of constructions. + * + * However, it considers changes in data that are used by assignments - either in conditions or in mappings. + * Changes of data used in mappings are demonstrated by testDirectExpressionReplaceDescription + * and testDirectExpressionReplaceDescriptionFromNull. Changes of data used in conditions are demonstrated by + * a couple of tests below. + * + * Changes in assignment presence (add/delete) are reflected into plus/minus sets by AssignmentProcessor. + */ + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee", "Engineer"); + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "title"); + assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); + assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "location"); + assertNoConstruction(evaluatedAssignment, MINUS, "location"); + + assertEquals("Wrong number of admin GUI configs", 1, evaluatedAssignment.getAdminGuiConfigurations().size()); + } + + /** + * jack has assigned role Manager. + * + * However, condition in job metarole for Manager is such that it needs "management" + * to be present in user/costCenter in order to be active. + */ + @Test + public void testRoleManagerChangeCostCenter() throws Exception { + final String TEST_NAME = "testRoleManagerChangeCostCenter"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject user = userTypeJack.asPrismObject().clone(); + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_MANAGER_FILE); + + AssignmentType assignmentForUser = assignmentType.clone(); + assignmentForUser.asPrismContainerValue().setParent(null); + user.asObjectable().getAssignment().add(assignmentForUser); + + ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, + UserType.F_COST_CENTER, prismContext, "management"); + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); + userOdo.recompute(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment.debugDump()); + assertEquals(4, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee"); // because Employee's job metarole is active even if Manager's is not + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); + assertConstruction(evaluatedAssignment, PLUS, "title", ZERO, "Manager"); // because Manager's job metarole is originally not active + assertConstruction(evaluatedAssignment, PLUS, "title", PLUS); + assertConstruction(evaluatedAssignment, PLUS, "title", MINUS); + assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); // because Generic Metarole is active all the time + assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "location"); + assertNoConstruction(evaluatedAssignment, MINUS, "location"); + } + + /** + * jack has assigned role Manager. + * + * However, condition in job metarole for Manager is such that it needs "management" + * to be present in user/costCenter in order to be active. + * + * In this test we remove the value of "management" from jack. + */ + @Test + public void testRoleManagerRemoveCostCenter() throws Exception { + final String TEST_NAME = "testRoleManagerRemoveCostCenter"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject user = userTypeJack.asPrismObject().clone(); + user.asObjectable().setCostCenter("management"); + AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_MANAGER_FILE); + + AssignmentType assignmentForUser = assignmentType.clone(); + assignmentForUser.asPrismContainerValue().setParent(null); + user.asObjectable().getAssignment().add(assignmentForUser); + + ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, + UserType.F_COST_CENTER, prismContext); + ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); + userOdo.recompute(); + AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); + assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); + assignmentIdi.recompute(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); + evaluatedAssignment.evaluateConstructions(userOdo, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNotNull(evaluatedAssignment); + display("Evaluated assignment",evaluatedAssignment.debugDump()); + assertEquals(4, evaluatedAssignment.getConstructions().size()); + PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); + + assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee"); // because Employee's job metarole is active even if Manager's is not + assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); + assertConstruction(evaluatedAssignment, MINUS, "title", ZERO, "Manager"); // because Manager's job metarole is not active any more + assertConstruction(evaluatedAssignment, MINUS, "title", PLUS); + assertConstruction(evaluatedAssignment, MINUS, "title", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "title"); + + assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); // because Generic Metarole is active all the time + assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); + assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); + assertNoConstruction(evaluatedAssignment, PLUS, "location"); + assertNoConstruction(evaluatedAssignment, MINUS, "location"); + } + + + + + protected void assertNoConstruction(EvaluatedAssignmentImpl evaluatedAssignment, PlusMinusZero constructionSet, String attributeName) { + Collection> constructions = evaluatedAssignment.getConstructionSet(constructionSet); + for (Construction construction : constructions) { + PrismValueDeltaSetTripleProducer, ? extends PrismPropertyDefinition> mapping = construction.getAttributeMapping(new QName(MidPointConstants.NS_RI, attributeName)); + assertNull("Unexpected mapping for " + attributeName, mapping); + } + } + + + protected void assertConstruction(EvaluatedAssignmentImpl evaluatedAssignment, PlusMinusZero constructionSet, String attributeName, PlusMinusZero attributeSet, String... expectedValues) { + Collection> constructions = evaluatedAssignment.getConstructionSet(constructionSet); + Set realValues = new HashSet<>(); + for (Construction construction : constructions) { + PrismValueDeltaSetTripleProducer, ? extends PrismPropertyDefinition> mapping = construction.getAttributeMapping(new QName(MidPointConstants.NS_RI, attributeName)); + if (mapping != null && mapping.getOutputTriple() != null) { + Collection> valsInMapping = mapping.getOutputTriple().getSet(attributeSet); + if (valsInMapping != null) { + for (PrismPropertyValue value : valsInMapping) { + if (value.getValue() instanceof String) { + realValues.add((String) value.getValue()); + } + } + } + } + } + AssertJUnit.assertEquals("Wrong values", new HashSet(Arrays.asList(expectedValues)), realValues); + } + + protected AssignmentEvaluator createAssignmentEvaluator() throws ObjectNotFoundException, SchemaException { + PrismObject userJack = userTypeJack.asPrismObject(); + return createAssignmentEvaluator(new ObjectDeltaObject(userJack, null, null)); + } + + protected AssignmentEvaluator createAssignmentEvaluator(ObjectDeltaObject focusOdo) throws ObjectNotFoundException, SchemaException { + AssignmentEvaluator assignmentEvaluator = new AssignmentEvaluator<>(); + assignmentEvaluator.setRepository(repositoryService); + assignmentEvaluator.setFocusOdo(focusOdo); + assignmentEvaluator.setObjectResolver(objectResolver); + assignmentEvaluator.setPrismContext(prismContext); + assignmentEvaluator.setActivationComputer(activationComputer); + assignmentEvaluator.setNow(clock.currentTimeXMLGregorianCalendar()); + assignmentEvaluator.setMappingFactory(mappingFactory); + assignmentEvaluator.setMappingEvaluator(mappingEvaluator); + // Fake + assignmentEvaluator.setLensContext(new LensContext<>(UserType.class, prismContext, provisioningService)); + return assignmentEvaluator; + } +} diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java index 3e11d88c730..5bfd2b3777c 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java @@ -85,615 +85,49 @@ */ @ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestAssignmentEvaluator extends AbstractLensTest { - - @Autowired(required=true) - private RepositoryService repositoryService; - - @Autowired(required=true) - private ObjectResolver objectResolver; - - @Autowired(required=true) - private Clock clock; +public class TestAssignmentEvaluator extends TestAbstractAssignmentEvaluator { + +// @Autowired(required=true) +// private RepositoryService repositoryService; +// +// @Autowired(required=true) +// private ObjectResolver objectResolver; +// +// @Autowired(required=true) +// private Clock clock; +// +// @Autowired(required=true) +// private ActivationComputer activationComputer; +// +// @Autowired(required=true) +// private MappingFactory mappingFactory; +// +// @Autowired(required=true) +// private MappingEvaluator mappingEvaluator; + + protected static final File[] ROLE_CORP_FILES = { + ROLE_CORP_GENERIC_METAROLE_FILE, + ROLE_CORP_JOB_METAROLE_FILE, + ROLE_CORP_VISITOR_FILE, + ROLE_CORP_CUSTOMER_FILE, + ROLE_CORP_CONTRACTOR_FILE, + ROLE_CORP_EMPLOYEE_FILE, + ROLE_CORP_ENGINEER_FILE, + ROLE_CORP_MANAGER_FILE + }; - @Autowired(required=true) - private ActivationComputer activationComputer; - - @Autowired(required=true) - private MappingFactory mappingFactory; - - @Autowired(required=true) - private MappingEvaluator mappingEvaluator; - @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); - addObjects(ROLE_CORP_FILES); - } - - @Test - public void testDirect() throws Exception { - final String TEST_NAME = "testDirect"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_DIRECT_FILE); - - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); - userOdo.recompute(); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment", evaluatedAssignment.debugDump()); - assertEquals(1, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); - display("Evaluated construction", construction); - assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); - - assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); - } - - @Test - public void testDirectExpression() throws Exception { - final String TEST_NAME = "testDirectExpression"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_DIRECT_EXPRESSION_FILE); - - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); - userOdo.recompute(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment", evaluatedAssignment); - assertEquals(1, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); - assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); - - assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); - } - - @Test - public void testDirectExpressionReplaceDescription() throws Exception { - final String TEST_NAME = "testDirectExpressionReplaceDescription"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - PrismObject user = userTypeJack.asPrismObject().clone(); - AssignmentType assignmentType = unmarshallValueFromFile(ASSIGNMENT_DIRECT_EXPRESSION_FILE, AssignmentType.class); - user.asObjectable().getAssignment().add(assignmentType.clone()); - - // We need to make sure that the assignment has a parent - PrismContainerDefinition assignmentContainerDefinition = user.getDefinition().findContainerDefinition(UserType.F_ASSIGNMENT); - PrismContainer assignmentContainer = assignmentContainerDefinition.instantiate(); - assignmentContainer.add(assignmentType.asPrismContainerValue().clone()); - - ItemPath path = new ItemPath( - new NameItemPathSegment(UserType.F_ASSIGNMENT), - new IdItemPathSegment(123L), - new NameItemPathSegment(AssignmentType.F_DESCRIPTION)); - ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, - path, prismContext, "captain"); - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); - userOdo.recompute(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.setSubItemDeltas((Collection)userDelta.getModifications()); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment); - assertEquals(1,evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(user); - - Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); - assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); - assertEquals(1,construction.getAttributeMappings().size()); - Mapping, PrismPropertyDefinition> attributeMapping = (Mapping, PrismPropertyDefinition>) construction.getAttributeMappings().iterator().next(); - PrismValueDeltaSetTriple> outputTriple = attributeMapping.getOutputTriple(); - PrismAsserts.assertTripleNoZero(outputTriple); - PrismAsserts.assertTriplePlus(outputTriple, "The best captain the world has ever seen"); - PrismAsserts.assertTripleMinus(outputTriple, "The best pirate the world has ever seen"); - - // the same using other words - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO); - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS, "The best captain the world has ever seen"); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS, "The best pirate the world has ever seen"); - assertNoConstruction(evaluatedAssignment, PLUS, "title"); - assertNoConstruction(evaluatedAssignment, MINUS, "title"); - - assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); + addObjects(getRoleCorpFiles()); } - @Test - public void testDirectExpressionReplaceDescriptionFromNull() throws Exception { - final String TEST_NAME = "testDirectExpressionReplaceDescriptionFromNull"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - PrismObject user = userTypeJack.asPrismObject().clone(); - AssignmentType assignmentType = unmarshallValueFromFile(ASSIGNMENT_DIRECT_EXPRESSION_FILE, AssignmentType.class); - assignmentType.setDescription(null); - user.asObjectable().getAssignment().add(assignmentType.clone()); - - // We need to make sure that the assignment has a parent - PrismContainerDefinition assignmentContainerDefinition = user.getDefinition().findContainerDefinition(UserType.F_ASSIGNMENT); - PrismContainer assignmentContainer = assignmentContainerDefinition.instantiate(); - assignmentContainer.add(assignmentType.asPrismContainerValue().clone()); - - ItemPath path = new ItemPath( - new NameItemPathSegment(UserType.F_ASSIGNMENT), - new IdItemPathSegment(123L), - new NameItemPathSegment(AssignmentType.F_DESCRIPTION)); - ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, - path, prismContext, "sailor"); - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); - userOdo.recompute(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.setSubItemDeltas((Collection)userDelta.getModifications()); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testDirect", task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment); - assertEquals(1,evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(user); - - Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); - assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); - assertEquals(1,construction.getAttributeMappings().size()); - PrismValueDeltaSetTripleProducer, PrismPropertyDefinition> attributeMapping = (PrismValueDeltaSetTripleProducer, PrismPropertyDefinition>) construction.getAttributeMappings().iterator().next(); - PrismValueDeltaSetTriple> outputTriple = attributeMapping.getOutputTriple(); - PrismAsserts.assertTripleNoZero(outputTriple); - PrismAsserts.assertTriplePlus(outputTriple, "The best sailor the world has ever seen"); - PrismAsserts.assertTripleMinus(outputTriple, "The best man the world has ever seen"); - - // the same using other words - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO); - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS, "The best sailor the world has ever seen"); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS, "The best man the world has ever seen"); - assertNoConstruction(evaluatedAssignment, PLUS, "title"); - assertNoConstruction(evaluatedAssignment, MINUS, "title"); - - assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); - } - - /* - - Explanation for roles structure (copied from role-corp-generic-metarole.xml) - - user-assignable roles: - - roles of unspecified type - - Visitor - - Customer - - roles of type: job - - Contractor - - Employee - - Engineer (induces Employee) - - Manager (induces Employee) - - metaroles: - - - Generic Metarole: assigned to Visitor and Customer [ induces ri:location attribute - from user/locality ] - - Job Metarole (induces Generic Metarole): assigned to Contractor, Employee, Engineer, Manager [ induces ri:title attribute - from role/name ] - - */ - - @Test - public void testRoleVisitor() throws Exception { - final String TEST_NAME = "testRoleVisitor"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_VISITOR_FILE); - - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); - userOdo.recompute(); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment.debugDump()); - assertEquals(1, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO); - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "title"); - assertNoConstruction(evaluatedAssignment, MINUS, "title"); - assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); - assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "location"); - assertNoConstruction(evaluatedAssignment, MINUS, "location"); - - assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); - } - - @Test - public void testRoleEngineer() throws Exception { - final String TEST_NAME = "testRoleEngineer"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_ENGINEER_FILE); - - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(userTypeJack.asPrismObject(), null, null); - userOdo.recompute(); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, "testRoleEngineer", task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment.debugDump()); - assertEquals(4, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee", "Engineer"); - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "title"); - assertNoConstruction(evaluatedAssignment, MINUS, "title"); - - assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); - assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "location"); - assertNoConstruction(evaluatedAssignment, MINUS, "location"); - - assertEquals("Wrong number of admin GUI configs", 1, evaluatedAssignment.getAdminGuiConfigurations().size()); - } - - @Test - public void testAddRoleEngineer() throws Exception { - final String TEST_NAME = "testAddRoleEngineer"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - PrismObject user = userTypeJack.asPrismObject().clone(); - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_ENGINEER_FILE); - - AssignmentType assignmentForUser = assignmentType.clone(); - assignmentForUser.asPrismContainerValue().setParent(null); - ObjectDelta userDelta = ObjectDelta.createModificationAddContainer(UserType.class, USER_JACK_OID, UserType.F_ASSIGNMENT, prismContext, assignmentForUser.asPrismContainerValue()); - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); - userOdo.recompute(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment.debugDump()); - assertEquals("Wrong number of constructions", 4, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - /* - * Here we observe an important thing about AssignmentEvaluator/AssignmentProcessor. - * The evaluator does not consider whether the assignment as such is being added or deleted or stays present. - * In all these cases all the constructions go into the ZERO set of constructions. - * - * However, it considers changes in data that are used by assignments - either in conditions or in mappings. - * Changes of data used in mappings are demonstrated by testDirectExpressionReplaceDescription - * and testDirectExpressionReplaceDescriptionFromNull. Changes of data used in conditions are demonstrated by - * a couple of tests below. - * - * Changes in assignment presence (add/delete) are reflected into plus/minus sets by AssignmentProcessor. - */ - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee", "Engineer"); - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "title"); - assertNoConstruction(evaluatedAssignment, MINUS, "title"); - - assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); - assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "location"); - assertNoConstruction(evaluatedAssignment, MINUS, "location"); - - assertEquals("Wrong number of admin GUI configs", 1, evaluatedAssignment.getAdminGuiConfigurations().size()); - } - - /** - * jack has assigned role Manager. - * - * However, condition in job metarole for Manager is such that it needs "management" - * to be present in user/costCenter in order to be active. - */ - @Test - public void testRoleManagerChangeCostCenter() throws Exception { - final String TEST_NAME = "testRoleManagerChangeCostCenter"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - PrismObject user = userTypeJack.asPrismObject().clone(); - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_MANAGER_FILE); - - AssignmentType assignmentForUser = assignmentType.clone(); - assignmentForUser.asPrismContainerValue().setParent(null); - user.asObjectable().getAssignment().add(assignmentForUser); - - ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, - UserType.F_COST_CENTER, prismContext, "management"); - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); - userOdo.recompute(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment.debugDump()); - assertEquals(4, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee"); // because Employee's job metarole is active even if Manager's is not - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); - assertConstruction(evaluatedAssignment, PLUS, "title", ZERO, "Manager"); // because Manager's job metarole is originally not active - assertConstruction(evaluatedAssignment, PLUS, "title", PLUS); - assertConstruction(evaluatedAssignment, PLUS, "title", MINUS); - assertNoConstruction(evaluatedAssignment, MINUS, "title"); - - assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); // because Generic Metarole is active all the time - assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "location"); - assertNoConstruction(evaluatedAssignment, MINUS, "location"); - } - - /** - * jack has assigned role Manager. - * - * However, condition in job metarole for Manager is such that it needs "management" - * to be present in user/costCenter in order to be active. - * - * In this test we remove the value of "management" from jack. - */ - @Test - public void testRoleManagerRemoveCostCenter() throws Exception { - final String TEST_NAME = "testRoleManagerRemoveCostCenter"; - TestUtil.displayTestTile(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestAssignmentEvaluator.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - PrismObject user = userTypeJack.asPrismObject().clone(); - user.asObjectable().setCostCenter("management"); - AssignmentType assignmentType = getAssignmentType(ASSIGNMENT_ROLE_MANAGER_FILE); - - AssignmentType assignmentForUser = assignmentType.clone(); - assignmentForUser.asPrismContainerValue().setParent(null); - user.asObjectable().getAssignment().add(assignmentForUser); - - ObjectDelta userDelta = ObjectDelta.createModificationReplaceProperty(UserType.class, USER_JACK_OID, - UserType.F_COST_CENTER, prismContext); - ObjectDeltaObject userOdo = new ObjectDeltaObject<>(user, userDelta, null); - userOdo.recompute(); - AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(userOdo); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); - assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.recompute(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - EvaluatedAssignmentImpl evaluatedAssignment = assignmentEvaluator.evaluate(assignmentIdi, false, userTypeJack, TEST_NAME, task, result); - evaluatedAssignment.evaluateConstructions(userOdo, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNotNull(evaluatedAssignment); - display("Evaluated assignment",evaluatedAssignment.debugDump()); - assertEquals(4, evaluatedAssignment.getConstructions().size()); - PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); - - assertConstruction(evaluatedAssignment, ZERO, "title", ZERO, "Employee"); // because Employee's job metarole is active even if Manager's is not - assertConstruction(evaluatedAssignment, ZERO, "title", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "title", MINUS); - assertConstruction(evaluatedAssignment, MINUS, "title", ZERO, "Manager"); // because Manager's job metarole is not active any more - assertConstruction(evaluatedAssignment, MINUS, "title", PLUS); - assertConstruction(evaluatedAssignment, MINUS, "title", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "title"); - - assertConstruction(evaluatedAssignment, ZERO, "location", ZERO, "Caribbean"); // because Generic Metarole is active all the time - assertConstruction(evaluatedAssignment, ZERO, "location", PLUS); - assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); - assertNoConstruction(evaluatedAssignment, PLUS, "location"); - assertNoConstruction(evaluatedAssignment, MINUS, "location"); - } - - private void assertNoConstruction(EvaluatedAssignmentImpl evaluatedAssignment, PlusMinusZero constructionSet, String attributeName) { - Collection> constructions = evaluatedAssignment.getConstructionSet(constructionSet); - for (Construction construction : constructions) { - PrismValueDeltaSetTripleProducer, ? extends PrismPropertyDefinition> mapping = construction.getAttributeMapping(new QName(MidPointConstants.NS_RI, attributeName)); - assertNull("Unexpected mapping for " + attributeName, mapping); - } - } - - private void assertConstruction(EvaluatedAssignmentImpl evaluatedAssignment, PlusMinusZero constructionSet, String attributeName, PlusMinusZero attributeSet, String... expectedValues) { - Collection> constructions = evaluatedAssignment.getConstructionSet(constructionSet); - Set realValues = new HashSet<>(); - for (Construction construction : constructions) { - PrismValueDeltaSetTripleProducer, ? extends PrismPropertyDefinition> mapping = construction.getAttributeMapping(new QName(MidPointConstants.NS_RI, attributeName)); - if (mapping != null && mapping.getOutputTriple() != null) { - Collection> valsInMapping = mapping.getOutputTriple().getSet(attributeSet); - if (valsInMapping != null) { - for (PrismPropertyValue value : valsInMapping) { - if (value.getValue() instanceof String) { - realValues.add((String) value.getValue()); - } - } - } - } - } - AssertJUnit.assertEquals("Wrong values", new HashSet(Arrays.asList(expectedValues)), realValues); + @Override + public File[] getRoleCorpFiles() { + return ROLE_CORP_FILES; } - - private AssignmentEvaluator createAssignmentEvaluator() throws ObjectNotFoundException, SchemaException { - PrismObject userJack = userTypeJack.asPrismObject(); - return createAssignmentEvaluator(new ObjectDeltaObject(userJack, null, null)); - } + - private AssignmentEvaluator createAssignmentEvaluator(ObjectDeltaObject focusOdo) throws ObjectNotFoundException, SchemaException { - AssignmentEvaluator assignmentEvaluator = new AssignmentEvaluator<>(); - assignmentEvaluator.setRepository(repositoryService); - assignmentEvaluator.setFocusOdo(focusOdo); - assignmentEvaluator.setObjectResolver(objectResolver); - assignmentEvaluator.setPrismContext(prismContext); - assignmentEvaluator.setActivationComputer(activationComputer); - assignmentEvaluator.setNow(clock.currentTimeXMLGregorianCalendar()); - assignmentEvaluator.setMappingFactory(mappingFactory); - assignmentEvaluator.setMappingEvaluator(mappingEvaluator); - // Fake - assignmentEvaluator.setLensContext(new LensContext<>(UserType.class, prismContext, provisioningService)); - return assignmentEvaluator; - } + } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluatorDynamic.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluatorDynamic.java new file mode 100644 index 00000000000..5f34a6854c1 --- /dev/null +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluatorDynamic.java @@ -0,0 +1,137 @@ +package com.evolveum.midpoint.model.impl.lens; + +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.MINUS; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.PLUS; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.ZERO; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; +import static com.evolveum.midpoint.test.IntegrationTestTools.*; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.xml.bind.JAXBException; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.delta.DeltaSetTriple; +import com.evolveum.midpoint.prism.delta.PlusMinusZero; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.constants.SchemaConstants; + +import org.apache.commons.collections.CollectionUtils; +import org.python.antlr.base.mod; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.common.ActivationComputer; +import com.evolveum.midpoint.common.Clock; +import com.evolveum.midpoint.model.common.expression.ItemDeltaItem; +import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject; +import com.evolveum.midpoint.model.common.mapping.Mapping; +import com.evolveum.midpoint.model.common.mapping.MappingFactory; +import com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer; +import com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest; +import com.evolveum.midpoint.model.impl.lens.AssignmentEvaluator; +import com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl; +import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator; +import com.evolveum.midpoint.model.impl.util.Utils; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.delta.ReferenceDelta; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectResolver; +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.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; + +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; + + +@ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestAssignmentEvaluatorDynamic extends TestAbstractAssignmentEvaluator { + + protected static final File ROLE_CORP_GENERIC_METAROLE_DYNAMIC_FILE = new File(TEST_DIR, "role-corp-generic-metarole-dynamic.xml"); + + protected static final File ROLE_CORP_JOB_METAROLE_DYNAMIC_FILE = new File(TEST_DIR, "role-corp-job-metarole-dynamic.xml"); + + protected static final File ROLE_CORP_MANAGER_DYNAMIC_FILE = new File(TEST_DIR, "role-corp-manager-dynamic.xml"); + + protected static final String NS_PIRACY = "http://midpoint.evolveum.com/xml/ns/samples/piracy"; + + protected static final File[] ROLE_CORP_FILES = { + ROLE_CORP_GENERIC_METAROLE_DYNAMIC_FILE, + ROLE_CORP_JOB_METAROLE_DYNAMIC_FILE, + ROLE_CORP_VISITOR_FILE, + ROLE_CORP_CUSTOMER_FILE, + ROLE_CORP_CONTRACTOR_FILE, + ROLE_CORP_EMPLOYEE_FILE, + ROLE_CORP_ENGINEER_FILE, + ROLE_CORP_MANAGER_FILE + }; + + @Override + public File[] getRoleCorpFiles() { + return ROLE_CORP_FILES; + } + + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + addObjects(getRoleCorpFiles()); + +// PrismObject userJack = getObject(UserType.class, USER_JACK_OID); +// ItemPath resourceNamePath = new ItemPath(FocusType.F_EXTENSION, new QName(NS_PIRACY, "resourceName")); +// ItemPath resourceRefPath = new ItemPath(FocusType.F_EXTENSION, new QName(NS_PIRACY, "resourceRef")); +// +// Collection modifications = new ArrayList<>(); +// modifications.add(PropertyDelta.createModificationAddProperty(resourceNamePath, userJack.getDefinition().findPropertyDefinition(resourceNamePath), "Dummy Resource")); +// modifications.add(ReferenceDelta.createModificationAdd(resourceRefPath, userJack.getDefinition(), ObjectTypeUtil.createObjectRef("10000000-0000-0000-0000-000000000004", ObjectTypes.RESOURCE).asReferenceValue())); +// +// Collection deltas = new ArrayList<>(); +// deltas.add(ObjectDelta.createModifyDelta(USER_JACK_OID, modifications, UserType.class, prismContext)); +// modelService.executeChanges(deltas, null, initTask, initResult); +// +// userTypeJack = getObject(UserType.class, USER_JACK_OID).asObjectable(); + + } + +} diff --git a/model/model-impl/src/test/resources/lens/role-corp-contractor.xml b/model/model-impl/src/test/resources/lens/role-corp-contractor.xml index 8cb8ca3e299..ebbcf736af9 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-contractor.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-contractor.xml @@ -15,6 +15,7 @@ --> Contractor Universal role for contractors working for the company @@ -29,4 +30,8 @@ true job + + Dummy Resource + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-customer.xml b/model/model-impl/src/test/resources/lens/role-corp-customer.xml index 576a4068078..e203297622b 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-customer.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-customer.xml @@ -15,6 +15,7 @@ --> Customer Someone who buys our stuff @@ -22,4 +23,8 @@ true + + Dummy Resource + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-employee.xml b/model/model-impl/src/test/resources/lens/role-corp-employee.xml index 1f2ba7b4fad..68906bd13c1 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-employee.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-employee.xml @@ -15,6 +15,7 @@ --> Employee Universal role for all (internal) employees in the company @@ -29,4 +30,8 @@ true job + + Dummy Resource + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-engineer.xml b/model/model-impl/src/test/resources/lens/role-corp-engineer.xml index 53fe43a8b8a..1d624070c8c 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-engineer.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-engineer.xml @@ -15,6 +15,7 @@ --> Engineer An engineer that is (obviously) also an employee @@ -50,4 +51,8 @@ job + + Dummy Resource + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-generic-metarole-dynamic.xml b/model/model-impl/src/test/resources/lens/role-corp-generic-metarole-dynamic.xml new file mode 100644 index 00000000000..9562ece5a70 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/role-corp-generic-metarole-dynamic.xml @@ -0,0 +1,71 @@ + + + + + + Generic Metarole + Metarole for all roles which are assigned directly to users + + + + + + name + + $immediateRole/extension/ext:resourceName + + + + + account + + ri:location + + + $focus/locality + + + + + 2 + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-job-metarole-dynamic.xml b/model/model-impl/src/test/resources/lens/role-corp-job-metarole-dynamic.xml new file mode 100644 index 00000000000..065e2ecb240 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/role-corp-job-metarole-dynamic.xml @@ -0,0 +1,74 @@ + + + + Job Metarole Dynamic + Metarole for all job roles + + + + + + + + + + + + + + + + + + + account + + ri:title + + + $immediateRole/name + + + + + 2 + + + + $immediateRole/roleType + + + $focus/costCenter + + + + + + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-manager.xml b/model/model-impl/src/test/resources/lens/role-corp-manager.xml index be65d7c9c6f..2d45328a217 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-manager.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-manager.xml @@ -15,6 +15,7 @@ --> Manager A manager that is (obviously) also an employee @@ -32,4 +33,8 @@ true management + + Dummy Resource + + diff --git a/model/model-impl/src/test/resources/lens/role-corp-visitor.xml b/model/model-impl/src/test/resources/lens/role-corp-visitor.xml index 4493843526c..a3b47f26544 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-visitor.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-visitor.xml @@ -15,6 +15,7 @@ --> Visitor Just a random visitor @@ -22,4 +23,8 @@ true + + Dummy Resource + + diff --git a/model/model-impl/src/test/resources/schema/piracy.xsd b/model/model-impl/src/test/resources/schema/piracy.xsd index 87e3f4ca732..c0254217248 100644 --- a/model/model-impl/src/test/resources/schema/piracy.xsd +++ b/model/model-impl/src/test/resources/schema/piracy.xsd @@ -21,6 +21,8 @@ xmlns:a="http://prism.evolveum.com/xml/ns/public/annotation-3" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + + @@ -35,5 +37,20 @@ + + + + + + + + + + + + + + + diff --git a/model/model-impl/testng-unit.xml b/model/model-impl/testng-unit.xml index f216ab518ae..d6619c51d0a 100644 --- a/model/model-impl/testng-unit.xml +++ b/model/model-impl/testng-unit.xml @@ -60,6 +60,7 @@ + diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java index dc91d350f1c..31d9516ae28 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java @@ -16,8 +16,35 @@ package com.evolveum.midpoint.repo.sql; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import javax.xml.bind.JAXBException; +import javax.xml.namespace.QName; + +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.stat.Statistics; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; @@ -25,7 +52,11 @@ import com.evolveum.midpoint.prism.util.ValueSerializationUtil; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.schema.*; +import com.evolveum.midpoint.schema.DeltaConvertor; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.ResultHandler; +import com.evolveum.midpoint.schema.RetrieveOption; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.ResourceSchema; import com.evolveum.midpoint.schema.result.OperationResult; @@ -36,24 +67,22 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationSituationDescriptionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationSituationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ValuePolicyType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.stat.Statistics; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.testng.AssertJUnit; -import org.testng.annotations.Test; - -import javax.xml.bind.JAXBException; -import javax.xml.namespace.QName; - -import java.io.File; -import java.util.*; - /** * @author lazyman */ @@ -400,6 +429,24 @@ public void addGetSyncDescription() throws Exception { desc = shadowType.getSynchronizationSituationDescription().get(0); AssertJUnit.assertEquals("Times don't match", TIME, XMLGregorianCalendarType.asDate(desc.getTimestamp())); } + + @Test + public void addGetRoleWithResourceRefFilter() throws Exception{ + PrismObject role = prismContext.parseObject(new File("src/test/resources/basic/role-resource-filter.xml")); + + System.out.println("role: " + role.debugDump()); + System.out.println("role: " + role.asObjectable().getInducement().get(0).getConstruction().getResourceRef().getFilter()); + + OperationResult result = new OperationResult("sync desc test"); + String oid = repositoryService.addObject(role, null, result); + + role = repositoryService.getObject(RoleType.class, oid, null, result); + RoleType roleType = role.asObjectable(); + System.out.println("role: " + role.debugDump()); + System.out.println("role: " + role.asObjectable().getInducement().get(0).getConstruction().getResourceRef().getFilter()); +// desc = roleType.getSynchronizationSituationDescription().get(0); +// AssertJUnit.assertEquals("Times don't match", TIME, XMLGregorianCalendarType.asDate(desc.getTimestamp())); + } /** * creates element in shadow diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java index d838b77ece4..67066a94200 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java @@ -141,8 +141,9 @@ public static void copyToJAXB(REmbeddedReference repo, ObjectReferenceType jaxb, public static void copyFromJAXB(ObjectReferenceType jaxb, REmbeddedReference repo, PrismContext prismContext) { Validate.notNull(repo, "Repo object must not be null."); Validate.notNull(jaxb, "JAXB object must not be null."); + if (jaxb.getFilter() == null){ Validate.notEmpty(jaxb.getOid(), "Target oid must not be null."); - + } repo.setType(ClassMapper.getHQLTypeForQName(jaxb.getType())); repo.setRelation(RUtil.qnameToString(jaxb.getRelation())); repo.setTargetOid(jaxb.getOid()); diff --git a/samples/rest/modify-user-assign-role.xml b/samples/rest/modify-user-assign-role.xml new file mode 100644 index 00000000000..0c5b64f06dd --- /dev/null +++ b/samples/rest/modify-user-assign-role.xml @@ -0,0 +1,12 @@ + + + add + c:assignment + + + + + From 3616d6dd759e1a9a65dab46c6017c67940de0b28 Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Thu, 10 Mar 2016 15:44:47 +0100 Subject: [PATCH 3/4] small improvement for "dynamic" assignments --- .../model/impl/lens/Construction.java | 403 +++++++++++------- .../resources/basic/role-resource-filter.xml | 71 +++ 2 files changed, 314 insertions(+), 160 deletions(-) create mode 100644 repo/repo-sql-impl-test/src/test/resources/basic/role-resource-filter.xml diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java index 20a12edfd08..1eb8525e450 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java @@ -91,14 +91,16 @@ import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; /** - * Live class that contains "construction" - a definition how to construct a resource object. It in fact reflects - * the definition of ConstructionType but it also contains "live" objects and can evaluate the construction. It also + * Live class that contains "construction" - a definition how to construct a + * resource object. It in fact reflects the definition of ConstructionType but + * it also contains "live" objects and can evaluate the construction. It also * contains intermediary and side results of the evaluation. * * @author Radovan Semancik * - * This class is Serializable but it is not in fact serializable. It implements Serializable interface only - * to be storable in the PrismPropertyValue. + * This class is Serializable but it is not in fact serializable. It + * implements Serializable interface only to be storable in the + * PrismPropertyValue. */ public class Construction implements DebugDumpable, Serializable { @@ -114,18 +116,22 @@ public class Construction implements DebugDumpable, Seriali private ObjectResolver objectResolver; private MappingFactory mappingFactory; private MappingEvaluator mappingEvaluator; - private Collection,? extends PrismPropertyDefinition>> attributeMappings; - private Collection,PrismContainerDefinition>> associationMappings; + private Collection, ? extends PrismPropertyDefinition>> attributeMappings; + private Collection, PrismContainerDefinition>> associationMappings; private RefinedObjectClassDefinition refinedObjectClassDefinition; private List auxiliaryObjectClassDefinitions; private AssignmentPathVariables assignmentPathVariables = null; private PrismContext prismContext; private PrismContainerDefinition associationContainerDefinition; - private PrismObject systemConfiguration; // only to provide $configuration variable (MID-2372) + private PrismObject systemConfiguration; // only to + // provide + // $configuration + // variable + // (MID-2372) private boolean isValid = true; - + private static final Trace LOGGER = TraceManager.getTrace(Construction.class); - + public Construction(ConstructionType constructionType, ObjectType source) { this.constructionType = constructionType; this.source = source; @@ -136,7 +142,7 @@ public Construction(ConstructionType constructionType, ObjectType source) { public void setSource(ObjectType source) { this.source = source; } - + public ObjectType getSource() { return source; } @@ -156,7 +162,7 @@ public String getChannel() { public void setChannel(String channel) { this.channel = channel; } - + public LensContext getLensContext() { return lensContext; } @@ -220,7 +226,7 @@ public void setSystemConfiguration(PrismObject systemCo public RefinedObjectClassDefinition getRefinedObjectClassDefinition() { return refinedObjectClassDefinition; } - + public void setRefinedObjectClassDefinition(RefinedObjectClassDefinition refinedObjectClassDefinition) { this.refinedObjectClassDefinition = refinedObjectClassDefinition; } @@ -228,15 +234,15 @@ public void setRefinedObjectClassDefinition(RefinedObjectClassDefinition refined public List getAuxiliaryObjectClassDefinitions() { return auxiliaryObjectClassDefinitions; } - - public void addAuxiliaryObjectClassDefinition(RefinedObjectClassDefinition auxiliaryObjectClassDefinition) { + + public void addAuxiliaryObjectClassDefinition( + RefinedObjectClassDefinition auxiliaryObjectClassDefinition) { if (auxiliaryObjectClassDefinitions == null) { auxiliaryObjectClassDefinitions = new ArrayList<>(); } auxiliaryObjectClassDefinitions.add(auxiliaryObjectClassDefinition); } - public ShadowKindType getKind() { if (refinedObjectClassDefinition == null) { throw new IllegalStateException("Kind can only be fetched from evaluated Construction"); @@ -254,7 +260,7 @@ public String getIntent() { public Object getDescription() { return constructionType.getDescription(); } - + public boolean isValid() { return isValid; } @@ -263,48 +269,51 @@ public void setValid(boolean isValid) { this.isValid = isValid; } - public Collection,? extends PrismPropertyDefinition>> getAttributeMappings() { + public Collection, ? extends PrismPropertyDefinition>> getAttributeMappings() { if (attributeMappings == null) { attributeMappings = new ArrayList<>(); } return attributeMappings; } - - public Mapping, ? extends PrismPropertyDefinition> getAttributeMapping(QName attrName) { - for (Mapping,? extends PrismPropertyDefinition> myVc : getAttributeMappings()) { + + public Mapping, ? extends PrismPropertyDefinition> getAttributeMapping( + QName attrName) { + for (Mapping, ? extends PrismPropertyDefinition> myVc : getAttributeMappings()) { if (myVc.getItemName().equals(attrName)) { return myVc; } } return null; } - - public void addAttributeMapping(Mapping,? extends PrismPropertyDefinition> mapping) { + + public void addAttributeMapping( + Mapping, ? extends PrismPropertyDefinition> mapping) { getAttributeMappings().add(mapping); } public boolean containsAttributeMapping(QName attributeName) { - for (Mapping mapping: getAttributeMappings()) { + for (Mapping mapping : getAttributeMappings()) { if (attributeName.equals(mapping.getItemName())) { return true; } } return false; } - - public Collection,PrismContainerDefinition>> getAssociationMappings() { + + public Collection, PrismContainerDefinition>> getAssociationMappings() { if (associationMappings == null) { - associationMappings = new ArrayList,PrismContainerDefinition>>(); + associationMappings = new ArrayList, PrismContainerDefinition>>(); } return associationMappings; } - - public void addAssociationMapping(Mapping,PrismContainerDefinition> mapping) { + + public void addAssociationMapping( + Mapping, PrismContainerDefinition> mapping) { getAssociationMappings().add(mapping); } public boolean containsAssociationMapping(QName assocName) { - for (Mapping mapping: getAssociationMappings()) { + for (Mapping mapping : getAssociationMappings()) { if (assocName.equals(mapping.getItemName())) { return true; } @@ -319,89 +328,121 @@ public AssignmentPath getAssignmentPath() { public void setAssignmentPath(AssignmentPath assignmentPath) { this.assignmentPath = assignmentPath; } - - private ResourceType resolveTarget(String sourceDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException{ -// SearchFilterType filter = targetRef.getFilter(); - ExpressionVariables variables = Utils.getDefaultExpressionVariables(focusOdo.getNewObject().asObjectable(), null, null, null); - variables.addVariableDefinition(ExpressionConstants.VAR_IMMEDIATE_ROLE, assignmentPathVariables.getImmediateRole()); - variables.addVariableDefinition(ExpressionConstants.VAR_IMMEDIATE_ASSIGNMENT, assignmentPathVariables.getImmediateAssignment()); - variables.addVariableDefinition(ExpressionConstants.VAR_THIS_ASSIGNMENT, assignmentPathVariables.getThisAssignment()); - variables.addVariableDefinition(ExpressionConstants.VAR_FOCUS_ASSIGNMENT, assignmentPathVariables.getFocusAssignment()); - LOGGER.info("Expression valriables for filter evaluation: {}", variables); + + private ResourceType resolveTarget(String sourceDescription, Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, + CommunicationException, ConfigurationException, SecurityViolationException { + // SearchFilterType filter = targetRef.getFilter(); + ExpressionVariables variables = Utils + .getDefaultExpressionVariables(focusOdo.getNewObject().asObjectable(), null, null, null); + if (assignmentPathVariables == null){ + assignmentPathVariables = LensUtil.computeAssignmentPathVariables(assignmentPath); + } + if (assignmentPathVariables != null) { + variables.addVariableDefinition(ExpressionConstants.VAR_IMMEDIATE_ROLE, + assignmentPathVariables.getImmediateRole()); + variables.addVariableDefinition(ExpressionConstants.VAR_IMMEDIATE_ASSIGNMENT, + assignmentPathVariables.getImmediateAssignment()); + variables.addVariableDefinition(ExpressionConstants.VAR_THIS_ASSIGNMENT, + assignmentPathVariables.getThisAssignment()); + variables.addVariableDefinition(ExpressionConstants.VAR_FOCUS_ASSIGNMENT, + assignmentPathVariables.getFocusAssignment()); + } + LOGGER.info("Expression valriables for filter evaluation: {}", variables); - ObjectFilter origFilter = QueryConvertor.parseFilter(constructionType.getResourceRef().getFilter(), ResourceType.class, prismContext); + ObjectFilter origFilter = QueryConvertor.parseFilter(constructionType.getResourceRef().getFilter(), + ResourceType.class, prismContext); LOGGER.info("Orig filter {}", origFilter); - ObjectFilter evaluatedFilter = ExpressionUtil.evaluateFilterExpressions(origFilter, variables, getMappingFactory().getExpressionFactory(), prismContext, " evaluating resource filter expression ", task, result); + ObjectFilter evaluatedFilter = ExpressionUtil.evaluateFilterExpressions(origFilter, variables, + getMappingFactory().getExpressionFactory(), prismContext, + " evaluating resource filter expression ", task, result); LOGGER.info("evaluatedFilter filter {}", evaluatedFilter); - - if (evaluatedFilter == null){ - throw new SchemaException("The OID is null and filter could not be evaluated in assignment targetRef in "+source); + + if (evaluatedFilter == null) { + throw new SchemaException( + "The OID is null and filter could not be evaluated in assignment targetRef in " + source); } - - - + final Collection> results = new ArrayList<>(); ResultHandler handler = new ResultHandler() { - + @Override public boolean handle(PrismObject object, OperationResult parentResult) { LOGGER.info("Found object {}", object); return results.add(object); } }; - objectResolver.searchIterative(ResourceType.class, ObjectQuery.createObjectQuery(evaluatedFilter), null, handler, task, result); - - if (org.apache.commons.collections.CollectionUtils.isEmpty(results)){ - throw new IllegalArgumentException("Got null target from repository, filter:"+evaluatedFilter+", class:"+ResourceType.class+" (should not happen, probably a bug) in "+sourceDescription); - } - - if (results.size() > 1){ - throw new IllegalArgumentException("Got more than one target from repository, filter:"+evaluatedFilter+", class:"+ResourceType.class+" (should not happen, probably a bug) in "+sourceDescription); - } - - PrismObject target = results.iterator().next(); - -// assignmentType.getTargetRef().setOid(target.getOid()); - return target.asObjectable(); - } - - public ResourceType getResource(Task task, OperationResult result) throws ObjectNotFoundException, SchemaException { + objectResolver.searchIterative(ResourceType.class, ObjectQuery.createObjectQuery(evaluatedFilter), + null, handler, task, result); + + if (org.apache.commons.collections.CollectionUtils.isEmpty(results)) { + throw new IllegalArgumentException("Got null target from repository, filter:" + evaluatedFilter + + ", class:" + ResourceType.class + " (should not happen, probably a bug) in " + + sourceDescription); + } + + if (results.size() > 1) { + throw new IllegalArgumentException("Got more than one target from repository, filter:" + + evaluatedFilter + ", class:" + ResourceType.class + + " (should not happen, probably a bug) in " + sourceDescription); + } + + PrismObject target = results.iterator().next(); + + // assignmentType.getTargetRef().setOid(target.getOid()); + return target.asObjectable(); + } + + public ResourceType getResource(Task task, OperationResult result) + throws ObjectNotFoundException, SchemaException { if (resource == null) { if (constructionType.getResource() != null) { resource = constructionType.getResource(); } else if (constructionType.getResourceRef() != null) { try { - - if (constructionType.getResourceRef().getOid() == null){ + + if (constructionType.getResourceRef().getOid() == null) { resource = resolveTarget(" resolving resource ", task, result); } else { - resource = LensUtil.getResource(lensContext, constructionType.getResourceRef().getOid(), objectResolver, task, result); + resource = LensUtil.getResource(lensContext, + constructionType.getResourceRef().getOid(), objectResolver, task, result); } } catch (ObjectNotFoundException e) { - throw new ObjectNotFoundException("Resource reference seems to be invalid in account construction in " + source + ": "+e.getMessage(), e); - } catch (SecurityViolationException|CommunicationException|ConfigurationException e) { - throw new SystemException("Couldn't fetch the resource in account construction in " + source + ": " + e.getMessage(), e); + throw new ObjectNotFoundException( + "Resource reference seems to be invalid in account construction in " + source + + ": " + e.getMessage(), + e); + } catch (SecurityViolationException | CommunicationException | ConfigurationException e) { + throw new SystemException("Couldn't fetch the resource in account construction in " + + source + ": " + e.getMessage(), e); } catch (ExpressionEvaluationException e) { - throw new SystemException("Couldn't evaluate filter expression for the resource in account construction in " + source + ": " + e.getMessage(), e); + throw new SystemException( + "Couldn't evaluate filter expression for the resource in account construction in " + + source + ": " + e.getMessage(), + e); } } if (resource == null) { - throw new SchemaException("No resource set in account construction in " + source + ", resource : " + constructionType.getResource() + ", resourceRef: " + constructionType.getResourceRef()); + throw new SchemaException("No resource set in account construction in " + source + + ", resource : " + constructionType.getResource() + ", resourceRef: " + + constructionType.getResourceRef()); } constructionType.getResourceRef().setOid(resource.getOid()); } return resource; } - - public void evaluate(Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { + + public void evaluate(Task task, OperationResult result) + throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { assignmentPathVariables = LensUtil.computeAssignmentPathVariables(assignmentPath); evaluateKindIntentObjectClass(task, result); evaluateAttributes(task, result); evaluateAssociations(task, result); } - - private void evaluateKindIntentObjectClass(Task task, OperationResult result) throws SchemaException, ObjectNotFoundException { + + private void evaluateKindIntentObjectClass(Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException { String resourceOid = null; if (constructionType.getResourceRef() != null) { resourceOid = constructionType.getResourceRef().getOid(); @@ -411,98 +452,122 @@ private void evaluateKindIntentObjectClass(Task task, OperationResult result) th } ResourceType resource = getResource(task, result); if (resourceOid != null && !resource.getOid().equals(resourceOid)) { - throw new IllegalStateException("The specified resource and the resource in construction does not match"); + throw new IllegalStateException( + "The specified resource and the resource in construction does not match"); } - - RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource, LayerType.MODEL, prismContext); + + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource, + LayerType.MODEL, prismContext); if (refinedSchema == null) { // Refined schema may be null in some error-related border cases - throw new SchemaException("No (refined) schema for "+resource); + throw new SchemaException("No (refined) schema for " + resource); } - + ShadowKindType kind = constructionType.getKind(); if (kind == null) { kind = ShadowKindType.ACCOUNT; } refinedObjectClassDefinition = refinedSchema.getRefinedDefinition(kind, constructionType.getIntent()); - + if (refinedObjectClassDefinition == null) { if (constructionType.getIntent() != null) { - throw new SchemaException("No "+kind+" type '"+constructionType.getIntent()+"' found in "+getResource(task, result)+" as specified in construction in "+source); + throw new SchemaException( + "No " + kind + " type '" + constructionType.getIntent() + "' found in " + + getResource(task, result) + " as specified in construction in " + source); } else { - throw new SchemaException("No default "+kind+" type found in " + resource + " as specified in construction in "+source); + throw new SchemaException("No default " + kind + " type found in " + resource + + " as specified in construction in " + source); } } - + auxiliaryObjectClassDefinitions = new ArrayList<>(constructionType.getAuxiliaryObjectClass().size()); - for (QName auxiliaryObjectClassName: constructionType.getAuxiliaryObjectClass()) { - RefinedObjectClassDefinition auxOcDef = refinedSchema.getRefinedDefinition(auxiliaryObjectClassName); + for (QName auxiliaryObjectClassName : constructionType.getAuxiliaryObjectClass()) { + RefinedObjectClassDefinition auxOcDef = refinedSchema + .getRefinedDefinition(auxiliaryObjectClassName); if (auxOcDef == null) { - throw new SchemaException("No auxiliary object class "+auxiliaryObjectClassName+" found in "+getResource(task, result)+" as specified in construction in "+source); + throw new SchemaException( + "No auxiliary object class " + auxiliaryObjectClassName + " found in " + + getResource(task, result) + " as specified in construction in " + source); } auxiliaryObjectClassDefinitions.add(auxOcDef); } } - private void evaluateAttributes(Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { + private void evaluateAttributes(Task task, OperationResult result) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { attributeMappings = new ArrayList<>(); -// LOGGER.trace("Assignments used for account construction for {} ({}): {}", new Object[]{this.resource, -// assignments.size(), assignments}); + // LOGGER.trace("Assignments used for account construction for {} ({}): + // {}", new Object[]{this.resource, + // assignments.size(), assignments}); for (ResourceAttributeDefinitionType attribudeDefinitionType : constructionType.getAttribute()) { QName attrName = ItemPathUtil.getOnlySegmentQName(attribudeDefinitionType.getRef()); if (attrName == null) { - throw new SchemaException("No attribute name (ref) in attribute definition in account construction in "+source); + throw new SchemaException( + "No attribute name (ref) in attribute definition in account construction in " + + source); } if (!attribudeDefinitionType.getInbound().isEmpty()) { - throw new SchemaException("Cannot process inbound section in definition of attribute "+attrName+" in account construction in "+source); + throw new SchemaException("Cannot process inbound section in definition of attribute " + + attrName + " in account construction in " + source); } MappingType outboundMappingType = attribudeDefinitionType.getOutbound(); if (outboundMappingType == null) { - throw new SchemaException("No outbound section in definition of attribute "+attrName+" in account construction in "+source); + throw new SchemaException("No outbound section in definition of attribute " + attrName + + " in account construction in " + source); } - Mapping,? extends PrismPropertyDefinition> attributeMapping = evaluateAttribute(attribudeDefinitionType, task, result); + Mapping, ? extends PrismPropertyDefinition> attributeMapping = evaluateAttribute( + attribudeDefinitionType, task, result); if (attributeMapping != null) { attributeMappings.add(attributeMapping); } } } - private Mapping, ResourceAttributeDefinition> evaluateAttribute(ResourceAttributeDefinitionType attribudeDefinitionType, - Task task, OperationResult result) - throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { + private Mapping, ResourceAttributeDefinition> evaluateAttribute( + ResourceAttributeDefinitionType attribudeDefinitionType, Task task, OperationResult result) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { QName attrName = ItemPathUtil.getOnlySegmentQName(attribudeDefinitionType.getRef()); if (attrName == null) { - throw new SchemaException("Missing 'ref' in attribute construction in account construction in "+ObjectTypeUtil.toShortString(source)); + throw new SchemaException("Missing 'ref' in attribute construction in account construction in " + + ObjectTypeUtil.toShortString(source)); } if (!attribudeDefinitionType.getInbound().isEmpty()) { - throw new SchemaException("Cannot process inbound section in definition of attribute "+attrName+" in account construction in "+source); + throw new SchemaException("Cannot process inbound section in definition of attribute " + attrName + + " in account construction in " + source); } MappingType outboundMappingType = attribudeDefinitionType.getOutbound(); if (outboundMappingType == null) { - throw new SchemaException("No outbound section in definition of attribute "+attrName+" in account construction in "+source); + throw new SchemaException("No outbound section in definition of attribute " + attrName + + " in account construction in " + source); } ResourceAttributeDefinition outputDefinition = findAttributeDefinition(attrName); if (outputDefinition == null) { - throw new SchemaException("Attribute "+attrName+" not found in schema for account type "+getIntent()+", "+ObjectTypeUtil.toShortString(getResource(task, result))+" as definied in "+ObjectTypeUtil.toShortString(source), attrName); + throw new SchemaException("Attribute " + attrName + " not found in schema for account type " + + getIntent() + ", " + ObjectTypeUtil.toShortString(getResource(task, result)) + + " as definied in " + ObjectTypeUtil.toShortString(source), attrName); } - Mapping,ResourceAttributeDefinition> mapping = mappingFactory.createMapping(outboundMappingType, - "for attribute " + PrettyPrinter.prettyPrint(attrName) + " in "+source); - - Mapping, ResourceAttributeDefinition> evaluatedMapping = evaluateMapping(mapping, attrName, outputDefinition, null, task, result); - - LOGGER.trace("Evaluated mapping for attribute "+attrName+": "+evaluatedMapping); + Mapping, ResourceAttributeDefinition> mapping = mappingFactory.createMapping( + outboundMappingType, + "for attribute " + PrettyPrinter.prettyPrint(attrName) + " in " + source); + + Mapping, ResourceAttributeDefinition> evaluatedMapping = evaluateMapping( + mapping, attrName, outputDefinition, null, task, result); + + LOGGER.trace("Evaluated mapping for attribute " + attrName + ": " + evaluatedMapping); return evaluatedMapping; } public RefinedAttributeDefinition findAttributeDefinition(QName attributeName) { if (refinedObjectClassDefinition == null) { - throw new IllegalStateException("Construction "+this+" was not evaluated:\n"+this.debugDump()); + throw new IllegalStateException( + "Construction " + this + " was not evaluated:\n" + this.debugDump()); } - RefinedAttributeDefinition attrDef = refinedObjectClassDefinition.findAttributeDefinition(attributeName); + RefinedAttributeDefinition attrDef = refinedObjectClassDefinition + .findAttributeDefinition(attributeName); if (attrDef != null) { return attrDef; } - for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition: auxiliaryObjectClassDefinitions) { + for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) { attrDef = auxiliaryObjectClassDefinition.findAttributeDefinition(attributeName); if (attrDef != null) { return attrDef; @@ -510,11 +575,12 @@ public RefinedAttributeDefinition findAttributeDefinition(QName attribute } return null; } - + public boolean hasValueForAttribute(QName attributeName) { - for (Mapping,? extends PrismPropertyDefinition> attributeConstruction: attributeMappings) { + for (Mapping, ? extends PrismPropertyDefinition> attributeConstruction : attributeMappings) { if (attributeName.equals(attributeConstruction.getItemName())) { - PrismValueDeltaSetTriple> outputTriple = attributeConstruction.getOutputTriple(); + PrismValueDeltaSetTriple> outputTriple = attributeConstruction + .getOutputTriple(); if (outputTriple != null && !outputTriple.isEmpty()) { return true; } @@ -522,63 +588,70 @@ public boolean hasValueForAttribute(QName attributeName) { } return false; } - - private void evaluateAssociations(Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { + + private void evaluateAssociations(Task task, OperationResult result) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { associationMappings = new ArrayList<>(); for (ResourceObjectAssociationType associationDefinitionType : constructionType.getAssociation()) { QName assocName = ItemPathUtil.getOnlySegmentQName(associationDefinitionType.getRef()); if (assocName == null) { - throw new SchemaException("No association name (ref) in association definition in construction in "+source); + throw new SchemaException( + "No association name (ref) in association definition in construction in " + source); } MappingType outboundMappingType = associationDefinitionType.getOutbound(); if (outboundMappingType == null) { - throw new SchemaException("No outbound section in definition of association "+assocName+" in construction in "+source); + throw new SchemaException("No outbound section in definition of association " + assocName + + " in construction in " + source); } - Mapping,PrismContainerDefinition> assocMapping = evaluateAssociation(associationDefinitionType, task, result); + Mapping, PrismContainerDefinition> assocMapping = evaluateAssociation( + associationDefinitionType, task, result); if (assocMapping != null) { associationMappings.add(assocMapping); } } } - private Mapping, PrismContainerDefinition> evaluateAssociation(ResourceObjectAssociationType associationDefinitionType, - Task task, OperationResult result) - throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { + private Mapping, PrismContainerDefinition> evaluateAssociation( + ResourceObjectAssociationType associationDefinitionType, Task task, OperationResult result) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { QName assocName = ItemPathUtil.getOnlySegmentQName(associationDefinitionType.getRef()); if (assocName == null) { - throw new SchemaException("Missing 'ref' in association in construction in "+source); + throw new SchemaException("Missing 'ref' in association in construction in " + source); } MappingType outboundMappingType = associationDefinitionType.getOutbound(); if (outboundMappingType == null) { - throw new SchemaException("No outbound section in definition of association "+assocName+" in construction in "+source); + throw new SchemaException("No outbound section in definition of association " + assocName + + " in construction in " + source); } PrismContainerDefinition outputDefinition = getAssociationContainerDefinition(); - Mapping,PrismContainerDefinition> mapping = mappingFactory.createMapping(outboundMappingType, - "for association " + PrettyPrinter.prettyPrint(assocName) + " in " + source); + Mapping, PrismContainerDefinition> mapping = mappingFactory + .createMapping(outboundMappingType, + "for association " + PrettyPrinter.prettyPrint(assocName) + " in " + source); mapping.setOriginType(OriginType.ASSIGNMENTS); mapping.setOriginObject(source); - + RefinedAssociationDefinition rAssocDef = refinedObjectClassDefinition.findAssociation(assocName); if (rAssocDef == null) { - throw new SchemaException("No association "+assocName+" in object class "+refinedObjectClassDefinition.getHumanReadableName() - +" in construction in "+source); + throw new SchemaException("No association " + assocName + " in object class " + + refinedObjectClassDefinition.getHumanReadableName() + " in construction in " + source); } - - Mapping, PrismContainerDefinition> evaluatedMapping = evaluateMapping(mapping, assocName, outputDefinition, - rAssocDef.getAssociationTarget(), task, result); - - LOGGER.trace("Evaluated mapping for association "+assocName+": "+evaluatedMapping); + + Mapping, PrismContainerDefinition> evaluatedMapping = evaluateMapping( + mapping, assocName, outputDefinition, rAssocDef.getAssociationTarget(), task, result); + + LOGGER.trace("Evaluated mapping for association " + assocName + ": " + evaluatedMapping); return evaluatedMapping; } - - private Mapping evaluateMapping(Mapping mapping, QName mappingQName, D outputDefinition, - RefinedObjectClassDefinition assocTargetObjectClassDefinition, Task task, OperationResult result) + + private Mapping evaluateMapping( + Mapping mapping, QName mappingQName, D outputDefinition, + RefinedObjectClassDefinition assocTargetObjectClassDefinition, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { - + if (!mapping.isApplicableToChannel(channel)) { return null; } - + mapping.addVariableDefinition(ExpressionConstants.VAR_USER, focusOdo); mapping.addVariableDefinition(ExpressionConstants.VAR_FOCUS, focusOdo); mapping.addVariableDefinition(ExpressionConstants.VAR_SOURCE, source); @@ -589,20 +662,23 @@ private Mapping evaluateMa mapping.setOriginType(originType); mapping.setOriginObject(source); mapping.setRefinedObjectClassDefinition(refinedObjectClassDefinition); - + mapping.addVariableDefinition(ExpressionConstants.VAR_CONTAINING_OBJECT, source); mapping.addVariableDefinition(ExpressionConstants.VAR_ORDER_ONE_OBJECT, orderOneObject); if (assocTargetObjectClassDefinition != null) { - mapping.addVariableDefinition(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION, assocTargetObjectClassDefinition); + mapping.addVariableDefinition(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION, + assocTargetObjectClassDefinition); } LensUtil.addAssignmentPathVariables(mapping, assignmentPathVariables); if (getSystemConfiguration() != null) { mapping.addVariableDefinition(ExpressionConstants.VAR_CONFIGURATION, getSystemConfiguration()); } // TODO: other variables ? - - // Set condition masks. There are used as a brakes to avoid evaluating to nonsense values in case user is not present - // (e.g. in old values in ADD situations and new values in DELETE situations). + + // Set condition masks. There are used as a brakes to avoid evaluating + // to nonsense values in case user is not present + // (e.g. in old values in ADD situations and new values in DELETE + // situations). if (focusOdo.getOldObject() == null) { mapping.setConditionMaskOld(false); } @@ -614,11 +690,13 @@ private Mapping evaluateMa return mapping; } - + private PrismContainerDefinition getAssociationContainerDefinition() { if (associationContainerDefinition == null) { - PrismObjectDefinition shadowDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class); - associationContainerDefinition = shadowDefinition.findContainerDefinition(ShadowType.F_ASSOCIATION); + PrismObjectDefinition shadowDefinition = prismContext.getSchemaRegistry() + .findObjectDefinitionByCompileTimeClass(ShadowType.class); + associationContainerDefinition = shadowDefinition + .findContainerDefinition(ShadowType.F_ASSOCIATION); } return associationContainerDefinition; } @@ -690,7 +768,11 @@ public String debugDump(int indent) { DebugUtil.debugDumpLabel(sb, "Construction", indent); if (refinedObjectClassDefinition == null) { sb.append(" (no object class definition)"); - if (constructionType != null && constructionType.getResourceRef() != null) { // should be always the case + if (constructionType != null && constructionType.getResourceRef() != null) { // should + // be + // always + // the + // case sb.append("\n"); DebugUtil.debugDumpLabel(sb, "resourceRef / kind / intent", indent + 1); sb.append(" "); @@ -712,43 +794,44 @@ public String debugDump(int indent) { } else if (auxiliaryObjectClassDefinitions.isEmpty()) { sb.append(" (empty)"); } else { - for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition: auxiliaryObjectClassDefinitions) { + for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) { sb.append("\n"); - DebugUtil.indentDebugDump(sb, indent+2); + DebugUtil.indentDebugDump(sb, indent + 2); sb.append(auxiliaryObjectClassDefinition.getTypeName()); } } if (constructionType != null && constructionType.getDescription() != null) { sb.append("\n"); - DebugUtil.debugDumpLabel(sb, "description", indent+1); + DebugUtil.debugDumpLabel(sb, "description", indent + 1); sb.append(" ").append(constructionType.getDescription()); } if (attributeMappings != null && !attributeMappings.isEmpty()) { sb.append("\n"); - DebugUtil.debugDumpLabel(sb, "attribute mappings", indent+1); - for (Mapping mapping: attributeMappings) { + DebugUtil.debugDumpLabel(sb, "attribute mappings", indent + 1); + for (Mapping mapping : attributeMappings) { sb.append("\n"); - sb.append(mapping.debugDump(indent+2)); + sb.append(mapping.debugDump(indent + 2)); } } if (associationMappings != null && !associationMappings.isEmpty()) { sb.append("\n"); - DebugUtil.debugDumpLabel(sb, "association mappings", indent+1); - for (Mapping mapping: associationMappings) { + DebugUtil.debugDumpLabel(sb, "association mappings", indent + 1); + for (Mapping mapping : associationMappings) { sb.append("\n"); - sb.append(mapping.debugDump(indent+2)); + sb.append(mapping.debugDump(indent + 2)); } } if (assignmentPath != null) { sb.append("\n"); - sb.append(assignmentPath.debugDump(indent+1)); + sb.append(assignmentPath.debugDump(indent + 1)); } return sb.toString(); } @Override public String toString() { - return "Construction(" + (refinedObjectClassDefinition == null ? constructionType : refinedObjectClassDefinition.getShadowDiscriminator()) + ")"; + return "Construction(" + (refinedObjectClassDefinition == null ? constructionType + : refinedObjectClassDefinition.getShadowDiscriminator()) + ")"; } - + } diff --git a/repo/repo-sql-impl-test/src/test/resources/basic/role-resource-filter.xml b/repo/repo-sql-impl-test/src/test/resources/basic/role-resource-filter.xml new file mode 100644 index 00000000000..8cc4fb6642a --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/resources/basic/role-resource-filter.xml @@ -0,0 +1,71 @@ + + + + + + Generic Metarole + Metarole for all roles which are assigned directly to users + + + + + + name + + $focus/extension/ext:resourceName + + + + + account + + ri:location + + + $focus/locality + + + + + 2 + + From f23b83f767241b65ba7487165f8040422c63ba69 Mon Sep 17 00:00:00 2001 From: honchar Date: Thu, 10 Mar 2016 16:20:25 +0100 Subject: [PATCH 4/4] MID-2786 fix. Also, replacing ConfirmationDialog with main popup (from PageBase class) --- .../component/dialog/ConfirmationPanel.html | 29 +++++ .../component/dialog/ConfirmationPanel.java | 123 ++++++++++++++++++ .../objectdetails/AbstractObjectTabPanel.java | 9 ++ .../FocusProjectionsTabPanel.java | 64 +++++---- 4 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.html create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.html new file mode 100644 index 00000000000..a87f6c3e819 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.html @@ -0,0 +1,29 @@ + + + + +
+

+ +

+ +

+ + +

+
+
\ No newline at end of file diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.java new file mode 100644 index 00000000000..92476f5f28a --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/ConfirmationPanel.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010-2016 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.web.component.dialog; + +import com.evolveum.midpoint.web.component.AjaxButton; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.StringResourceModel; + +/** + * Created by Honchar. + * + * class is created based on the ConfirmationDialog. + * ConfirmationPanel panel is to be added + * to main popup (from PageBase class) as a content + * + */ +public class ConfirmationPanel extends Panel{ + private static final String ID_PANEL = "panel"; + private static final String ID_CONFIRM_TEXT = "confirmText"; + private static final String ID_YES = "yes"; + private static final String ID_NO = "no"; + + private int confirmType; + + public ConfirmationPanel(String id) { + this(id, null); + } + + public ConfirmationPanel(String id, IModel message) { + super(id); + + if (message == null) { + message = new Model(); + } + initLayout(message); + } + + public boolean getLabelEscapeModelStrings(){ + return true; + } + + public void setMessage(IModel message) { + Label label = (Label) get(ID_PANEL).get(ID_CONFIRM_TEXT); + label.setDefaultModel(message); + } + + private void initLayout(IModel message) { + WebMarkupContainer panel = new WebMarkupContainer(ID_PANEL); + + Label label = new Label(ID_CONFIRM_TEXT, message); + label.setEscapeModelStrings(getLabelEscapeModelStrings()); + panel.add(label); + + AjaxButton yesButton = new AjaxButton(ID_YES, new StringResourceModel("confirmationDialog.yes", + this, null)) { + + @Override + public void onClick(AjaxRequestTarget target) { + yesPerformed(target); + } + }; + panel.add(yesButton); + + AjaxButton noButton = new AjaxButton(ID_NO, new StringResourceModel("confirmationDialog.no", + this, null)) { + + @Override + public void onClick(AjaxRequestTarget target) { + noPerformed(target); + } + }; + panel.add(noButton); + add(panel); + } + + public void yesPerformed(AjaxRequestTarget target) { + + } + + public void noPerformed(AjaxRequestTarget target) { + ModalWindow modalWindow = findParent(ModalWindow.class); + if (modalWindow != null) { + modalWindow.close(target); + } + } + + /** + * @return confirmation type identifier + */ + public int getConfirmType() { + return confirmType; + } + + /** + * This method provides solution for reusing one confirmation dialog for more messages/actions + * by using confirmType identifier. See for example {@link com.evolveum.midpoint.web.page.admin.users.component.TreeTablePanel} + * + * @param confirmType + */ + public void setConfirmType(int confirmType) { + this.confirmType = confirmType; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java index 0cb7f9ad208..d301578cef6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java @@ -18,11 +18,13 @@ import javax.xml.namespace.QName; import org.apache.commons.lang.StringUtils; +import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.request.mapper.parameter.PageParameters; @@ -135,6 +137,13 @@ protected void showModalWindow(String id, AjaxRequestTarget target) { target.add(getFeedbackPanel()); } + protected void showModalWindow(Component body, IModel title, AjaxRequestTarget target) { + getPageBase().setMainPopupContent(body); + getPageBase().setMainPopupTitle(title); + getPageBase().showMainPopup(target); + target.add(getFeedbackPanel()); + } + protected void addPrismPropertyPanel(MarkupContainer parentComponent, String id, QName propertyName) { addPrismPropertyPanel(parentComponent, id, new ItemPath(propertyName)); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java index 29c036b86ea..2f66557c6e4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java @@ -21,59 +21,37 @@ import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.*; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.security.api.AuthorizationConstants; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.assignment.AssignmentEditorDto; -import com.evolveum.midpoint.web.component.assignment.AssignmentTablePanel; -import com.evolveum.midpoint.web.component.data.TablePanel; -import com.evolveum.midpoint.web.component.dialog.ConfirmationDialog; +import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.menu.cog.InlineMenu; import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction; import com.evolveum.midpoint.web.component.prism.*; import com.evolveum.midpoint.web.component.util.ObjectWrapperUtil; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.page.admin.server.PageTasks; -import com.evolveum.midpoint.web.page.admin.server.dto.TaskDto; -import com.evolveum.midpoint.web.page.admin.server.dto.TaskDtoProvider; -import com.evolveum.midpoint.web.page.admin.server.dto.TaskDtoProviderOptions; import com.evolveum.midpoint.web.page.admin.users.component.*; import com.evolveum.midpoint.web.page.admin.users.dto.FocusProjectionDto; import com.evolveum.midpoint.web.page.admin.users.dto.SimpleUserResourceProvider; import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; import com.evolveum.midpoint.web.resource.img.ImgResources; -import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.apache.wicket.Component; -import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; -import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; -import org.apache.wicket.markup.head.IHeaderResponse; -import org.apache.wicket.markup.head.JavaScriptHeaderItem; -import org.apache.wicket.markup.head.OnDomReadyHeaderItem; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.*; -import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.PackageResourceReference; -import org.apache.wicket.util.string.StringValue; import javax.xml.namespace.QName; @@ -369,7 +347,8 @@ private void deleteProjectionPerformed(AjaxRequestTarget target, IModel() { + + @Override + public String getObject() { + return createStringResource("pageAdminFocus.message.deleteAccountConfirm", + getSelectedProjections(projectionModel).size()).getString(); + } + }) { + + @Override + public void yesPerformed(AjaxRequestTarget target) { + ModalWindow modalWindow = findParent(ModalWindow.class); + if (modalWindow != null) { + modalWindow.close(target); + deleteAccountConfirmedPerformed(target, getSelectedProjections(projectionModel)); + } + } + }; + return dialog; + } + + private void deleteAccountConfirmedPerformed(AjaxRequestTarget target, + List selected) { + List accounts = projectionModel.getObject(); + for (FocusProjectionDto account : selected) { + if (UserDtoStatus.ADD.equals(account.getStatus())) { + accounts.remove(account); + } else { + account.setStatus(UserDtoStatus.DELETE); + } + } + target.add(get(createComponentPath(ID_SHADOWS))); + } + }