Skip to content

Commit

Permalink
Deduplicate code in SelectorToFilterTranslator
Browse files Browse the repository at this point in the history
There was a duplication of selector-to-filter translating code between
linked objects and security enforcer since 4.2. Now, with the advent of
ValueSelector, it became easy to fix. This commit does that.
  • Loading branch information
mederly committed Jun 12, 2023
1 parent 228b6a6 commit eac6bfb
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 253 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import com.evolveum.midpoint.prism.Objectable;

import com.evolveum.midpoint.prism.query.FilterCreationUtil;
import com.evolveum.midpoint.prism.query.ObjectFilter;

import com.google.common.base.Preconditions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -71,12 +74,6 @@ private ValueSelector(
return new ValueSelector(null, null, List.of(), null);
}

/** Type name must be qualified. */
public static @NotNull ValueSelector emptyWithType(@NotNull QName typeName) {
TypeClause typeClause = TypeClause.ofQualified(typeName);
return new ValueSelector(typeClause, null, List.of(typeClause), null);
}

public static ValueSelector of(@NotNull TypeClause typeClause, @NotNull ParentClause parentClause) {
return new ValueSelector(
typeClause,
Expand Down Expand Up @@ -131,8 +128,7 @@ public static ValueSelector of(SelectorClause... clauses) {
clauses.add(FilterClause.of(qTypeName, filter));
}

if (bean instanceof SubjectedObjectSelectorType) {
SubjectedObjectSelectorType sBean = (SubjectedObjectSelectorType) bean;
if (bean instanceof SubjectedObjectSelectorType sBean) {

var orgRelation = sBean.getOrgRelation();
if (orgRelation != null) {
Expand Down Expand Up @@ -164,8 +160,7 @@ public static ValueSelector of(SelectorClause... clauses) {
}
}

if (bean instanceof OwnedObjectSelectorType) {
OwnedObjectSelectorType oBean = (OwnedObjectSelectorType) bean;
if (bean instanceof OwnedObjectSelectorType oBean) {

var owner = oBean.getOwner();
if (owner != null) {
Expand Down Expand Up @@ -252,10 +247,6 @@ public static ValueSelector forType(@NotNull QName typeName) {
null);
}

public @Nullable TypeClause getTypeClause() {
return typeClause;
}

public @Nullable QName getTypeName() {
return typeClause != null ? typeClause.getTypeName() : null;
}
Expand All @@ -282,6 +273,16 @@ public boolean matches(@NotNull PrismValue value, @NotNull ClauseMatchingContext
return true;
}

public ObjectFilter computeFilter(@NotNull ClauseFilteringContext ctx)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException {
if (applyFilters(ctx)) {
return ctx.getFilterCollector().getFilter();
} else {
return FilterCreationUtil.createNone();
}
}

public boolean applyFilters(@NotNull ClauseFilteringContext ctx)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.Objects;
import java.util.stream.Collectors;

import com.evolveum.midpoint.model.common.LinkManager;
import com.evolveum.midpoint.prism.schema.SchemaRegistry;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.repo.common.expression.ExpressionFactory;
import com.evolveum.midpoint.repo.common.query.LinkedSelectorToFilterTranslator;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
Expand Down Expand Up @@ -59,7 +57,6 @@ public class LinkedObjectsFunctions {
@Autowired private RelationRegistry relationRegistry;
@Autowired private MidpointFunctionsImpl midpointFunctions;
@Autowired private LinkManager linkManager;
@Autowired private ExpressionFactory expressionFactory;
@Autowired
@Qualifier("cacheRepositoryService")
private RepositoryService repositoryService;
Expand Down Expand Up @@ -108,13 +105,17 @@ <T extends AssignmentHolderType> List<T> findLinkedSources(String linkType) thro
return List.of();
}
PrismReferenceValue focusReference = focusObjectReference.asReferenceValue();
LinkedSelectorToFilterTranslator translator = new LinkedSelectorToFilterTranslator(definition.getSelector(), focusReference,
"finding linked sources for " + focusContext, prismContext, expressionFactory,
currentTask, currentResult);
ObjectQuery query = prismContext.queryFactory().createQuery(translator.createFilter());
LinkedSelectorToFilterTranslator translator = new LinkedSelectorToFilterTranslator(
definition.getSelector(),
focusReference,
"finding linked sources for " + focusContext,
LOGGER,
currentTask);
ObjectQuery query = prismContext.queryFactory().createQuery(translator.createFilter(currentResult));

//noinspection unchecked
return (List<T>) midpointFunctions.searchObjects(translator.getNarrowedTargetType(), query, null);
return (List<T>) midpointFunctions.searchObjects(
translator.getNarrowedTargetType(), query, null);
}

// Should be used after assignment evaluation!
Expand Down Expand Up @@ -142,7 +143,7 @@ <T extends AssignmentHolderType> List<T> findLinkedTargets(Class<T> type, String
Set<PrismReferenceValue> membership = getMembership();
List<PrismReferenceValue> assignedWithMemberRelation = membership.stream()
.filter(ref -> relationRegistry.isMember(ref.getRelation()) && objectTypeMatches(ref, type))
.collect(Collectors.toList());
.toList();
// TODO deduplicate w.r.t. member/manager
// TODO optimize matching
List<T> objects = new ArrayList<>(assignedWithMemberRelation.size());
Expand Down Expand Up @@ -178,7 +179,7 @@ <T extends AssignmentHolderType> List<T> findLinkedTargets(String linkTypeName)
Set<PrismReferenceValue> membership = getMembership();
List<PrismReferenceValue> assignedWithMatchingRelation = membership.stream()
.filter(ref -> relationMatches(ref, definition.getSelector()) && objectTypeMatches(ref, expectedClasses))
.collect(Collectors.toList());
.toList();
// TODO deduplicate w.r.t. member/manager
// TODO optimize matching
List<T> objects = new ArrayList<>(assignedWithMatchingRelation.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,12 @@ private List<LinkedObjectSelectorType> resolveLinkTypes(List<LinkSourceObjectSel
throws SchemaException, ConfigurationException {
List<LinkedObjectSelectorType> resolvedSelectors = new ArrayList<>();
for (LinkSourceObjectSelectorType selector : selectors) {
if (selector.getLinkType() != null) {
LinkedObjectSelectorType resolvedSelector = resolveSourceSelector(selector.getLinkType());
LinkSourceObjectSelectorType mergedSelector = mergeSelectors(selector, resolvedSelector);
resolvedSelectors.add(mergedSelector);
String linkType = selector.getLinkType();
if (linkType != null) {
resolvedSelectors.add(
mergeSelectors(
selector,
resolveSourceSelector(linkType)));
} else {
resolvedSelectors.add(selector);
}
Expand Down Expand Up @@ -155,29 +157,32 @@ private ObjectQuery createQuery() throws CommunicationException, ObjectNotFoundE
queryFactory.createOrOptimized(convertedSelectors));
}

private ObjectFilter createFilter(LinkedObjectSelectorType sourceSelector) throws CommunicationException,
private ObjectFilter createFilter(@NotNull LinkedObjectSelectorType sourceSelector) throws CommunicationException,
ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException,
ExpressionEvaluationException {
SelectorToFilterTranslator translator = new SelectorToFilterTranslator(sourceSelector, AssignmentHolderType.class,
"link source selector in rule script executor", beans.prismContext, beans.expressionFactory,
actx.task, result);
ObjectFilter selectorFilter = translator.createFilter();
SelectorToFilterTranslator translator =
new SelectorToFilterTranslator(
sourceSelector, AssignmentHolderType.class,
"link source selector in rule script executor", LOGGER, actx.task);
Class<? extends ObjectType> narrowedSourceType = translator.getNarrowedTargetType();
ObjectFilter allSourcesFilter = beans.prismContext.queryFor(narrowedSourceType)
.item(AssignmentHolderType.F_ROLE_MEMBERSHIP_REF).ref(createExpectedReferenceValues(sourceSelector))
.buildFilter();

narrowedSourceTypes.add(narrowedSourceType);
return ObjectQueryUtil.simplify(queryFactory.createAnd(allSourcesFilter, selectorFilter));
return ObjectQueryUtil.simplify(
queryFactory.createAndOptimized(
translator.createFilter(result),
beans.prismContext.queryFor(narrowedSourceType)
.item(AssignmentHolderType.F_ROLE_MEMBERSHIP_REF)
.ref(createExpectedReferenceValues(sourceSelector))
.buildFilter()));
}

@NotNull
private List<PrismReferenceValue> createExpectedReferenceValues(LinkedObjectSelectorType sourceSelector) {
List<PrismReferenceValue> values = new ArrayList<>(sourceSelector.getRelation().size());
if (sourceSelector.getRelation().isEmpty()) {
List<QName> relations = sourceSelector.getRelation();
List<PrismReferenceValue> values = new ArrayList<>(relations.size());
if (relations.isEmpty()) {
values.add(new ObjectReferenceType().oid(focusOid).asReferenceValue());
} else {
for (QName relation : sourceSelector.getRelation()) {
for (QName relation : relations) {
values.add(new ObjectReferenceType().oid(focusOid).relation(relation).asReferenceValue());
}
}
Expand All @@ -196,7 +201,7 @@ private List<PrismReferenceValue> searchForSourceReferences(CompleteQuery<?> com
List<PrismReferenceValue> references = new ArrayList<>();
beans.repositoryService.searchObjectsIterative(completeQuery.getType(), completeQuery.getQuery(),
(object, parentResult) ->
references.add(ObjectTypeUtil.createObjectRef(object, beans.prismContext).asReferenceValue()),
references.add(ObjectTypeUtil.createObjectRef(object).asReferenceValue()),
completeQuery.getOptions(), false, result);
return references;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ private LinkTargetObjectSelectorType resolveLinkType(LinkTargetObjectSelectorTyp
return selector;
} else {
LinkTargetObjectSelectorType mergedSelector = new LinkTargetObjectSelectorType();
PrismContainerValue<?> mergedPcv = mergedSelector.asPrismContainerValue();
LinkedObjectSelectorType linkSelector = resolveLinkTypeInternal(linkTypeName);
if (linkSelector != null) {
((PrismContainerValue<?>) mergedSelector.asPrismContainerValue()).mergeContent(linkSelector.asPrismContainerValue(), emptyList());
mergedPcv.mergeContent(linkSelector.asPrismContainerValue(), List.of());
}
((PrismContainerValue<?>) mergedSelector.asPrismContainerValue()).mergeContent(selector.asPrismContainerValue(), emptyList());
mergedPcv.mergeContent(selector.asPrismContainerValue(), List.of());
mergedSelector.setLinkType(null);
return mergedSelector;
}
Expand Down Expand Up @@ -123,8 +124,9 @@ private List<PrismObject<? extends ObjectType>> getTargetsInternal(LinkTargetObj
Set<PrismReferenceValue> links = new HashSet<>(getLinksInChangeSituation(selector));
LOGGER.trace("Links matching change situation: {}", links);

if (!selector.getRelation().isEmpty()) {
applyRelationFilter(links, selector.getRelation());
List<QName> relations = selector.getRelation();
if (!relations.isEmpty()) {
applyRelationFilter(links, relations);
LOGGER.trace("Links matching also relation(s): {}", links);
}

Expand All @@ -138,9 +140,10 @@ private List<PrismObject<? extends ObjectType>> getTargetsInternal(LinkTargetObj
LOGGER.trace("Links matching also policy constraints: {}", links);
}

if (selector.getType() != null) {
QName typeName = selector.getType();
if (typeName != null) {
// This is just to avoid resolving objects with non-matching type
applyObjectType(links, selector.getType());
applyObjectType(links, typeName);
LOGGER.trace("Links matching also object type: {}", links);
}

Expand All @@ -151,7 +154,8 @@ private List<PrismObject<? extends ObjectType>> getTargetsInternal(LinkTargetObj
return matchingObjects;
}

private List<PrismObject<? extends ObjectType>> getMatchingObjects(Collection<PrismObject<? extends ObjectType>> objects,
private List<PrismObject<? extends ObjectType>> getMatchingObjects(
Collection<PrismObject<? extends ObjectType>> objects,
ObjectSelectorType selector) {
List<PrismObject<? extends ObjectType>> matching = new ArrayList<>();
for (PrismObject<? extends ObjectType> object : objects) {
Expand All @@ -160,7 +164,8 @@ private List<PrismObject<? extends ObjectType>> getMatchingObjects(Collection<Pr
matching.add(object);
}
} catch (CommonException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't match link target {} for {} when filtering link targets", e,
LoggingUtils.logUnexpectedException(
LOGGER, "Couldn't match link target {} for {} when filtering link targets", e,
object, actx.focusContext.getObjectAny());
}
}
Expand Down Expand Up @@ -230,24 +235,15 @@ private void applyRelationFilter(Set<PrismReferenceValue> links, List<QName> rel

@NotNull
private Set<PrismReferenceValue> getLinksInChangeSituation(LinkTargetObjectSelectorType selector) {
switch (defaultIfNull(selector.getChangeSituation(), LinkChangeSituationType.ALWAYS)) {
case ALWAYS:
return SetUtils.union(getLinkedOld(), getLinkedNew());
case ADDED:
return SetUtils.difference(getLinkedNew(), getLinkedOld());
case REMOVED:
return SetUtils.difference(getLinkedOld(), getLinkedNew());
case UNCHANGED:
return SetUtils.intersection(getLinkedOld(), getLinkedNew());
case CHANGED:
return SetUtils.disjunction(getLinkedOld(), getLinkedNew());
case IN_NEW:
return getLinkedNew();
case IN_OLD:
return getLinkedOld();
default:
throw new AssertionError(selector.getChangeSituation());
}
return switch (defaultIfNull(selector.getChangeSituation(), LinkChangeSituationType.ALWAYS)) {
case ALWAYS -> SetUtils.union(getLinkedOld(), getLinkedNew());
case ADDED -> SetUtils.difference(getLinkedNew(), getLinkedOld());
case REMOVED -> SetUtils.difference(getLinkedOld(), getLinkedNew());
case UNCHANGED -> SetUtils.intersection(getLinkedOld(), getLinkedNew());
case CHANGED -> SetUtils.disjunction(getLinkedOld(), getLinkedNew());
case IN_NEW -> getLinkedNew();
case IN_OLD -> getLinkedOld();
};
}

private Set<PrismReferenceValue> getLinkedOld() {
Expand Down

0 comments on commit eac6bfb

Please sign in to comment.