Skip to content

Commit

Permalink
Fix associationTargetSearch queries
Browse files Browse the repository at this point in the history
These queries filtered on objectClass, while the correct behavior is
to filter on kind/intent. (As we are looking for specific type, as
provided in association definition.)

Also removed long-obsolete DefaultSearchExpressionEvaluatorCache.

Related to e9934aa.
  • Loading branch information
mederly committed May 27, 2022
1 parent d2ba99b commit 473467d
Show file tree
Hide file tree
Showing 7 changed files with 297 additions and 194 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
* @author Radovan Semancik
*/
public class AssignmentTargetSearchExpressionEvaluator
extends AbstractSearchExpressionEvaluator<PrismContainerValue<AssignmentType>,
PrismContainerDefinition<AssignmentType>,
AssignmentTargetSearchExpressionEvaluatorType> {
extends AbstractSearchExpressionEvaluator<
PrismContainerValue<AssignmentType>,
AssignmentHolderType,
PrismContainerDefinition<AssignmentType>,
AssignmentTargetSearchExpressionEvaluatorType> {

AssignmentTargetSearchExpressionEvaluator(QName elementName,
AssignmentTargetSearchExpressionEvaluatorType expressionEvaluatorType,
Expand All @@ -49,11 +51,13 @@ public class AssignmentTargetSearchExpressionEvaluator
modelService, securityContextManager, localizationService, cacheConfigurationManager);
}

protected PrismContainerValue<AssignmentType> createPrismValue(String oid, QName targetTypeQName,
protected PrismContainerValue<AssignmentType> createPrismValue(
String oid,
QName targetTypeQName,
List<ItemDelta<PrismContainerValue<AssignmentType>, PrismContainerDefinition<AssignmentType>>> additionalAttributeDeltas,
ExpressionEvaluationContext context) {

AssignmentType assignment = new AssignmentType(prismContext)
AssignmentType assignment = new AssignmentType()
.targetRef(oid, targetTypeQName, getRelation());
assignment.getSubtype().addAll(getSubtypes());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,41 +34,55 @@
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.expression.TypedValue;
import com.evolveum.midpoint.schema.internals.InternalsConfig;
import com.evolveum.midpoint.schema.util.ObjectQueryUtil;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.security.api.SecurityContextManager;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SearchObjectExpressionEvaluatorType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;

import org.jetbrains.annotations.NotNull;

import static com.evolveum.midpoint.util.MiscUtil.argCheck;

/**
* Creates an association (or associations) based on specified condition for the associated object.
*
* @author Radovan Semancik
*/
public class AssociationTargetSearchExpressionEvaluator
extends AbstractSearchExpressionEvaluator<PrismContainerValue<ShadowAssociationType>,
PrismContainerDefinition<ShadowAssociationType>,
SearchObjectExpressionEvaluatorType> {

AssociationTargetSearchExpressionEvaluator(QName elementName, SearchObjectExpressionEvaluatorType expressionEvaluatorType,
PrismContainerDefinition<ShadowAssociationType> outputDefinition, Protector protector, PrismContext prismContext, ObjectResolver objectResolver,
ModelService modelService, SecurityContextManager securityContextManager,
LocalizationService localizationService, CacheConfigurationManager cacheConfigurationManager) {
super(elementName, expressionEvaluatorType, outputDefinition, protector, prismContext, objectResolver, modelService, securityContextManager, localizationService,
extends AbstractSearchExpressionEvaluator<
PrismContainerValue<ShadowAssociationType>,
ShadowType,
PrismContainerDefinition<ShadowAssociationType>,
SearchObjectExpressionEvaluatorType> {

AssociationTargetSearchExpressionEvaluator(
QName elementName,
SearchObjectExpressionEvaluatorType expressionEvaluatorBean,
PrismContainerDefinition<ShadowAssociationType> outputDefinition,
Protector protector,
PrismContext prismContext,
ObjectResolver objectResolver,
ModelService modelService,
SecurityContextManager securityContextManager,
LocalizationService localizationService,
CacheConfigurationManager cacheConfigurationManager) {
super(
elementName,
expressionEvaluatorBean,
outputDefinition,
protector,
prismContext,
objectResolver,
modelService,
securityContextManager,
localizationService,
cacheConfigurationManager);
}

@Override
protected AbstractSearchExpressionEvaluatorCache getCache() {
protected AbstractSearchExpressionEvaluatorCache<PrismContainerValue<ShadowAssociationType>, ShadowType, ?, ?> getCache() {
return AssociationSearchExpressionEvaluatorCache.getCache();
}

Expand All @@ -83,7 +97,7 @@ protected CacheType getCacheType() {
}

@Override
protected ObjectQuery extendQuery(ObjectQuery query, ExpressionEvaluationContext params) throws SchemaException, ExpressionEvaluationException {
protected ObjectQuery extendQuery(ObjectQuery query, ExpressionEvaluationContext params) throws ExpressionEvaluationException {
@SuppressWarnings("unchecked")
TypedValue<ResourceObjectTypeDefinition> rAssocTargetDefTypedValue =
params.getVariables().get(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION);
Expand All @@ -92,32 +106,41 @@ protected ObjectQuery extendQuery(ObjectQuery query, ExpressionEvaluationContext
params.getContextDescription()+"; the expression may be used in a wrong place. It is only supposed to create an association.");
}
ResourceObjectTypeDefinition rAssocTargetDef = (ResourceObjectTypeDefinition) rAssocTargetDefTypedValue.getValue();
ObjectFilter resourceFilter = ObjectQueryUtil.createResourceFilter(rAssocTargetDef.getResourceOid());
ObjectFilter objectClassFilter = ObjectQueryUtil.createObjectClassFilter(
rAssocTargetDef.getObjectClassName(), prismContext);
ObjectFilter extendedFilter = prismContext.queryFactory().createAnd(resourceFilter, objectClassFilter, query.getFilter());
query.setFilter(extendedFilter);
ObjectFilter coordinatesFilter = prismContext.queryFor(ShadowType.class)
.item(ShadowType.F_RESOURCE_REF).ref(rAssocTargetDef.getResourceOid())
.and().item(ShadowType.F_KIND).eq(rAssocTargetDef.getKind())
.and().item(ShadowType.F_INTENT).eq(rAssocTargetDef.getIntent())
.buildFilter();
query.setFilter(
prismContext.queryFactory()
.createAnd(coordinatesFilter, query.getFilter()));
return query;
}

@Override
protected void extendOptions(Collection<SelectorOptions<GetOperationOptions>> options,
protected void extendOptions(
Collection<SelectorOptions<GetOperationOptions>> options,
boolean searchOnResource) {
super.extendOptions(options, searchOnResource);
// We do not need to worry about associations of associations here
// (nested associations). Avoiding that will make the query faster.
options.add(SelectorOptions.create(prismContext.toUniformPath(ShadowType.F_ASSOCIATION), GetOperationOptions.createDontRetrieve()));
options.add(
SelectorOptions.create(
prismContext.toUniformPath(ShadowType.F_ASSOCIATION),
GetOperationOptions.createDontRetrieve()));
}

@Override
protected <O extends ObjectType> boolean isAcceptable(@NotNull PrismObject<O> object) {
O objectable = object.asObjectable();
argCheck(objectable instanceof ShadowType, "Not a shadow: %s", objectable);
return ShadowUtil.isNotDead((ShadowType) objectable);
protected boolean isAcceptable(@NotNull PrismObject<ShadowType> object) {
return ShadowUtil.isNotDead(object.asObjectable());
}

protected PrismContainerValue<ShadowAssociationType> createPrismValue(String oid, QName targetTypeQName, List<ItemDelta<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> additionalAttributeDeltas, ExpressionEvaluationContext params) {
ShadowAssociationType association = new ShadowAssociationType(prismContext)
protected PrismContainerValue<ShadowAssociationType> createPrismValue(
String oid,
QName targetTypeQName,
List<ItemDelta<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> additionalAttributeDeltas,
ExpressionEvaluationContext params) {
ShadowAssociationType association = new ShadowAssociationType()
.name(params.getMappingQName())
.shadowRef(oid, targetTypeQName);

Expand All @@ -132,7 +155,8 @@ protected PrismContainerValue<ShadowAssociationType> createPrismValue(String oid

prismContext.adopt(associationCVal, ShadowType.COMPLEX_TYPE, ShadowType.F_ASSOCIATION);
if (InternalsConfig.consistencyChecks) {
associationCVal.assertDefinitions(() -> "associationCVal in assignment expression in "+params.getContextDescription());
associationCVal.assertDefinitions(
() -> "associationCVal in assignment expression in " + params.getContextDescription());
}
} catch (SchemaException e) {
// Should not happen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext;
import com.evolveum.midpoint.schema.cache.CacheConfigurationManager;
import com.evolveum.midpoint.security.api.SecurityContextManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ReferenceSearchExpressionEvaluatorType;

/**
Expand All @@ -30,15 +31,41 @@
* @author Radovan Semancik
*/
public class ReferenceSearchExpressionEvaluator
extends AbstractSearchExpressionEvaluator<PrismReferenceValue,PrismReferenceDefinition,ReferenceSearchExpressionEvaluatorType> {
extends AbstractSearchExpressionEvaluator<
PrismReferenceValue,
ObjectType,
PrismReferenceDefinition,
ReferenceSearchExpressionEvaluatorType> {

ReferenceSearchExpressionEvaluator(QName elementName, ReferenceSearchExpressionEvaluatorType expressionEvaluatorType,
PrismReferenceDefinition outputDefinition, Protector protector, PrismContext prismContext,
ObjectResolver objectResolver, ModelService modelService, SecurityContextManager securityContextManager, LocalizationService localizationService, CacheConfigurationManager cacheConfigurationManager) {
super(elementName, expressionEvaluatorType, outputDefinition, protector, prismContext, objectResolver, modelService, securityContextManager, localizationService, cacheConfigurationManager);
ReferenceSearchExpressionEvaluator(
QName elementName,
ReferenceSearchExpressionEvaluatorType expressionEvaluatorType,
PrismReferenceDefinition outputDefinition,
Protector protector,
PrismContext prismContext,
ObjectResolver objectResolver,
ModelService modelService,
SecurityContextManager securityContextManager,
LocalizationService localizationService,
CacheConfigurationManager cacheConfigurationManager) {
super(
elementName,
expressionEvaluatorType,
outputDefinition,
protector,
prismContext,
objectResolver,
modelService,
securityContextManager,
localizationService,
cacheConfigurationManager);
}

protected PrismReferenceValue createPrismValue(String oid, QName targetTypeQName, List<ItemDelta<PrismReferenceValue, PrismReferenceDefinition>> additionalAttributeValues, ExpressionEvaluationContext params) {
protected PrismReferenceValue createPrismValue(
String oid,
QName targetTypeQName,
List<ItemDelta<PrismReferenceValue, PrismReferenceDefinition>> additionalAttributeValues,
ExpressionEvaluationContext params) {
PrismReferenceValue refVal = prismContext.itemFactory().createReferenceValue();

refVal.setOid(oid);
Expand All @@ -52,5 +79,4 @@ protected PrismReferenceValue createPrismValue(String oid, QName targetTypeQName
public String shortDebugDump() {
return "referenceSearchExpression";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@
* - should we store anything in addition to the resulting list of values? E.g. shadow kind in case of associationTargetSearch that is used for invalidation?
*
* V - type of cached result items
* RV - type of raw values that we are searching for
* O - type of raw values that we are searching for
* QK, QR - customized query keys / values
*
* After refactoring, this class contains almost nothing ;) Consider removing it altogether.
*/
public abstract class AbstractSearchExpressionEvaluatorCache<V extends PrismValue, RV extends PrismObject, QK extends QueryKey, QR extends QueryResult> extends
public abstract class AbstractSearchExpressionEvaluatorCache<
V extends PrismValue,
O extends ObjectType,
QK extends QueryKey,
QR extends QueryResult<V>> extends
AbstractThreadLocalCache {

private static final Trace LOGGER = TraceManager.getTrace(AbstractSearchExpressionEvaluatorCache.class);
Expand All @@ -57,9 +61,14 @@ public void setClientContextInformation(Object clientContextInformation) {
// Also probably because of MID-5355, although it's a bit unclear.
Map<QK, QR> queries = new ConcurrentHashMap<>();

public List<V> getQueryResult(Class<? extends ObjectType> type, ObjectQuery query, ObjectSearchStrategyType searchStrategy, ExpressionEvaluationContext params, PrismContext prismContext) {
public List<V> getQueryResult(
Class<O> type,
ObjectQuery query,
ObjectSearchStrategyType searchStrategy,
ExpressionEvaluationContext params,
PrismContext prismContext) {
QK queryKey = createQueryKey(type, query, searchStrategy, params, prismContext);
if (queryKey != null) { // TODO BRUTAL HACK
if (queryKey != null) { // TODO BRUTAL HACK
QR result = queries.get(queryKey);
if (result != null) {
return result.getResultingList();
Expand All @@ -68,20 +77,29 @@ public List<V> getQueryResult(Class<? extends ObjectType> type, ObjectQuery quer
return null;
}

public <T extends ObjectType> void putQueryResult(Class<T> type, ObjectQuery query, ObjectSearchStrategyType searchStrategy,
ExpressionEvaluationContext params, List<V> resultList, List<RV> rawResultList,
PrismContext prismContext) {
public void putQueryResult(
Class<O> type,
ObjectQuery query,
ObjectSearchStrategyType searchStrategy,
ExpressionEvaluationContext params,
List<V> resultList,
List<PrismObject<O>> rawResultList,
PrismContext prismContext) {
QK queryKey = createQueryKey(type, query, searchStrategy, params, prismContext);
if (queryKey != null) { // TODO BRUTAL HACK
if (queryKey != null) { // TODO BRUTAL HACK
QR queryResult = createQueryResult(resultList, rawResultList);
queries.put(queryKey, queryResult);
}
}

abstract protected QK createQueryKey(Class<? extends ObjectType> type, ObjectQuery query, ObjectSearchStrategyType searchStrategy,
ExpressionEvaluationContext params, PrismContext prismContext);
abstract protected QK createQueryKey(
Class<O> type,
ObjectQuery query,
ObjectSearchStrategyType searchStrategy,
ExpressionEvaluationContext params,
PrismContext prismContext);

protected abstract QR createQueryResult(List<V> resultList, List<RV> rawResultList);
protected abstract QR createQueryResult(List<V> resultList, List<PrismObject<O>> rawResultList);

@Override
public String description() {
Expand Down

0 comments on commit 473467d

Please sign in to comment.