From 2bebf83dad50a5bd91a2f582faa525f707551e2a Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 17 Jan 2020 13:03:02 +0100 Subject: [PATCH] Add on-demand fetching of items for mappings This commit resolves MID-5772: When a mapping source is incomplete (e.g. $immediateRole/jpegPhoto) we load it on demand. Note that the solution provided here is not 100% finished, from both functional (MID-6001) and performance (MID-6002) point of view. This commit also fixes a fault in RepositoryCache where we considered non-user focus types (e.g. ServiceType, RoleType, OrgType) as loaded fully even with no RETRIEVE options specified. This is not true because they can contain jpegPhoto! Fixing this bug can result in some performance degradation because cache is avoided in more cases than before. See also MID-6003. Other minor changes: - SimpleTaskAdapter was renamed to NullTaskImpl and moved to task-api. - Minor refactorings were done. --- .../midpoint/prism/util/ItemDeltaItem.java | 4 +- .../midpoint/schema/SelectorOptions.java | 3 +- .../evolveum/midpoint/util/PrettyPrinter.java | 16 +- .../model/common/mapping/MappingFactory.java | 4 +- .../model/common/mapping/MappingImpl.java | 178 +++++----- .../model/common/AbstractModelCommonTest.java | 5 + .../common/expression/TestExpression.java | 4 +- .../common/expression/TestExpressionUtil.java | 9 +- .../common/mapping/MappingTestEvaluator.java | 19 +- .../common/mapping/TestMappingComplex.java | 12 +- .../common/mapping/TestMappingDomain.java | 16 +- .../mapping/TestMappingDynamicSimple.java | 36 +- .../mapping/TestMappingDynamicSysVar.java | 42 +-- .../model/common/mapping/TestMappingTime.java | 22 +- .../projector/mappings/MappingEvaluator.java | 20 +- .../common/expression/ExpressionUtil.java | 192 +---------- .../expression/PathExpressionResolver.java | 315 ++++++++++++++++++ .../repo/sql/AuditCleanupPerformanceTest.java | 4 +- .../evolveum/midpoint/repo/sql/AuditTest.java | 8 +- .../midpoint/repo/sql/CleanupTest.java | 4 +- .../midpoint/test/asserter/UserAsserter.java | 13 +- .../midpoint/task/api/test/NullTaskImpl.java} | 223 +++++++------ .../resources/photo/archetype-id-card.xml | 20 +- 23 files changed, 664 insertions(+), 505 deletions(-) create mode 100644 repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/PathExpressionResolver.java rename repo/{repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java => task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java} (69%) diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/util/ItemDeltaItem.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/util/ItemDeltaItem.java index 21b6d141e5a..e977550f8db 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/util/ItemDeltaItem.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/util/ItemDeltaItem.java @@ -49,13 +49,13 @@ public class ItemDeltaItem implem private D definition; private ItemPath resolvePath = ItemPath.EMPTY_PATH; - // Residual path is a temporary solution to Structured attriebutes in 3.x and 4.x. + // Residual path is a temporary solution to Structured attributes in 3.x and 4.x. // It should disappear in 5.x. private ItemPath residualPath = null; // The deltas in sub-items. E.g. if this object represents "ContainerDeltaContainer" // this property contains property deltas that may exist inside the container. - Collection> subItemDeltas; + private Collection> subItemDeltas; // For clone and ObjectDeltaObject protected ItemDeltaItem() { } diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java index f7322cb4f50..d7acbd9ed30 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java @@ -181,7 +181,8 @@ public boolean isRoot() { ItemPath.create(AccessCertificationCampaignType.F_CASE))); private static final Set> OBJECTS_NOT_RETURNED_FULLY_BY_DEFAULT = new HashSet<>(Arrays.asList( - UserType.class, FocusType.class, AssignmentHolderType.class, ObjectType.class, + UserType.class, RoleType.class, OrgType.class, ServiceType.class, AbstractRoleType.class, + FocusType.class, AssignmentHolderType.class, ObjectType.class, TaskType.class, LookupTableType.class, AccessCertificationCampaignType.class, ShadowType.class // because of index-only attributes )); diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/PrettyPrinter.java b/infra/util/src/main/java/com/evolveum/midpoint/util/PrettyPrinter.java index 9ddfc94352f..f3393da61a5 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/PrettyPrinter.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/PrettyPrinter.java @@ -251,19 +251,19 @@ public static String prettyPrint(Object value) { if (value == null) { return "null"; } - String out = null; if (value instanceof JAXBElement) { Object elementValue = ((JAXBElement)value).getValue(); - out = tryPrettyPrint(elementValue); - if (out != null) { - return ("JAXBElement("+((JAXBElement)value).getName()+","+out+")"); + String attempt = tryPrettyPrint(elementValue); + if (attempt != null) { + return ("JAXBElement("+((JAXBElement)value).getName()+","+attempt+")"); } } - out = tryPrettyPrint(value); - if (out == null) { - out = value.toString(); + String attempt = tryPrettyPrint(value); + if (attempt != null) { + return attempt; + } else { + return value.toString(); } - return out; } private static String tryPrettyPrint(Object value) { diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingFactory.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingFactory.java index 9a68cc5e986..71eb4431489 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingFactory.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingFactory.java @@ -77,12 +77,14 @@ public MappingImpl.Builder MappingImpl.Builder createMappingBuilder(MappingType mappingType, String shortDesc) { return this.createMappingBuilder().mappingType(mappingType) - .contextDescription(shortDesc); + .contextDescription(shortDesc) + .objectResolver(objectResolver); } } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java index 1d5d9c15fb5..4846546d528 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java @@ -6,44 +6,21 @@ */ package com.evolveum.midpoint.model.common.mapping; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.datatype.DatatypeConstants; -import javax.xml.datatype.Duration; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.schema.constants.ExpressionConstants; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.expression.ExpressionProfile; -import com.evolveum.midpoint.schema.expression.TypedValue; -import com.evolveum.midpoint.schema.expression.VariablesMap; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.DeltaSetTripleType; -import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; - import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.model.api.context.Mapping; -import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.util.ItemDeltaItem; import com.evolveum.midpoint.prism.util.ObjectDeltaObject; import com.evolveum.midpoint.repo.common.ObjectResolver; -import com.evolveum.midpoint.repo.common.expression.Expression; -import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; -import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; -import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; -import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; -import com.evolveum.midpoint.repo.common.expression.Source; -import com.evolveum.midpoint.repo.common.expression.ValuePolicyResolver; -import com.evolveum.midpoint.repo.common.expression.ValueSetDefinition; -import com.evolveum.midpoint.repo.common.expression.VariableProducer; +import com.evolveum.midpoint.repo.common.expression.*; +import com.evolveum.midpoint.schema.constants.ExpressionConstants; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.expression.ExpressionProfile; +import com.evolveum.midpoint.schema.expression.TypedValue; +import com.evolveum.midpoint.schema.expression.VariablesMap; import com.evolveum.midpoint.schema.internals.InternalsConfig; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.SchemaDebugUtil; @@ -52,15 +29,19 @@ import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -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.exception.SecurityViolationException; -import com.evolveum.midpoint.util.exception.TunnelException; +import com.evolveum.midpoint.util.exception.*; 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.prism.xml.ns._public.types_3.DeltaSetTripleType; +import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; +import org.jetbrains.annotations.NotNull; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; +import java.util.*; /** * @@ -85,7 +66,7 @@ public class MappingImpl implemen private final PrismContext prismContext; private final ObjectDeltaObject sourceContext; - private TypedValue> typedSourceContext; // cahced + private TypedValue> typedSourceContext; // cached private final Collection> sources; private final Source defaultSource; @@ -229,7 +210,7 @@ private TypedValue> getTypedSourceContext() { return null; } if (typedSourceContext == null) { - typedSourceContext = new TypedValue>(sourceContext, sourceContext.getDefinition()); + typedSourceContext = new TypedValue<>(sourceContext, sourceContext.getDefinition()); } return typedSourceContext; } @@ -251,6 +232,7 @@ public MappingType getMappingType() { return mappingType; } + @SuppressWarnings("unused") public MappingPreExpression getMappingPreExpression() { return mappingPreExpression; } @@ -395,6 +377,7 @@ public T getStateProperty(String propertyName) { if (stateProperties == null) { return null; } + //noinspection unchecked return (T) stateProperties.get(propertyName); } @@ -403,11 +386,13 @@ public T setStateProperty(String propertyName, T value) { if (stateProperties == null) { stateProperties = new HashMap<>(); } + //noinspection unchecked return (T)stateProperties.put(propertyName, value); } // TODO: rename to evaluateAll - public void evaluate(Task task, OperationResult parentResult) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException { + public void evaluate(Task task, OperationResult parentResult) throws ExpressionEvaluationException, ObjectNotFoundException, + SchemaException, SecurityViolationException, ConfigurationException, CommunicationException { OperationResult result = parentResult.subresult(OP_EVALUATE) .addArbitraryObjectAsContext("mapping", this) .addArbitraryObjectAsContext("context", getContextDescription()) @@ -443,8 +428,7 @@ public void evaluate(Task task, OperationResult parentResult) throws ExpressionE /** * Prepare mapping for evaluation. Parse the values - * After this call it can checked if a mapping is activated - * (i.e. if the input changes will "trigger" the mapping). + * After this call it can be checked if a mapping is activated (i.e. if the input changes will "trigger" the mapping). */ public void prepare(Task task, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, SecurityViolationException, @@ -600,7 +584,7 @@ private void checkRange(Task task, OperationResult result) private void checkRangeTarget(Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { - String name = null; + String name; if (outputPath != null) { name = outputPath.lastName().getLocalPart(); } else { @@ -862,6 +846,7 @@ private void parseTimeConstraints(Task task, OperationResult result) throws Sche return; } + //noinspection RedundantIfStatement if (timeTo == null) { // after timeFrom and no timeTo // no nextRecomputeTime set, there is nothing to recompute in the future @@ -925,15 +910,10 @@ private XMLGregorianCalendar parseTime(MappingTimeDeclarationType timeType, Task return time; } - private XMLGregorianCalendar parseTimeSource(VariableBindingDefinitionType sourceType, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { - ItemPathType itemPathType = sourceType.getPath(); - if (itemPathType == null) { - throw new SchemaException("No path in source definition in "+getMappingContextDescription()); - } - ItemPath path = itemPathType.getItemPath(); - if (path.isEmpty()) { - throw new SchemaException("Empty source path in "+getMappingContextDescription()); - } + private XMLGregorianCalendar parseTimeSource(VariableBindingDefinitionType source, Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, + SecurityViolationException, ExpressionEvaluationException { + ItemPath path = getSourcePath(source); Object sourceObject = ExpressionUtil.resolvePathGetValue(path, variables, false, getTypedSourceContext(), objectResolver, getPrismContext(), "reference time definition in "+getMappingContextDescription(), task, result); if (sourceObject == null) { @@ -941,62 +921,55 @@ private XMLGregorianCalendar parseTimeSource(VariableBindingDefinitionType sourc } PrismProperty timeProperty; if (sourceObject instanceof ItemDeltaItem) { + //noinspection unchecked timeProperty = (PrismProperty) ((ItemDeltaItem)sourceObject).getItemNew(); } else if (sourceObject instanceof Item) { + //noinspection unchecked timeProperty = (PrismProperty) sourceObject; } else { throw new IllegalStateException("Unknown resolve result "+sourceObject); } - if (timeProperty == null) { - return null; - } - return timeProperty.getRealValue(); + return timeProperty != null ? timeProperty.getRealValue() : null; } private void parseSources(Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, SecurityViolationException, ConfigurationException, CommunicationException { - List sourceTypes = mappingType.getSource(); + List sourceDefinitions = mappingType.getSource(); if (defaultSource != null) { defaultSource.recompute(); - sources.add(defaultSource); + this.sources.add(defaultSource); defaultSource.recompute(); } - if (sourceTypes != null) { - for (VariableBindingDefinitionType sourceType: sourceTypes) { - Source source = parseSource(sourceType, task, result); + if (sourceDefinitions != null) { + for (VariableBindingDefinitionType sourceDefinition: sourceDefinitions) { + Source source = parseSource(sourceDefinition, task, result); source.recompute(); // Override existing sources (e.g. default source) - sources.removeIf(next -> next.getName().equals(source.getName())); - sources.add(source); + this.sources.removeIf(next -> next.getName().equals(source.getName())); + this.sources.add(source); } } } - private Source parseSource(VariableBindingDefinitionType sourceType, + private Source parseSource(VariableBindingDefinitionType sourceDefinition, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { - ItemPathType itemPathType = sourceType.getPath(); - if (itemPathType == null) { - throw new SchemaException("No path in source definition in "+getMappingContextDescription()); - } - ItemPath path = itemPathType.getItemPath(); - if (path.isEmpty()) { - throw new SchemaException("Empty source path in "+getMappingContextDescription()); - } - QName sourceQName = sourceType.getName(); - if (sourceQName == null) { - sourceQName = ItemPath.toName(path.last()); - } + ItemPath path = getSourcePath(sourceDefinition); + QName sourceQName = sourceDefinition.getName() != null ? sourceDefinition.getName() : ItemPath.toName(path.last()); String variableName = sourceQName.getLocalPart(); - ItemPath resolvePath = path; - TypedValue typedSourceObject = ExpressionUtil.resolvePathGetTypedValue(path, variables, true, getTypedSourceContext(), objectResolver, getPrismContext(), "source definition in "+getMappingContextDescription(), task, result); - Object sourceObject = typedSourceObject.getValue(); + + TypedValue typedSourceObject = ExpressionUtil.resolvePathGetTypedValue(path, variables, true, + getTypedSourceContext(), objectResolver, getPrismContext(), + "source definition in "+getMappingContextDescription(), task, result); + + Object sourceObject = typedSourceObject != null ? typedSourceObject.getValue() : null; Item itemOld = null; ItemDelta delta = null; Item itemNew = null; + ItemPath resolvePath = path; ItemPath residualPath = null; Collection> subItemDeltas = null; if (sourceObject != null) { @@ -1023,12 +996,15 @@ private Source parseSo } } - ID sourceDefinition = (ID)typedSourceObject.getDefinition(); + // TODO what if typedSourceObject is null? + + //noinspection unchecked + ID sourceItemDefinition = (ID)typedSourceObject.getDefinition(); // apply domain - ValueSetDefinitionType domainSetType = sourceType.getSet(); + ValueSetDefinitionType domainSetType = sourceDefinition.getSet(); if (domainSetType != null) { - ValueSetDefinition setDef = new ValueSetDefinition<>(domainSetType, sourceDefinition, expressionProfile, variableName, "domain of "+variableName+" in "+getMappingContextDescription(), task, result); + ValueSetDefinition setDef = new ValueSetDefinition<>(domainSetType, sourceItemDefinition, expressionProfile, variableName, "domain of "+variableName+" in "+getMappingContextDescription(), task, result); setDef.init(expressionFactory); setDef.setAdditionalVariables(variables); try { @@ -1068,13 +1044,26 @@ private Source parseSo } } - Source source = new Source<>(itemOld, delta, itemNew, sourceQName, sourceDefinition); + Source source = new Source<>(itemOld, delta, itemNew, sourceQName, sourceItemDefinition); source.setResidualPath(residualPath); source.setResolvePath(resolvePath); source.setSubItemDeltas(subItemDeltas); return source; } + @NotNull + private ItemPath getSourcePath(VariableBindingDefinitionType sourceType) throws SchemaException { + ItemPathType itemPathType = sourceType.getPath(); + if (itemPathType == null) { + throw new SchemaException("No path in source definition in " + getMappingContextDescription()); + } + ItemPath path = itemPathType.getItemPath(); + if (path.isEmpty()) { + throw new SchemaException("Empty source path in " + getMappingContextDescription()); + } + return path; + } + private boolean sourcesChanged() { for (Source source: sources) { if (source.getDelta() != null) { @@ -1271,9 +1260,9 @@ private void transitionState(MappingEvaluationState newState) { state = newState; } - private void assertState(MappingEvaluationState expecetdState) { - if (state != expecetdState) { - throw new IllegalArgumentException("Expected mapping state "+expecetdState+", but was "+state); + private void assertState(MappingEvaluationState expectedState) { + if (state != expectedState) { + throw new IllegalArgumentException("Expected mapping state "+expectedState+", but was "+state); } } @@ -1337,6 +1326,7 @@ public int hashCode() { return result; } + @SuppressWarnings("RedundantIfStatement") @Override public boolean equals(Object obj) { if (this == obj) @@ -1806,7 +1796,7 @@ public Builder addVariableDefinition(ExpressionVariableDefinitionType varD } public Builder addVariableDefinition(String name, ObjectReferenceType objectRef) { - return addVariableDefinition(name, (Object)objectRef, objectRef.asReferenceValue().getDefinition()); + return addVariableDefinition(name, objectRef, objectRef.asReferenceValue().getDefinition()); } public Builder addVariableDefinition(String name, O objectType, Class expectedClass) { @@ -1824,19 +1814,19 @@ public Builder addVariableDefinition(String name, P public Builder addVariableDefinition(String name, String value) { MutablePrismPropertyDefinition def = prismContext.definitionFactory().createPropertyDefinition( new QName(SchemaConstants.NS_C, name), PrimitiveType.STRING.getQname()); - return addVariableDefinition(name, (Object)value, def); + return addVariableDefinition(name, value, def); } public Builder addVariableDefinition(String name, boolean value) { MutablePrismPropertyDefinition def = prismContext.definitionFactory().createPropertyDefinition( new QName(SchemaConstants.NS_C, name), PrimitiveType.BOOLEAN.getQname()); - return addVariableDefinition(name, (Object)value, def); + return addVariableDefinition(name, value, def); } public Builder addVariableDefinition(String name, int value) { MutablePrismPropertyDefinition def = prismContext.definitionFactory().createPropertyDefinition( new QName(SchemaConstants.NS_C, name), PrimitiveType.INT.getQname()); - return addVariableDefinition(name, (Object)value, def); + return addVariableDefinition(name, value, def); } // public Builder addVariableDefinition(String name, Element value) { @@ -1844,7 +1834,7 @@ public Builder addVariableDefinition(String name, int value) { // } public Builder addVariableDefinition(String name, PrismValue value) { - return addVariableDefinition(name, (Object)value, value.getParent().getDefinition()); + return addVariableDefinition(name, value, value.getParent().getDefinition()); } public Builder addVariableDefinition(String name, ObjectDeltaObject value) { @@ -1852,7 +1842,7 @@ public Builder addVariableDefinition(String name, ObjectDeltaObject val if (definition == null) { throw new IllegalArgumentException("Attempt to set variable '"+name+"' as ODO without a definition: "+value); } - return addVariableDefinition(name,(Object)value, definition); + return addVariableDefinition(name, value, definition); } public Builder addAliasRegistration(String alias, String mainVariable) { @@ -1875,7 +1865,7 @@ public Builder addVariableDefinition(String name, Object value, Class t return this; } - public boolean hasVariableDefinition(QName varName) { + public boolean hasVariableDefinition(String varName) { return variables.containsKey(varName); } diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/AbstractModelCommonTest.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/AbstractModelCommonTest.java index 31fb5b84d28..10e2894d0d8 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/AbstractModelCommonTest.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/AbstractModelCommonTest.java @@ -8,6 +8,8 @@ import java.io.File; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import com.evolveum.midpoint.test.util.TestUtil; /** @@ -33,4 +35,7 @@ protected void displayThen(final String TEST_NAME) { TestUtil.displayThen(TEST_NAME); } + protected Task createTask() { + return new NullTaskImpl(); + } } diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpression.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpression.java index df4ccf35b74..5c4094aad8b 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpression.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpression.java @@ -397,7 +397,7 @@ public void test200IterationCondition() throws Exception { variables.put(ExpressionConstants.VAR_ITERATION_TOKEN, "001", TestUtil.createPrimitivePropertyDefinition(prismContext, ExpressionConstants.VAR_ITERATION_TOKEN, PrimitiveType.STRING)); - ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(null , variables, TEST_NAME, null); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(null , variables, TEST_NAME, createTask()); // WHEN PrismValueDeltaSetTriple> outputTriple = @@ -445,7 +445,7 @@ protected PrismValueDeltaSetTri ExpressionType expressionType, D outputDefinition, ExpressionEvaluationContext expressionContext, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { - Expression expression = expressionFactory.makeExpression(expressionType, outputDefinition , getExpressionProfile(), + Expression expression = expressionFactory.makeExpression(expressionType, outputDefinition, getExpressionProfile(), expressionContext.getContextDescription(), expressionContext.getTask(), result); LOGGER.debug("Starting evaluation of expression: {}", expression); return expression.evaluate(expressionContext, result); diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionUtil.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionUtil.java index 452f210b4fa..39012203f3f 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionUtil.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionUtil.java @@ -15,6 +15,9 @@ import com.evolveum.midpoint.prism.util.ObjectDeltaObject; import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.repo.common.DirectoryFileObjectResolver; +import com.evolveum.midpoint.repo.common.ObjectResolver; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import org.testng.annotations.Test; import java.io.File; @@ -200,12 +203,14 @@ private T resolvePath(String path, ExpressionVariables variables, final Stri ItemPath itemPath = toItemPath(path); // WHEN - Object resolved = ExpressionUtil.resolvePathGetValue(itemPath, variables, false, null, null, - PrismTestUtil.getPrismContext(), TEST_NAME, null, result); + ObjectResolver objectResolver = new DirectoryFileObjectResolver(MidPointTestConstants.OBJECTS_DIR); + Object resolved = ExpressionUtil.resolvePathGetValue(itemPath, variables, false, null, objectResolver, + PrismTestUtil.getPrismContext(), TEST_NAME, new NullTaskImpl(), result); // THEN IntegrationTestTools.display("Resolved", resolved); + //noinspection unchecked return (T) resolved; } diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/MappingTestEvaluator.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/MappingTestEvaluator.java index 9d1e5f67cad..974aa800b06 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/MappingTestEvaluator.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/MappingTestEvaluator.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import org.xml.sax.SAXException; @@ -279,7 +280,7 @@ public PrismValueDeltaSetTriple> evaluateMapping(Str throws SchemaException, IOException, JAXBException, ExpressionEvaluationException, ObjectNotFoundException, EncryptionException, SecurityViolationException, ConfigurationException, CommunicationException { MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyPath, null); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -293,7 +294,7 @@ public PrismValueDeltaSetTriple> evaluateMapping(Str throws SchemaException, IOException, JAXBException, ExpressionEvaluationException, ObjectNotFoundException, EncryptionException, SecurityViolationException, ConfigurationException, CommunicationException { MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, null); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -307,7 +308,7 @@ public PrismValueDeltaSetTriple> evaluateMapping(Str throws SchemaException, IOException, JAXBException, ExpressionEvaluationException, ObjectNotFoundException, EncryptionException, SecurityViolationException, ConfigurationException, CommunicationException { MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, null); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -339,7 +340,7 @@ public PrismValueDeltaSetTriple> evaluateMappingDyna valuesToAdd); MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyPath, userDelta); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -356,7 +357,7 @@ public PrismValueDeltaSetTriple> evaluateMappingDyna valuesToAdd); MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, userDelta); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -373,7 +374,7 @@ public PrismValueDeltaSetTriple> evaluateMappingDyna valuesToReplace); MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, userDelta); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -390,7 +391,7 @@ public PrismValueDeltaSetTriple> evaluateMappingDyna valuesToReplace); MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, userDelta); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -408,7 +409,7 @@ public PrismValueDeltaSetTriple> evaluateMappingDyna MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, userDelta); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { @@ -425,7 +426,7 @@ public PrismValueDeltaSetTriple> evaluateMappingDyna valuesToReplace); MappingImpl,PrismPropertyDefinition> mapping = createMapping(filename, testName, defaultTargetPropertyName, userDelta); OperationResult opResult = new OperationResult(testName); - mapping.evaluate(null, opResult); + mapping.evaluate(new NullTaskImpl(), opResult); assertResult(opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); if (outputTriple != null) { diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingComplex.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingComplex.java index cebc26cb049..6ca0b3af3aa 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingComplex.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingComplex.java @@ -60,7 +60,7 @@ public void testModifyObjectSetAdditionalName() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -91,7 +91,7 @@ public void testModifyObjectSetAdditionalNameFalse() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -118,7 +118,7 @@ public void testModifyObjectUnrelated() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -148,7 +148,7 @@ public void testModifyObjectUnrelatedFalse() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -173,7 +173,7 @@ public void testAddObjectUnrelatedFalse() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -197,7 +197,7 @@ public void testAddObjectUnrelatedEmptyFalse() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDomain.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDomain.java index cdbfc0a2123..b9da769043e 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDomain.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDomain.java @@ -11,6 +11,8 @@ import java.io.IOException; import java.util.List; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.xml.sax.SAXException; @@ -73,7 +75,7 @@ public void testControlReplaceSingleValue() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -83,6 +85,10 @@ public void testControlReplaceSingleValue() throws Exception { PrismAsserts.assertTripleMinus(outputTriple, PrismTestUtil.createPolyString("Pirate null (1234567890)")); } + private Task createTask() { + return new NullTaskImpl(); + } + /** * Control. All goes well here. All values in the domain. */ @@ -112,7 +118,7 @@ public void testControlReplaceMultiValue() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -155,7 +161,7 @@ public void testReplaceMixedMultiValue() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN TestUtil.displayThen(TEST_NAME); @@ -199,7 +205,7 @@ public void testAddMixedMultiValue() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN TestUtil.displayThen(TEST_NAME); @@ -246,7 +252,7 @@ public void testDeleteMixedMultiValue() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN TestUtil.displayThen(TEST_NAME); diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSimple.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSimple.java index 8412d600884..48803088a07 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSimple.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSimple.java @@ -618,7 +618,7 @@ public void testScriptExtraVariablesRef() throws Exception { OperationResult opResult = new OperationResult("testScriptExtraVariablesRef"); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -647,7 +647,7 @@ public void testScriptExtraVariablesJaxb() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -711,7 +711,7 @@ public void testScriptFullNameDeleteGivenName() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -743,7 +743,7 @@ public void testScriptFullNameDeleteGivenNameFromNull() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -773,7 +773,7 @@ public void testScriptFullNameDeleteGivenNameFamilyName() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -933,7 +933,7 @@ public void testConditionNonEmptyCaptain() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -961,7 +961,7 @@ public void testConditionNonEmptyEmpty() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -985,7 +985,7 @@ public void testConditionNonEmptyNoValue() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -1020,7 +1020,7 @@ public void testScriptTransformMultiAddDelete() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN TestUtil.displayThen(TEST_NAME); @@ -1060,7 +1060,7 @@ public void testScriptTransformMultiReplace() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN TestUtil.displayThen(TEST_NAME); @@ -1099,7 +1099,7 @@ public void testInboundMapping() throws Exception{ OperationResult opResult = new OperationResult(TEST_NAME); displayWhen(TEST_NAME); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); outputTriple.checkConsistence(); @@ -1121,7 +1121,7 @@ public void testGenerateDefault() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN (1) - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN (1) PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -1135,7 +1135,7 @@ public void testGenerateDefault() throws Exception { mapping = evaluator.createMapping("mapping-generate.xml", TEST_NAME, stringPolicy, "employeeNumber", null); // WHEN (2) - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN (2) outputTriple = mapping.getOutputTriple(); @@ -1194,7 +1194,7 @@ private void generatePolicy(final String TEST_NAME, String mappingFileName, Stri OperationResult opResult = new OperationResult(TEST_NAME); // WHEN (1) - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN (1) PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -1211,7 +1211,7 @@ private void generatePolicy(final String TEST_NAME, String mappingFileName, Stri mapping = evaluator.createMapping(mappingFileName, TEST_NAME, stringPolicy, "employeeNumber", null); // WHEN (2) - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN (2) outputTriple = mapping.getOutputTriple(); @@ -1284,7 +1284,7 @@ private void generatePolicyNumeric(final String TEST_NAME, String mappingFil OperationResult opResult = new OperationResult(TEST_NAME); // WHEN (1) - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN (1) PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -1307,7 +1307,7 @@ private void generatePolicyNumeric(final String TEST_NAME, String mappingFil .build(); // WHEN (2) - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN (2) outputTriple = mapping.getOutputTriple(); @@ -1332,7 +1332,7 @@ public void testGenerateProtectedString() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSysVar.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSysVar.java index 9fa556805c5..0e5820b9caa 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSysVar.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingDynamicSysVar.java @@ -88,7 +88,7 @@ public void testScriptSystemVariablesConditionAddObjectTrue(String filename) thr OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -117,7 +117,7 @@ public void testScriptSystemVariablesConditionModifyObjectTrueGroovyUnrelated() OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -151,7 +151,7 @@ public void testScriptSystemVariablesConditionAddObjectFalse(String filename) th OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -185,7 +185,7 @@ public void testScriptSystemVariablesConditionAddObjectFalseNoVal(String filenam OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -219,7 +219,7 @@ public void testScriptSystemVariablesConditionAddObjectFalseNoProperty(String fi OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -252,7 +252,7 @@ public void testScriptSystemVariablesConditionTrueToTrue(String filename) throws OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -282,7 +282,7 @@ public void testScriptSystemVariablesConditionFalseToFalse(String filename) thro OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -310,7 +310,7 @@ public void testScriptSystemVariablesConditionFalseToTrue(String filename) throw OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -344,7 +344,7 @@ public void testScriptSystemVariablesConditionTrueToFalse(String filename) throw OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -397,7 +397,7 @@ public void testScriptSystemVariablesConditionEmptyTrue(final String TEST_NAME, OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -437,7 +437,7 @@ public void testScriptSystemVariablesConditionEmptyFalseToTrue(final String TEST OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -490,7 +490,7 @@ public void testScriptSystemVariablesConditionEmptyFalse(final String TEST_NAME, OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -528,7 +528,7 @@ public void testScriptSystemVariablesConditionEmptyTrueToFalse(final String TEST OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -554,7 +554,7 @@ public void testNpeFalseToTrue() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -584,7 +584,7 @@ public void testNpeTrueToFalse() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -612,7 +612,7 @@ public void testPathEnum() throws Exception { // WHEN System.out.println("WHEN"); LOGGER.info("WHEN"); - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -764,7 +764,7 @@ public void testEmployeeTypeDeltaAreplaceB() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN evaluator.assertResult(opResult); @@ -795,7 +795,7 @@ public void testEmployeeTypeDeltaNullreplaceB() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN evaluator.assertResult(opResult); @@ -826,7 +826,7 @@ public void testEmployeeTypeDeltaBreplaceB() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN evaluator.assertResult(opResult); @@ -916,7 +916,7 @@ public PrismValueDeltaSetTriple> employeeTypeDeltaABA OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN evaluator.assertResult(opResult); @@ -1009,7 +1009,7 @@ public PrismValueDeltaSetTriple> employeeTypeDeltaDel OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN evaluator.assertResult(opResult); diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingTime.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingTime.java index 06336cf90f3..4232dc62dd9 100644 --- a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingTime.java +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/mapping/TestMappingTime.java @@ -14,6 +14,8 @@ import javax.xml.datatype.XMLGregorianCalendar; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.xml.sax.SAXException; @@ -76,7 +78,7 @@ public void testBeforeTimeFrom() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -84,6 +86,10 @@ public void testBeforeTimeFrom() throws Exception { assertNextRecompute(mapping, TIME_MAPPING_DISABLED_PLUS_1D); } + private Task createTask() { + return new NullTaskImpl(); + } + @Test public void testBetweenTimes() throws Exception { final String TEST_NAME = "testBetweenTimes"; @@ -104,7 +110,7 @@ public void testBetweenTimes() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -135,7 +141,7 @@ public void testAfterTimeTo() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -165,7 +171,7 @@ public void testExistenceBefore() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -195,7 +201,7 @@ public void testExistenceAfter() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -231,7 +237,7 @@ public void testNoReferenceTime() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -271,7 +277,7 @@ public void testSetReferenceTimeBefore() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); @@ -310,7 +316,7 @@ public void testSetReferenceTimeAfter() throws Exception { OperationResult opResult = new OperationResult(TEST_NAME); // WHEN - mapping.evaluate(null, opResult); + mapping.evaluate(createTask(), opResult); // THEN PrismValueDeltaSetTriple> outputTriple = mapping.getOutputTriple(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java index 9169347f443..521d13f98e0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java @@ -17,6 +17,7 @@ import com.evolveum.midpoint.model.impl.lens.projector.*; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.common.ObjectResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -77,20 +78,26 @@ public class MappingEvaluator { @Autowired private CredentialsProcessor credentialsProcessor; @Autowired private ContextLoader contextLoader; @Autowired private PrismContext prismContext; + @Autowired private ObjectResolver objectResolver; public PrismContext getPrismContext() { return prismContext; } - public static final List FOCUS_VARIABLE_NAMES = Arrays.asList(ExpressionConstants.VAR_FOCUS, ExpressionConstants.VAR_USER); + static final List FOCUS_VARIABLE_NAMES = Arrays.asList(ExpressionConstants.VAR_FOCUS, ExpressionConstants.VAR_USER); - public void evaluateMapping( - MappingImpl mapping, LensContext lensContext, Task task, OperationResult parentResult) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException { + public void evaluateMapping(MappingImpl mapping, + LensContext lensContext, Task task, OperationResult parentResult) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, SecurityViolationException, + ConfigurationException, CommunicationException { evaluateMapping(mapping, lensContext, null, task, parentResult); } - public void evaluateMapping( - MappingImpl mapping, LensContext lensContext, LensProjectionContext projContext, Task task, OperationResult parentResult) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException { + public void evaluateMapping(MappingImpl mapping, + LensContext lensContext, LensProjectionContext projContext, Task task, OperationResult parentResult) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, SecurityViolationException, + ConfigurationException, CommunicationException { + ExpressionEnvironment env = new ExpressionEnvironment<>(); env.setLensContext(lensContext); env.setProjectionContext(projContext); @@ -98,6 +105,7 @@ public vo env.setCurrentResult(parentResult); env.setCurrentTask(task); ModelExpressionThreadLocalHolder.pushExpressionEnvironment(env); + ObjectType originObject = mapping.getOriginObject(); String objectOid, objectName, objectTypeName; if (originObject != null) { @@ -108,6 +116,7 @@ public vo objectOid = objectName = objectTypeName = null; } String mappingName = mapping.getItemName() != null ? mapping.getItemName().getLocalPart() : null; + long start = System.currentTimeMillis(); try { task.recordState("Started evaluation of mapping " + mapping.getMappingContextDescription() + "."); @@ -681,6 +690,7 @@ public ValuePolicyType resolve() { .originalTargetValues(targetValues) .originType(OriginType.USER_POLICY) .originObject(originObject) + .objectResolver(objectResolver) .valuePolicyResolver(stringPolicyResolver) .rootNode(focusOdo) .now(now); diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionUtil.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionUtil.java index fd3fcf7df87..beb94516901 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionUtil.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionUtil.java @@ -24,7 +24,6 @@ import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.MutablePrismPropertyDefinition; import com.evolveum.midpoint.prism.Objectable; -import com.evolveum.midpoint.prism.PartiallyResolvedItem; import com.evolveum.midpoint.prism.PrimitiveType; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; @@ -63,7 +62,6 @@ import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.prism.query.UndefinedFilter; import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.prism.util.DefinitionResolver; import com.evolveum.midpoint.prism.util.ItemDeltaItem; import com.evolveum.midpoint.prism.util.JavaTypeConverter; import com.evolveum.midpoint.prism.util.ObjectDeltaObject; @@ -222,189 +220,11 @@ public static Object resolvePathGetValue(ItemPath path, ExpressionVariables vari * 1. consider setting this parameter to true at some other places where it might be relevant * 2. consider normalizing delete deltas earlier in the clockwork, probably at the very beginning of the operation */ - public static TypedValue resolvePathGetTypedValue(ItemPath path, ExpressionVariables variables, boolean normalizeValuesToDelete, - TypedValue defaultContext, ObjectResolver objectResolver, PrismContext prismContext, String shortDesc, Task task, OperationResult result) - throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { - - TypedValue root = defaultContext; - ItemPath relativePath = path; - Object first = path.first(); - String topVarDesc = "default context"; - if (ItemPath.isVariable(first)) { - String topVarName = ItemPath.toVariableName(first).getLocalPart(); - topVarDesc = "variable " + PrettyPrinter.prettyPrint(topVarName); - relativePath = path.rest(); - if (variables.containsKey(topVarName)) { - root = variables.get(topVarName); - } else { - throw new SchemaException("No variable with name " + topVarName + " in " + shortDesc); - } - } - if (root == null) { - return null; - } - if (relativePath.isEmpty()) { - return root; - } - - if (normalizeValuesToDelete) { - root = normalizeValuesToDelete(root); - } - - if (root.getValue() instanceof ObjectReferenceType) { - root = resolveReference((TypedValue) root, objectResolver, topVarDesc, shortDesc, task, - result); - } - - String lastPathSegmentName = relativePath.lastName().getLocalPart(); - - Object rootValue = root.getValue(); - if (rootValue == null) { - // The result value is going to be null, but we still need a definition. Try to determine that from root definition. - if (root.getDefinition() == null) { - throw new IllegalArgumentException("No definition for path "+path+": "+root); - } - // Relative path is not empty here. Therefore the root must be a container. - ItemDefinition subitemDefinition = ((PrismContainerDefinition)root.getDefinition()).findItemDefinition(relativePath); - if (subitemDefinition == null) { - // this must be something dynamic, e.g. assignment extension. Just assume string here. Not completely correct. But what can we do? - subitemDefinition = prismContext.definitionFactory().createPropertyDefinition(relativePath.lastName(), PrimitiveType.STRING.getQname()); - } - return new TypedValue<>(null, subitemDefinition); - } - - if (rootValue instanceof Objectable) { - return determineTypedValue(prismContext, lastPathSegmentName, ((Objectable) rootValue).asPrismObject(), relativePath); - } - if (rootValue instanceof PrismObject) { - return determineTypedValue(prismContext, lastPathSegmentName, (PrismObject) rootValue, relativePath); - } else if (rootValue instanceof PrismContainer) { - return determineTypedValue(prismContext, lastPathSegmentName, (PrismContainer) rootValue, relativePath); - } else if (rootValue instanceof PrismContainerValue) { - return determineTypedValue(prismContext, lastPathSegmentName, (PrismContainerValue) rootValue, relativePath); - } else if (rootValue instanceof Item) { - // Except for container (which is handled above) - throw new SchemaException( - "Cannot apply path " + relativePath + " to " + root + " in " + shortDesc); - } else if (rootValue instanceof ObjectDeltaObject) { - return determineTypedValueOdo(prismContext, lastPathSegmentName, root, relativePath); - } else if (rootValue instanceof ItemDeltaItem) { - return determineTypedValue(prismContext, lastPathSegmentName, (ItemDeltaItem) rootValue, relativePath); - } else { - throw new IllegalArgumentException( - "Unexpected root " + rootValue + " (relative path:" + relativePath + ") in " + shortDesc); - } - } - - private static TypedValue determineTypedValue(PrismContext prismContext, String name, PrismContainer rootContainer, ItemPath relativePath) throws SchemaException { - Object value; - PartiallyResolvedItem partiallyResolvedItem = rootContainer.findPartial(relativePath); - if (partiallyResolvedItem == null) { - value = null; - } else { - if (partiallyResolvedItem.getResidualPath() == null) { - value = partiallyResolvedItem.getItem(); - } else { - Object parentValue = partiallyResolvedItem.getItem().getRealValue(); - if (parentValue instanceof Structured) { - value = ((Structured)parentValue).resolve(partiallyResolvedItem.getResidualPath()); - } else { - throw new SchemaException("No subpath "+partiallyResolvedItem.getResidualPath()+" in "+partiallyResolvedItem.getItem()); - } - } - } - ItemDefinition def = determineItemDefinition(rootContainer.getDefinition(), relativePath); - if (def == null) { - throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootContainer+", value: "+value); - } - return new TypedValue<>((T)value, def); - } - - private static TypedValue determineTypedValue(PrismContext prismContext, String name, PrismContainerValue rootContainerValue, ItemPath relativePath) throws SchemaException { - Item value = rootContainerValue.findItem(relativePath); - ItemDefinition def = determineItemDefinition(rootContainerValue.getDefinition(), relativePath); - if (def == null) { - throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootContainerValue+", value: "+value); - } - return new TypedValue<>((T)value, def); - } - - private static TypedValue determineTypedValue(PrismContext prismContext, String name, ItemDeltaItem rootIdi, ItemPath relativePath) throws SchemaException { - ItemDeltaItem value = rootIdi.findIdi(relativePath); - ItemDefinition def = determineItemDefinition((PrismContainerDefinition)rootIdi.getDefinition(), relativePath); - if (def == null) { - throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootIdi+", value: "+value); - } - return new TypedValue<>((T)value, def); - } - - private static TypedValue determineTypedValueOdo(PrismContext prismContext, String name, TypedValue root, ItemPath relativePath) throws SchemaException { - ObjectDeltaObject rootOdo = (ObjectDeltaObject) root.getValue(); - DefinitionResolver, ItemDefinition> resolver = (rootDef,path) -> { - // We are called just before failure. Therefore all normal ways of resolving of definition did not work. - ItemDefinition parentDef = rootDef.findItemDefinition(path.allExceptLast()); - if (parentDef != null && parentDef.isDynamic()) { - // This is the case of dynamic schema extensions, such as assignment extension. - // Those may not have a definition. In that case just assume strings. - // In fact, this is a HACK. All such schemas should have a definition. - // Otherwise there may be problems with parameter types for caching compiles scripts and so on. - return prismContext.definitionFactory().createPropertyDefinition(path.firstName(), PrimitiveType.STRING.getQname()); - } - return null; - }; - ItemDeltaItem subValue = rootOdo.findIdi(relativePath, resolver); - PrismObjectDefinition rootDefinition = root.getDefinition(); - if (rootDefinition == null) { - rootDefinition = rootOdo.getDefinition(); - if (rootDefinition == null) { - throw new IllegalArgumentException("Found ODO without a definition while processing variable '"+name+"': "+rootOdo); - } - } - ItemDefinition def = determineItemDefinition(rootDefinition, relativePath); - if (def == null) { - throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootOdo+", value: "+subValue); - } - return new TypedValue<>((T)subValue, def); - } - - private static ItemDefinition determineItemDefinition(PrismContainerDefinition containerDefinition, ItemPath relativePath) { - ItemDefinition def = containerDefinition.findItemDefinition(relativePath); - if (def != null) { - return def; - } - // This may be a wrong path. Or it may be a path to a "subproperty" of a structured property, such as PolyString/norm. - // Let's find out by looking at the parent. - ItemPath parentPath = relativePath.allExceptLast(); - ItemDefinition parentDef = containerDefinition.findItemDefinition(parentPath); - if (parentDef == null) { - return null; - } - if (parentDef instanceof PrismContainerDefinition) { - if (parentDef.isDynamic() && ((PrismContainerDefinition)parentDef).isEmpty()) { - // The case of dynamic schema for which there are no definitions - // E.g. assignment extension - // just default to single-value strings. Better than nothing. At least for now. - return parentDef.getPrismContext().definitionFactory().createPropertyDefinition(relativePath.lastName(), PrimitiveType.STRING.getQname()); - } - } else if ((parentDef instanceof PrismPropertyDefinition)) { - if (PrismUtil.isStructuredType(parentDef.getTypeName())) { - // All "subproperties" are hardcoded as singlevalue strings - return parentDef.getPrismContext().definitionFactory().createPropertyDefinition(relativePath.lastName(), PrimitiveType.STRING.getQname()); - } - } - return null; - } - - private static TypedValue normalizeValuesToDelete(TypedValue root) { - Object rootValue = root.getValue(); - if (rootValue instanceof ObjectDeltaObject) { - return new TypedValue(((ObjectDeltaObject) rootValue).normalizeValuesToDelete(true), root.getDefinition()); - } else if (rootValue instanceof ItemDeltaItem) { - // TODO normalize as well - return root; - } else { - return root; - } + public static TypedValue resolvePathGetTypedValue(ItemPath path, ExpressionVariables variables, boolean normalizeValuesToDelete, + TypedValue defaultContext, ObjectResolver objectResolver, PrismContext prismContext, String shortDesc, Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + return new PathExpressionResolver(path, variables, normalizeValuesToDelete, defaultContext, objectResolver, prismContext, shortDesc, task) + .resolve(result); } public static Collection computeTargetValues( @@ -571,7 +391,7 @@ public static TypedValue convertVariableValue(TypedValue originalTyped return convertedTypeValue; } - private static TypedValue> resolveReference(TypedValue refAndDef, ObjectResolver objectResolver, + static TypedValue> resolveReference(TypedValue refAndDef, ObjectResolver objectResolver, String varDesc, String contextDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { ObjectReferenceType ref = (ObjectReferenceType) refAndDef.getValue(); diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/PathExpressionResolver.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/PathExpressionResolver.java new file mode 100644 index 00000000000..89bd3714e9f --- /dev/null +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/PathExpressionResolver.java @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.repo.common.expression; + +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.util.DefinitionResolver; +import com.evolveum.midpoint.prism.util.ItemDeltaItem; +import com.evolveum.midpoint.prism.util.ObjectDeltaObject; +import com.evolveum.midpoint.prism.util.PrismUtil; +import com.evolveum.midpoint.repo.common.ObjectResolver; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.expression.TypedValue; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +import static com.evolveum.midpoint.repo.common.expression.ExpressionUtil.resolveReference; + +/** + * Resolves expression paths (e.g. $immediateRole/jpegPhoto). + * + * Factored out from ExpressionUtil. + */ +class PathExpressionResolver { + + private static final Trace LOGGER = TraceManager.getTrace(PathExpressionResolver.class); + + /** + * Path to be resolved, e.g. "$focus/name" or "assignment". + */ + @NotNull private final ItemPath path; + + /** + * Variable name, if present (e.g. focus, immediateRole, ...). + */ + private final String variableName; + + /** + * Path without the variable name, e.g. "name", "assignment", ... + */ + @NotNull private final ItemPath relativePath; + + /** + * Variables that can be pointed to by the variable name (e.g. focus, immediateRole). + */ + @NotNull private final ExpressionVariables variables; + + /** + * Default object to be used if the path does not start with a variable. + */ + private final TypedValue defaultContext; + + /** + * Whether to normalize container values that are to be deleted, i.e. convert them from id-only to full data (MID-4863). + */ + private final boolean normalizeValuesToDelete; + + @NotNull private final ObjectResolver objectResolver; + @NotNull private final PrismContext prismContext; + + @NotNull private final String shortDesc; + @NotNull private final Task task; + + PathExpressionResolver(@NotNull ItemPath path, @NotNull ExpressionVariables variables, boolean normalizeValuesToDelete, + TypedValue defaultContext, @NotNull ObjectResolver objectResolver, @NotNull PrismContext prismContext, + @NotNull String shortDesc, @NotNull Task task) { + this.path = path; + if (path.startsWithVariable()) { + this.variableName = path.firstToVariableNameOrNull().getLocalPart(); + this.relativePath = path.rest(); + } else { + this.variableName = null; + this.relativePath = path; + } + this.variables = variables; + this.normalizeValuesToDelete = normalizeValuesToDelete; + this.defaultContext = defaultContext; + this.objectResolver = objectResolver; + this.prismContext = prismContext; + this.shortDesc = shortDesc; + this.task = task; + } + + /** + * Main entry point. + */ + TypedValue resolve(OperationResult result) throws SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + TypedValue root; + String topVarDesc; + if (variableName != null) { + topVarDesc = "variable " + variableName; + if (variables.containsKey(variableName)) { + root = variables.get(variableName); + } else { + throw new SchemaException("No variable with name " + variableName + " in " + shortDesc); + } + } else { + topVarDesc = "default context"; + root = defaultContext; + } + + if (root == null) { + return null; + } + if (relativePath.isEmpty()) { + return root; + } + + if (normalizeValuesToDelete) { + root = normalizeValuesToDelete(root); + } + + if (root.getValue() instanceof ObjectReferenceType) { + //noinspection unchecked + root = resolveReference((TypedValue) root, objectResolver, topVarDesc, shortDesc, task, result); + } + + String lastPathSegmentName = relativePath.lastName().getLocalPart(); + + Object rootValue = root.getValue(); + if (rootValue == null) { + return determineNullTypedValue(root); + } else if (rootValue instanceof Objectable) { + return determineTypedValue(((Objectable) rootValue).asPrismObject(), false, result); + } else if (rootValue instanceof PrismObject) { + return determineTypedValue((PrismObject) rootValue, false, result); + } else if (rootValue instanceof PrismContainer) { + return determineTypedValue((PrismContainer) rootValue, false, result); + } else if (rootValue instanceof PrismContainerValue) { + return determineTypedValue((PrismContainerValue) rootValue); + } else if (rootValue instanceof Item) { + // Except for container (which is handled above) + throw new SchemaException( + "Cannot apply path " + relativePath + " to " + root + " in " + shortDesc); + } else if (rootValue instanceof ObjectDeltaObject) { + return determineTypedValueOdo(lastPathSegmentName, root); + } else if (rootValue instanceof ItemDeltaItem) { + return determineTypedValue((ItemDeltaItem) rootValue); + } else { + throw new IllegalArgumentException( + "Unexpected root " + rootValue + " (relative path:" + relativePath + ") in " + shortDesc); + } + } + + @NotNull + private TypedValue determineNullTypedValue(TypedValue root) { + // Even if the result value is going to be null, we still need a definition. Here we try to determine that from root definition. + if (root.getDefinition() == null) { + throw new IllegalArgumentException("Root item has no definition for path "+path+". Root="+root); + } + ItemDefinition resultDefinition; + // Relative path is not empty here. Therefore the root must be a container. + ItemDefinition subItemDefinition = ((PrismContainerDefinition)root.getDefinition()).findItemDefinition(relativePath); + if (subItemDefinition != null) { + resultDefinition = subItemDefinition; + } else { + // this must be something dynamic, e.g. assignment extension. Just assume string here. Not completely correct. But what can we do? + resultDefinition = prismContext.definitionFactory() + .createPropertyDefinition(relativePath.lastName(), PrimitiveType.STRING.getQname()); + } + return new TypedValue<>(null, resultDefinition); + } + + @NotNull + private TypedValue determineTypedValue(PrismContainer rootContainer, boolean objectAlreadyFetched, + OperationResult result) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, + ConfigurationException, ExpressionEvaluationException { + Object value; + PartiallyResolvedItem> partiallyResolvedItem = rootContainer.findPartial(relativePath); + if (partiallyResolvedItem == null) { + value = null; + } else { + if (partiallyResolvedItem.getResidualPath() == null) { + value = partiallyResolvedItem.getItem(); + } else { + Object parentValue = partiallyResolvedItem.getItem().getRealValue(); + if (parentValue instanceof Structured) { + value = ((Structured)parentValue).resolve(partiallyResolvedItem.getResidualPath()); + } else { + throw new SchemaException("No subpath "+partiallyResolvedItem.getResidualPath()+" in "+partiallyResolvedItem.getItem()); + } + } + } + if (value instanceof Item && ((Item) value).isIncomplete()) { + if (objectAlreadyFetched) { + LOGGER.warn("Referencing incomplete item {} in {} but it is marked as incomplete even if the object was fully fetched", value, rootContainer); + } else if (!(rootContainer instanceof PrismObject)) { + LOGGER.warn("Unable to resolve incomplete item {} in {} because the root is not a prism object", value, rootContainer); + } else { + PrismObject rootObject = (PrismObject) rootContainer; + LOGGER.info("Fetching {} because of incomplete item {}", rootObject, value); + //noinspection unchecked + Class type = (Class) rootObject.asObjectable().getClass(); + // Let's retrieve everything (at least for now). In the future we could ask just for the single item. + Collection> options = + SelectorOptions.createCollection(GetOperationOptions.createRetrieve()); + ObjectType object = objectResolver.getObject(type, rootObject.getOid(), options, task, result); + return determineTypedValue(object.asPrismObject(), true, result); + } + } + ItemDefinition def = determineItemDefinition(rootContainer.getDefinition(), relativePath); + if (def == null) { + throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootContainer+", value: "+value); + } + return new TypedValue<>(value, def); + } + + private TypedValue determineTypedValue(PrismContainerValue rootContainerValue) { + Item> value = rootContainerValue.findItem(relativePath); + ItemDefinition def = determineItemDefinition(rootContainerValue.getDefinition(), relativePath); + if (def == null) { + throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootContainerValue+", value: "+value); + } + return new TypedValue<>(value, def); + } + + private TypedValue determineTypedValue(ItemDeltaItem rootIdi) throws SchemaException { + ItemDeltaItem> value = rootIdi.findIdi(relativePath); + ItemDefinition def = determineItemDefinition((PrismContainerDefinition)rootIdi.getDefinition(), relativePath); + if (def == null) { + throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootIdi+", value: "+value); + } + return new TypedValue<>(value, def); + } + + private TypedValue determineTypedValueOdo(String name, TypedValue root) + throws SchemaException { + //noinspection unchecked + ObjectDeltaObject rootOdo = (ObjectDeltaObject) root.getValue(); + DefinitionResolver, ItemDefinition> resolver = (rootDef, path) -> { + // We are called just before failure. Therefore all normal ways of resolving of definition did not work. + ItemDefinition parentDef = rootDef.findItemDefinition(path.allExceptLast()); + if (parentDef != null && parentDef.isDynamic()) { + // This is the case of dynamic schema extensions, such as assignment extension. + // Those may not have a definition. In that case just assume strings. + // In fact, this is a HACK. All such schemas should have a definition. + // Otherwise there may be problems with parameter types for caching compiles scripts and so on. + return prismContext.definitionFactory().createPropertyDefinition(path.firstName(), PrimitiveType.STRING.getQname()); + } + return null; + }; + ItemDeltaItem> subValue = rootOdo.findIdi(relativePath, resolver); + PrismObjectDefinition rootDefinition; + if (root.getDefinition() == null) { + rootDefinition = rootOdo.getDefinition(); + if (rootDefinition == null) { + throw new IllegalArgumentException("Found ODO without a definition while processing variable '"+name+"': "+rootOdo); + } + } else { + rootDefinition = root.getDefinition(); + } + ItemDefinition itemDefinition = determineItemDefinition(rootDefinition, relativePath); + if (itemDefinition == null) { + throw new IllegalArgumentException("Cannot determine definition for '"+relativePath+"' from "+rootOdo+", value: "+subValue); + } + return new TypedValue<>(subValue, itemDefinition); + } + + private ItemDefinition determineItemDefinition(PrismContainerDefinition containerDefinition, ItemPath relativePath) { + ItemDefinition def = containerDefinition.findItemDefinition(relativePath); + if (def != null) { + return def; + } + // This may be a wrong path. Or it may be a path to a "sub-property" of a structured property, such as PolyString/norm. + // Let's find out by looking at the parent. + ItemPath parentPath = relativePath.allExceptLast(); + ItemDefinition parentDef = containerDefinition.findItemDefinition(parentPath); + if (parentDef == null) { + return null; + } + if (parentDef instanceof PrismContainerDefinition) { + if (parentDef.isDynamic() && ((PrismContainerDefinition)parentDef).isEmpty()) { + // The case of dynamic schema for which there are no definitions + // E.g. assignment extension just default to single-value strings. Better than nothing. At least for now. + return parentDef.getPrismContext().definitionFactory().createPropertyDefinition(relativePath.lastName(), PrimitiveType.STRING.getQname()); + } + } else if (parentDef instanceof PrismPropertyDefinition) { + if (PrismUtil.isStructuredType(parentDef.getTypeName())) { + // All "sub-properties" are hardcoded as single value strings + return parentDef.getPrismContext().definitionFactory().createPropertyDefinition(relativePath.lastName(), PrimitiveType.STRING.getQname()); + } + } + return null; + } + + private TypedValue normalizeValuesToDelete(TypedValue root) { + Object rootValue = root.getValue(); + if (rootValue instanceof ObjectDeltaObject) { + return new TypedValue<>(((ObjectDeltaObject) rootValue).normalizeValuesToDelete(true), + (ItemDefinition) root.getDefinition()); + } else if (rootValue instanceof ItemDeltaItem) { + // TODO normalize as well + return root; + } else { + return root; + } + } +} diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditCleanupPerformanceTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditCleanupPerformanceTest.java index 5ae3e41cca5..3fe9df71d63 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditCleanupPerformanceTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditCleanupPerformanceTest.java @@ -10,11 +10,11 @@ import com.evolveum.midpoint.audit.api.AuditEventRecord; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.repo.sql.data.audit.RAuditEventRecord; -import com.evolveum.midpoint.repo.sql.util.SimpleTaskAdapter; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType; @@ -85,7 +85,7 @@ private void prepareAuditEventRecords() throws Exception { record.setTimestamp(System.currentTimeMillis()); record.addPropertyValue("prop1", "val1"); record.addReferenceValue("ref1", ObjectTypeUtil.createObjectRef("oid1", ObjectTypes.USER).asReferenceValue()); - auditService.audit(record, new SimpleTaskAdapter()); + auditService.audit(record, new NullTaskImpl()); i++; if (i%1000 == 0 || i == RECORDS) { long duration = System.currentTimeMillis() - start; diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditTest.java index 9f84825e747..b6549ac315b 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AuditTest.java @@ -13,8 +13,8 @@ import com.evolveum.midpoint.audit.api.AuditReferenceValue; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.repo.sql.data.audit.RAuditEventRecord; -import com.evolveum.midpoint.repo.sql.util.SimpleTaskAdapter; import com.evolveum.midpoint.schema.ObjectDeltaOperation; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; @@ -57,7 +57,7 @@ public void test100AuditSimple() throws Exception { record.addReferenceValue("ref2", refVal2); record.addReferenceValue("ref3", refVal3); LOGGER.info("Adding audit record {}", record); - auditService.audit(record, new SimpleTaskAdapter()); + auditService.audit(record, new NullTaskImpl()); // THEN System.out.println("Record written:\n" + record.debugDump()); @@ -88,7 +88,7 @@ public void test110AuditSecond() throws Exception { AuditEventRecord record = new AuditEventRecord(); record.addPropertyValue("prop", "val"); LOGGER.info("Adding audit record {}", record); - auditService.audit(record, new SimpleTaskAdapter()); + auditService.audit(record, new NullTaskImpl()); // THEN System.out.println("Record written:\n" + record.debugDump()); @@ -119,7 +119,7 @@ public void testAudit() { "124")); record.getDeltas().add(delta); - auditService.audit(record, new SimpleTaskAdapter()); + auditService.audit(record, new NullTaskImpl()); } private AuditEventRecord getAuditEventRecord(int expectedCount, int index) { diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CleanupTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CleanupTest.java index 32b14f95714..935b246db41 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CleanupTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CleanupTest.java @@ -10,11 +10,11 @@ import com.evolveum.midpoint.audit.api.AuditEventRecord; import com.evolveum.midpoint.prism.delta.DeltaFactory; import com.evolveum.midpoint.repo.sql.data.audit.RAuditEventRecord; -import com.evolveum.midpoint.repo.sql.util.SimpleTaskAdapter; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.test.NullTaskImpl; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType; @@ -181,7 +181,7 @@ private void prepareAuditEventRecords() throws Exception { record.addReferenceValue("ref1", ObjectTypeUtil.createObjectRef("oid1", ObjectTypes.USER).asReferenceValue()); LOGGER.info("Adding audit record with timestamp {}", new Object[]{new Date(timestamp)}); - auditService.audit(record, new SimpleTaskAdapter()); + auditService.audit(record, new NullTaskImpl()); calendar.add(Calendar.HOUR_OF_DAY, 1); } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/UserAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/UserAsserter.java index 624fb204e29..9e93ab9f5d1 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/UserAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/UserAsserter.java @@ -7,19 +7,17 @@ package com.evolveum.midpoint.test.asserter; import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; -import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.test.IntegrationTestTools; import com.evolveum.midpoint.test.asserter.prism.PolyStringAsserter; -import com.evolveum.midpoint.test.asserter.prism.PrismObjectAsserter; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; @@ -261,7 +259,14 @@ public UserAsserter assertEmployeeNumber() { } public UserAsserter assertJpegPhoto() { - assertNotNull("Missing jpegPhoto in "+desc(), getObject().asObjectable().getJpegPhoto()); + PrismProperty photoProperty = getObject().findProperty(UserType.F_JPEG_PHOTO); + assertTrue("Missing jpegPhoto in "+desc(), photoProperty != null && + (photoProperty.isIncomplete() || photoProperty.size() == 1 && photoProperty.getRealValue() != null)); + return this; + } + + public UserAsserter assertJpegPhoto(byte[] expected) { + assertEquals("Wrong jpegPhoto in "+desc(), expected, getObject().asObjectable().getJpegPhoto()); return this; } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java b/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java similarity index 69% rename from repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java rename to repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java index 60799534532..1bd16c27017 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java +++ b/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2010-2015 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.repo.sql.util; +package com.evolveum.midpoint.task.api.test; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ChangeType; @@ -20,123 +20,132 @@ import org.jetbrains.annotations.NotNull; import javax.xml.namespace.QName; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; -import static java.util.Collections.*; +import static java.util.Collections.emptyMap; +import static java.util.Collections.emptySet; /** + * DO NOT USE in production code. This is only for testing purposes: provides a no-op implementation of Task interface + * to be used when task-quartz-impl is not available. + * + * TODO move to src/main/test tree. + * * @author lazyman */ -public class SimpleTaskAdapter implements Task { +public class NullTaskImpl implements Task { @Override public void addDependent(String taskIdentifier) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isAsynchronous() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public TaskExecutionStatus getExecutionStatus() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeWaiting() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeRunnable() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setInitialExecutionStatus(TaskExecutionStatus value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public TaskPersistenceStatus getPersistenceStatus() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isTransient() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isPersistent() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public TaskRecurrence getRecurrenceStatus() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isSingle() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isRecurring() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public ScheduleType getSchedule() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public TaskBinding getBinding() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isTightlyBound() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isLooselyBound() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setBinding(TaskBinding value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setBindingImmediate(TaskBinding value, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String getHandlerUri() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setHandlerUri(String value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setHandlerUriImmediate(String value, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public UriStack getOtherHandlersUriStack() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -151,7 +160,7 @@ public PrismObject getOwner() { @Override public void setOwner(PrismObject owner) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -161,12 +170,12 @@ public String getChannel() { @Override public void setChannel(String channelUri) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setChannelImmediate(String channelUri, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -193,67 +202,67 @@ public String getOid() { @Override public PrismObject getObject(Class type, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public ObjectReferenceType getObjectRefOrClone() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setObjectRef(ObjectReferenceType objectRef) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setObjectRef(String oid, QName type) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setObjectTransient(PrismObject object) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String getObjectOid() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public OperationResult getResult() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setResultTransient(OperationResult result) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setResult(OperationResult result) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setResultImmediate(OperationResult result, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Long getLastRunStartTimestamp() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Long getLastRunFinishTimestamp() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Long getNextRunStartTime(OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -263,87 +272,87 @@ public PolyStringType getName() { @Override public void setName(PolyStringType value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setName(String value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setNameImmediate(PolyStringType value, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Item getExtensionItemOrClone(ItemName propertyName) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionContainer(PrismContainer item) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionReference(PrismReference reference) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionProperty(PrismProperty property) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionPropertyImmediate(PrismProperty property, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void addExtensionProperty(PrismProperty property) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionPropertyValue(QName propertyName, T value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionPropertyValueTransient(QName propertyName, T value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionContainerValue(QName containerName, T value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setExtensionItem(Item item) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void modifyExtension(ItemDelta itemDelta) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public long getProgress() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setProgress(Long value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setProgressImmediate(Long progress, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -353,64 +362,64 @@ public void setProgressTransient(Long value) { @NotNull @Override public PrismObject getUpdatedOrClonedTaskObject() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @NotNull @Override public PrismObject getUpdatedTaskObject() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @NotNull @Override public PrismObject getClonedTaskObject() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void refresh(OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String debugDump() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String debugDump(int indent) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void flushPendingModifications(OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String getCategory() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeRecurringSimple(int interval) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeRecurringCron(String cronLikeSpecification) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeSingle() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String getNode() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -420,22 +429,22 @@ public String getNodeAsObserved() { @Override public OperationResultStatusType getResultStatus() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public ThreadStopActionType getThreadStopAction() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isResilient() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setCategory(String category) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override @@ -481,159 +490,159 @@ public PrismReference getExtensionReferenceOrClone(ItemName name) { @Override public void setDescriptionImmediate(String value, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setDescription(String value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String getDescription() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void deleteExtensionProperty(PrismProperty property) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setThreadStopAction(ThreadStopActionType value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeRecurring(ScheduleType schedule) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeSingle(ScheduleType schedule) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Task createSubtask() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public String getParent() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void pushHandlerUri(String uri, ScheduleType schedule, TaskBinding binding) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void pushHandlerUri(String uri, ScheduleType schedule, TaskBinding binding, Collection> extensionDeltas) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void pushHandlerUri(String uri, ScheduleType schedule, TaskBinding binding, ItemDelta delta) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void finishHandler(OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @NotNull @Override public List listSubtasks(boolean persistentOnly, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public List listPrerequisiteTasks(OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void startWaitingForTasksImmediate(OperationResult result) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public List getDependents() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void deleteDependent(String value) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public List listDependents(OperationResult result) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Task getParentTask(OperationResult result) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public TaskWaitingReason getWaitingReason() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public boolean isClosed() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeWaiting(TaskWaitingReason reason) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void makeWaiting(TaskWaitingReason reason, TaskUnpauseActionType unpauseAction) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void pushWaitForTasksHandlerUri() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Long getCompletionTimestamp() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void setObjectRefImmediate(ObjectReferenceType value, OperationResult parentResult) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public void addExtensionReference(PrismReference reference) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public List listSubtasksDeeply(boolean persistentOnly, OperationResult result) { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public Collection> getPendingModifications() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } @Override public PolicyRuleType getPolicyRule() { - throw new UnsupportedOperationException("not implemented yet."); + throw new UnsupportedOperationException(); } diff --git a/testing/story/src/test/resources/photo/archetype-id-card.xml b/testing/story/src/test/resources/photo/archetype-id-card.xml index c5f094802ae..8f3b7a8384b 100644 --- a/testing/story/src/test/resources/photo/archetype-id-card.xml +++ b/testing/story/src/test/resources/photo/archetype-id-card.xml @@ -5,7 +5,7 @@ ~ and European Union Public License. See LICENSE file for details. --> - + @@ -40,7 +40,7 @@ weak - $immediateRole/extension/photo + $immediateRole/jpegPhoto @@ -53,20 +53,4 @@ 2 UserType - - - - - - jpegPhoto to extension/photo - strong - - jpegPhoto - - - extension/photo - - - -