Skip to content

Commit

Permalink
Merge branch 'support-3.5' of https://github.com/Evolveum/midpoint in…
Browse files Browse the repository at this point in the history
…to support-3.5
  • Loading branch information
KaterynaHonchar committed Jan 19, 2017
2 parents 6f1b572 + f2b6786 commit 2cdc2aa
Show file tree
Hide file tree
Showing 14 changed files with 808 additions and 33 deletions.
Expand Up @@ -1142,6 +1142,13 @@ public static void applyTo(Collection<? extends ItemDelta> deltas, PrismContaine
}
}

public static void applyTo(Collection<? extends ItemDelta> deltas, PrismContainerValue propertyContainerValue)
throws SchemaException {
for (ItemDelta delta : deltas) {
delta.applyTo(propertyContainerValue);
}
}

public static void applyToMatchingPath(Collection<? extends ItemDelta> deltas, PrismContainer propertyContainer)
throws SchemaException {
for (ItemDelta delta : deltas) {
Expand Down
Expand Up @@ -6552,13 +6552,21 @@
</xsd:element>
<xsd:element name="createOnDemand" type="xsd:boolean" minOccurs="0" maxOccurs="1" default="false">
</xsd:element>
<xsd:element name="populateObject" type="tns:PopulateObjectType" minOccurs="0">
<xsd:element name="populateObject" type="tns:PopulateType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="populate" type="tns:PopulateType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Populate assignment, association,... (any container) specific attributes, e.g activation status, validTo, validFrom
and can be also used for setting assignmnet parameters
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
Expand Down Expand Up @@ -6617,6 +6625,8 @@
<xsd:sequence>
<xsd:element name="relation" type="xsd:QName" minOccurs="0" maxOccurs="1">
</xsd:element>
<xsd:element name="activation" type="tns:ActivationType" minOccurs="0" maxOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
Expand Down Expand Up @@ -6664,7 +6674,7 @@
</xsd:complexType>
<xsd:element name="associationFromLink" type="tns:AssociationFromLinkExpressionEvaluatorType" substitutionGroup="tns:expressionEvaluator"/>

<xsd:complexType name="PopulateObjectType">
<xsd:complexType name="PopulateType">
<xsd:annotation>
<xsd:documentation>TODO</xsd:documentation>
</xsd:annotation>
Expand Down
Expand Up @@ -350,7 +350,7 @@ private static PrismObject<?> resolveReference(ObjectReferenceType ref, ObjectRe
}

public static <ID extends ItemDefinition> ID resolveDefinitionPath(ItemPath path,
ExpressionVariables variables, PrismObjectDefinition<?> defaultContext, String shortDesc)
ExpressionVariables variables, PrismContainerDefinition<?> defaultContext, String shortDesc)
throws SchemaException {
while (path != null && !path.isEmpty() && !(path.first() instanceof NameItemPathSegment)) {
path = path.rest();
Expand Down
Expand Up @@ -21,13 +21,6 @@

import javax.xml.namespace.QName;

import com.evolveum.midpoint.model.common.expression.evaluator.caching.AbstractSearchExpressionEvaluatorCache;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.security.api.SecurityEnforcer;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectSearchStrategyType;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;

import org.apache.commons.lang.BooleanUtils;

import com.evolveum.midpoint.model.api.ModelService;
Expand All @@ -36,7 +29,13 @@
import com.evolveum.midpoint.model.common.expression.ExpressionFactory;
import com.evolveum.midpoint.model.common.expression.ExpressionUtil;
import com.evolveum.midpoint.model.common.expression.ExpressionVariables;
import com.evolveum.midpoint.model.common.expression.evaluator.caching.AbstractSearchExpressionEvaluatorCache;
import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.Definition;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerDefinition;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
Expand All @@ -50,14 +49,17 @@
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.QueryJaxbConvertor;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
import com.evolveum.midpoint.schema.util.ObjectResolver;
import com.evolveum.midpoint.security.api.SecurityEnforcer;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
Expand All @@ -69,13 +71,16 @@
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingTargetDeclarationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectSearchStrategyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PopulateItemType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PopulateObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PopulateType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SearchObjectExpressionEvaluatorType;
import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;

/**
* @author Radovan Semancik
Expand Down Expand Up @@ -149,9 +154,15 @@ protected List<V> transformSingleValue(ExpressionVariables variables, PlusMinusZ
List<V> resultValues = null;
ObjectQuery query = null;

List<ItemDelta<V, D>> additionalAttributeDeltas = null;
PopulateType populateAssignmentType = getExpressionEvaluatorType().getPopulate();
if (populateAssignmentType != null) {
additionalAttributeDeltas = collectAdditionalAttributes(populateAssignmentType, outputDefinition, variables, params, contextDescription, task, result);
}

if (getExpressionEvaluatorType().getOid() != null) {
resultValues = new ArrayList<>(1);
resultValues.add(createPrismValue(getExpressionEvaluatorType().getOid(), targetTypeQName, params));
resultValues.add(createPrismValue(getExpressionEvaluatorType().getOid(), targetTypeQName, additionalAttributeDeltas, params));
} else {

SearchFilterType filterType = getExpressionEvaluatorType().getFilter();
Expand All @@ -173,13 +184,13 @@ protected List<V> transformSingleValue(ExpressionVariables variables, PlusMinusZ
LOGGER.trace("Query after extension: {}", query.debugDump());
}

resultValues = executeSearchUsingCache(targetTypeClass, targetTypeQName, query, params, contextDescription, task, params.getResult());
resultValues = executeSearchUsingCache(targetTypeClass, targetTypeQName, query, additionalAttributeDeltas, params, contextDescription, task, params.getResult());
}

if (resultValues.isEmpty() && getExpressionEvaluatorType().isCreateOnDemand() == Boolean.TRUE &&
(valueDestination == PlusMinusZero.PLUS || valueDestination == PlusMinusZero.ZERO || useNew)) {
String createdObjectOid = createOnDemand(targetTypeClass, variables, params, params.getContextDescription(), task, params.getResult());
resultValues.add(createPrismValue(createdObjectOid, targetTypeQName, params));
resultValues.add(createPrismValue(createdObjectOid, targetTypeQName, additionalAttributeDeltas, params));
}

LOGGER.trace("Search expression got {} results for query {}", resultValues==null?"null":resultValues.size(), query);
Expand All @@ -200,14 +211,14 @@ protected AbstractSearchExpressionEvaluatorCache getCache() {
return null;
}

private <O extends ObjectType> List<V> executeSearchUsingCache(Class<O> targetTypeClass, final QName targetTypeQName, ObjectQuery query,
private <O extends ObjectType> List<V> executeSearchUsingCache(Class<O> targetTypeClass, final QName targetTypeQName, ObjectQuery query, List<ItemDelta<V, D>> additionalAttributeDeltas,
final ExpressionEvaluationContext params, String contextDescription, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {

ObjectSearchStrategyType searchStrategy = getSearchStrategy();

AbstractSearchExpressionEvaluatorCache cache = getCache();
if (cache == null) {
return executeSearch(null, targetTypeClass, targetTypeQName, query, searchStrategy, params, contextDescription, task, result);
return executeSearch(null, targetTypeClass, targetTypeQName, query, searchStrategy, additionalAttributeDeltas, params, contextDescription, task, result);
}

List<V> list = cache.getQueryResult(targetTypeClass, query, searchStrategy, params, prismContext);
Expand All @@ -217,7 +228,7 @@ private <O extends ObjectType> List<V> executeSearchUsingCache(Class<O> targetTy
}
LOGGER.trace("Cache: MISS {} ({})", query, targetTypeClass.getSimpleName());
List<PrismObject> rawResult = new ArrayList<>();
list = executeSearch(rawResult, targetTypeClass, targetTypeQName, query, searchStrategy, params, contextDescription, task, result);
list = executeSearch(rawResult, targetTypeClass, targetTypeQName, query, searchStrategy, additionalAttributeDeltas, params, contextDescription, task, result);
if (list != null && !list.isEmpty()) {
// we don't want to cache negative results (e.g. if used with focal objects it might mean that they would be attempted to create multiple times)
cache.putQueryResult(targetTypeClass, query, searchStrategy, params, list, rawResult, prismContext);
Expand All @@ -239,6 +250,7 @@ private ObjectSearchStrategyType getSearchStrategy() {
private <O extends ObjectType> List<V> executeSearch(List<PrismObject> rawResult,
Class<O> targetTypeClass, final QName targetTypeQName, ObjectQuery query,
ObjectSearchStrategyType searchStrategy,
List<ItemDelta<V, D>> additionalAttributeDeltas,
ExpressionEvaluationContext params, String contextDescription,
Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
Expand All @@ -254,18 +266,18 @@ private <O extends ObjectType> List<V> executeSearch(List<PrismObject> rawResult

switch (searchStrategy) {
case IN_REPOSITORY:
return executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, false, false, params, contextDescription, task, result);
return executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, false, false, additionalAttributeDeltas, params, contextDescription, task, result);
case ON_RESOURCE:
return executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, true, true, params, contextDescription, task, result);
return executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, true, true, additionalAttributeDeltas, params, contextDescription, task, result);
case ON_RESOURCE_IF_NEEDED:
List<V> inRepo = executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, false, false, params, contextDescription, task, result);
List<V> inRepo = executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, false, false, additionalAttributeDeltas, params, contextDescription, task, result);
if (!inRepo.isEmpty()) {
return inRepo;
}
if (rawResult != null) {
rawResult.clear();
}
return executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, true, false, params, contextDescription, task, result);
return executeSearchAttempt(rawResult, targetTypeClass, targetTypeQName, query, true, false, additionalAttributeDeltas, params, contextDescription, task, result);
default:
throw new IllegalArgumentException("Unknown search strategy: " + searchStrategy);
}
Expand All @@ -274,6 +286,7 @@ private <O extends ObjectType> List<V> executeSearch(List<PrismObject> rawResult
private <O extends ObjectType> List<V> executeSearchAttempt(final List<PrismObject> rawResult,
Class<O> targetTypeClass, final QName targetTypeQName,
ObjectQuery query, boolean searchOnResource, boolean tryAlsoRepository,
final List<ItemDelta<V, D>> additionalAttributeDeltas,
final ExpressionEvaluationContext params, String contextDescription,
Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
Expand All @@ -292,7 +305,7 @@ public boolean handle(PrismObject<O> object, OperationResult parentResult) {
if (rawResult != null) {
rawResult.add(object);
}
list.add(createPrismValue(object.getOid(), targetTypeQName, params));
list.add(createPrismValue(object.getOid(), targetTypeQName, additionalAttributeDeltas, params));

// TODO: we should count results and stop after some reasonably high number?

Expand Down Expand Up @@ -341,8 +354,32 @@ public boolean handle(PrismObject<O> object, OperationResult parentResult) {
protected void extendOptions(Collection<SelectorOptions<GetOperationOptions>> options, boolean searchOnResource) {
// Nothing to do. To be overridden by subclasses
}

// e.g parameters, activation for assignment etc.
protected <C extends Containerable> List<ItemDelta<V,D>> collectAdditionalAttributes(PopulateType fromPopulate,
D outputDefinition, ExpressionVariables variables, ExpressionEvaluationContext params,
String contextDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException {

if (!(outputDefinition instanceof PrismContainerDefinition)) {
return null;
}

List<ItemDelta<V,D>> deltas = new ArrayList<>();

for (PopulateItemType populateItem: fromPopulate.getPopulateItem()) {

ItemDelta<V,D> itemDelta = evaluatePopulateExpression(populateItem, variables, params,
(PrismContainerDefinition<C>) outputDefinition, contextDescription, false, task, result);
if (itemDelta != null) {
deltas.add(itemDelta);
}

}

return deltas;
}

protected abstract V createPrismValue(String oid, QName targetTypeQName, ExpressionEvaluationContext params);
protected abstract V createPrismValue(String oid, QName targetTypeQName, List<ItemDelta<V, D>> additionalAttributeDeltas, ExpressionEvaluationContext params);

private <O extends ObjectType> String createOnDemand(Class<O> targetTypeClass, ExpressionVariables variables,
ExpressionEvaluationContext params, String contextDescription, Task task, OperationResult result)
Expand All @@ -353,15 +390,15 @@ private <O extends ObjectType> String createOnDemand(Class<O> targetTypeClass, E
PrismObjectDefinition<O> objectDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(targetTypeClass);
PrismObject<O> newObject = objectDefinition.instantiate();

PopulateObjectType populateObject = getExpressionEvaluatorType().getPopulateObject();
PopulateType populateObject = getExpressionEvaluatorType().getPopulateObject();

if (populateObject == null) {
LOGGER.warn("No populateObject in assignment expression in {}, "
+ "object created on demand will be empty. Subsequent operations will most likely fail", contextDescription);
} else {
for (PopulateItemType populateItem: populateObject.getPopulateItem()) {

ItemDelta<?,?> itemDelta = evaluatePopulateExpression(populateItem, variables, params,
objectDefinition, contextDescription, task, result);
objectDefinition, contextDescription, true, task, result);
if (itemDelta != null) {
itemDelta.applyTo(newObject);
}
Expand All @@ -386,9 +423,9 @@ private <O extends ObjectType> String createOnDemand(Class<O> targetTypeClass, E
return addDelta.getOid();
}

private <IV extends PrismValue, ID extends ItemDefinition, O extends ObjectType> ItemDelta<IV,ID> evaluatePopulateExpression(PopulateItemType populateItem,
ExpressionVariables variables, ExpressionEvaluationContext params, PrismObjectDefinition<O> objectDefinition,
String contextDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException {
private <IV extends PrismValue, ID extends ItemDefinition, C extends Containerable> ItemDelta<IV,ID> evaluatePopulateExpression(PopulateItemType populateItem,
ExpressionVariables variables, ExpressionEvaluationContext params, PrismContainerDefinition<C> objectDefinition,
String contextDescription, boolean evaluateMinus, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException {
ExpressionType expressionType = populateItem.getExpression();
if (expressionType == null) {
LOGGER.warn("No expression in populateObject in assignment expression in {}, "
Expand Down

0 comments on commit 2cdc2aa

Please sign in to comment.