jstastny-cz commented on code in PR #2328:
URL: 
https://github.com/apache/incubator-kie-kogito-apps/pull/2328#discussion_r3497381235


##########
data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/JPAQuery.java:
##########
@@ -156,17 +185,145 @@ protected final Predicate 
buildPredicateFunction(AttributeFilter filter, Root<E>
                 return builder
                         .lessThanOrEqualTo(getAttributePath(root, 
filter.getAttribute()), (Comparable) filter.getValue());
             case OR:
-                return builder.or(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, false, false);
             case AND:
-                return builder.and(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, true, false);
             case NOT:
-                return builder.not(filterPredicateFunction(root, 
builder).apply((AttributeFilter<?>) filter.getValue()));
+                AttributeFilter<?> innerFilter = (AttributeFilter<?>) 
filter.getValue();
+
+                // Handle NOT with AND/OR: Apply De Morgan's Law by negating 
and flipping the operator
+                if (innerFilter.getCondition() == FilterCondition.AND || 
innerFilter.getCondition() == FilterCondition.OR) {
+                    // NOT (A AND B) = NOT A OR NOT B, NOT (A OR B) = NOT A 
AND NOT B
+                    boolean flipToAnd = innerFilter.getCondition() == 
FilterCondition.OR;
+                    return buildGroupedPredicate(innerFilter, root, builder, 
criteriaQuery, flipToAnd, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute()) &&
+                        (innerFilter.getCondition() == 
FilterCondition.CONTAINS ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ALL ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ANY ||
+                                innerFilter.getCondition() == 
FilterCondition.EQUAL)) {
+                    return buildCollectionPredicate(innerFilter, root, 
builder, criteriaQuery, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute())) {
+                    return buildNegatedCollectionPredicate(innerFilter, root, 
builder, criteriaQuery);
+                }
+
+                return builder.not(filterPredicateFunction(root, builder, 
criteriaQuery).apply(innerFilter));
             default:
                 return null;
         }
 
     }
 
+    /**
+     * Builds predicates for AND/OR, grouping CONTAINS filters on same 
collection into single EXISTS.
+     * 
+     * @param isNegated if true, negates each predicate (for NOT operations 
with De Morgan's Law)
+     */
+    private Predicate buildGroupedPredicate(AttributeFilter<?> filter, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
isAnd, boolean isNegated) {
+
+        List<AttributeFilter<?>> nestedFilters = (List<AttributeFilter<?>>) 
filter.getValue();
+
+        java.util.Map<String, List<AttributeFilter<?>>> groups = new 
java.util.HashMap<>();
+        List<Predicate> otherPredicates = new ArrayList<>();
+
+        for (AttributeFilter<?> f : nestedFilters) {
+            if (f.getAttribute() != null && 
isCollectionAttribute(f.getAttribute()) &&
+                    (f.getCondition() == FilterCondition.CONTAINS ||

Review Comment:
   the same if condition is in the method above too, so I'd say it's a 
categorization that we want to have explicitly defined in a single place.



##########
data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/JPAQuery.java:
##########
@@ -156,17 +185,145 @@ protected final Predicate 
buildPredicateFunction(AttributeFilter filter, Root<E>
                 return builder
                         .lessThanOrEqualTo(getAttributePath(root, 
filter.getAttribute()), (Comparable) filter.getValue());
             case OR:
-                return builder.or(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, false, false);
             case AND:
-                return builder.and(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, true, false);
             case NOT:
-                return builder.not(filterPredicateFunction(root, 
builder).apply((AttributeFilter<?>) filter.getValue()));
+                AttributeFilter<?> innerFilter = (AttributeFilter<?>) 
filter.getValue();
+
+                // Handle NOT with AND/OR: Apply De Morgan's Law by negating 
and flipping the operator
+                if (innerFilter.getCondition() == FilterCondition.AND || 
innerFilter.getCondition() == FilterCondition.OR) {
+                    // NOT (A AND B) = NOT A OR NOT B, NOT (A OR B) = NOT A 
AND NOT B
+                    boolean flipToAnd = innerFilter.getCondition() == 
FilterCondition.OR;
+                    return buildGroupedPredicate(innerFilter, root, builder, 
criteriaQuery, flipToAnd, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute()) &&
+                        (innerFilter.getCondition() == 
FilterCondition.CONTAINS ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ALL ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ANY ||
+                                innerFilter.getCondition() == 
FilterCondition.EQUAL)) {
+                    return buildCollectionPredicate(innerFilter, root, 
builder, criteriaQuery, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute())) {
+                    return buildNegatedCollectionPredicate(innerFilter, root, 
builder, criteriaQuery);
+                }
+
+                return builder.not(filterPredicateFunction(root, builder, 
criteriaQuery).apply(innerFilter));
             default:
                 return null;
         }
 
     }
 
+    /**
+     * Builds predicates for AND/OR, grouping CONTAINS filters on same 
collection into single EXISTS.
+     * 
+     * @param isNegated if true, negates each predicate (for NOT operations 
with De Morgan's Law)
+     */
+    private Predicate buildGroupedPredicate(AttributeFilter<?> filter, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
isAnd, boolean isNegated) {
+
+        List<AttributeFilter<?>> nestedFilters = (List<AttributeFilter<?>>) 
filter.getValue();
+
+        java.util.Map<String, List<AttributeFilter<?>>> groups = new 
java.util.HashMap<>();
+        List<Predicate> otherPredicates = new ArrayList<>();
+
+        for (AttributeFilter<?> f : nestedFilters) {
+            if (f.getAttribute() != null && 
isCollectionAttribute(f.getAttribute()) &&
+                    (f.getCondition() == FilterCondition.CONTAINS ||
+                            f.getCondition() == FilterCondition.CONTAINS_ALL ||
+                            f.getCondition() == FilterCondition.CONTAINS_ANY ||
+                            f.getCondition() == FilterCondition.EQUAL)) {
+                String collection = f.getAttribute().split("\\.")[0];
+                groups.computeIfAbsent(collection, k -> new 
ArrayList<>()).add(f);
+            } else {
+                Predicate pred = filterPredicateFunction(root, builder, 
criteriaQuery).apply(f);
+                otherPredicates.add(isNegated ? builder.not(pred) : pred);
+            }
+        }
+
+        List<Predicate> allPredicates = new ArrayList<>(otherPredicates);
+        for (List<AttributeFilter<?>> groupFilters : groups.values()) {
+            if (groupFilters.size() == 1) {
+                
allPredicates.add(buildCollectionPredicate(groupFilters.get(0), root, builder, 
criteriaQuery, isNegated));
+            } else {
+                
allPredicates.add(buildMultiFilterCollectionPredicate(groupFilters, root, 
builder, criteriaQuery, isAnd, isNegated));
+            }
+        }
+
+        return isAnd ? builder.and(allPredicates.toArray(new Predicate[0]))
+                : builder.or(allPredicates.toArray(new Predicate[0]));
+    }
+
+    /**
+     * Builds single EXISTS with HAVING for multiple CONTAINS filters on same 
collection.
+     * Example: [{ comments.id: "A" }, { comments.status: "ACTIVE" }]
+     * → EXISTS(... HAVING SUM(id='A')>0 AND SUM(status='ACTIVE')>0)
+     * 
+     * @param isNegated if true, uses = 0 instead of > 0 and applies De 
Morgan's Law
+     */
+    private Predicate 
buildMultiFilterCollectionPredicate(List<AttributeFilter<?>> filters, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
combineWithAnd, boolean isNegated) {
+
+        String collectionName = filters.get(0).getAttribute().split("\\.")[0];
+
+        Subquery<Integer> subquery = criteriaQuery.subquery(Integer.class);
+        Root<E> subRoot = subquery.from(entityClass);
+        Join<?, ?> collectionJoin = subRoot.join(collectionName);
+
+        List<Predicate> havingConditions = new ArrayList<>();
+
+        for (AttributeFilter<?> filter : filters) {
+            String property = filter.getAttribute().split("\\.")[1];
+            List<Object> values = (filter.getCondition() == 
FilterCondition.CONTAINS || filter.getCondition() == FilterCondition.EQUAL)

Review Comment:
   Perhaps even each multipleValues condition could carry the information of 
what is the "joining" operation, if AND or OR ... but that's just a tiny detail.



##########
data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/JPAQuery.java:
##########
@@ -156,17 +185,145 @@ protected final Predicate 
buildPredicateFunction(AttributeFilter filter, Root<E>
                 return builder
                         .lessThanOrEqualTo(getAttributePath(root, 
filter.getAttribute()), (Comparable) filter.getValue());
             case OR:
-                return builder.or(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, false, false);
             case AND:
-                return builder.and(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, true, false);
             case NOT:
-                return builder.not(filterPredicateFunction(root, 
builder).apply((AttributeFilter<?>) filter.getValue()));
+                AttributeFilter<?> innerFilter = (AttributeFilter<?>) 
filter.getValue();
+
+                // Handle NOT with AND/OR: Apply De Morgan's Law by negating 
and flipping the operator
+                if (innerFilter.getCondition() == FilterCondition.AND || 
innerFilter.getCondition() == FilterCondition.OR) {
+                    // NOT (A AND B) = NOT A OR NOT B, NOT (A OR B) = NOT A 
AND NOT B
+                    boolean flipToAnd = innerFilter.getCondition() == 
FilterCondition.OR;
+                    return buildGroupedPredicate(innerFilter, root, builder, 
criteriaQuery, flipToAnd, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute()) &&
+                        (innerFilter.getCondition() == 
FilterCondition.CONTAINS ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ALL ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ANY ||
+                                innerFilter.getCondition() == 
FilterCondition.EQUAL)) {
+                    return buildCollectionPredicate(innerFilter, root, 
builder, criteriaQuery, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute())) {
+                    return buildNegatedCollectionPredicate(innerFilter, root, 
builder, criteriaQuery);
+                }
+
+                return builder.not(filterPredicateFunction(root, builder, 
criteriaQuery).apply(innerFilter));
             default:
                 return null;
         }
 
     }
 
+    /**
+     * Builds predicates for AND/OR, grouping CONTAINS filters on same 
collection into single EXISTS.
+     * 
+     * @param isNegated if true, negates each predicate (for NOT operations 
with De Morgan's Law)
+     */
+    private Predicate buildGroupedPredicate(AttributeFilter<?> filter, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
isAnd, boolean isNegated) {
+
+        List<AttributeFilter<?>> nestedFilters = (List<AttributeFilter<?>>) 
filter.getValue();
+
+        java.util.Map<String, List<AttributeFilter<?>>> groups = new 
java.util.HashMap<>();
+        List<Predicate> otherPredicates = new ArrayList<>();
+
+        for (AttributeFilter<?> f : nestedFilters) {
+            if (f.getAttribute() != null && 
isCollectionAttribute(f.getAttribute()) &&
+                    (f.getCondition() == FilterCondition.CONTAINS ||
+                            f.getCondition() == FilterCondition.CONTAINS_ALL ||
+                            f.getCondition() == FilterCondition.CONTAINS_ANY ||
+                            f.getCondition() == FilterCondition.EQUAL)) {
+                String collection = f.getAttribute().split("\\.")[0];
+                groups.computeIfAbsent(collection, k -> new 
ArrayList<>()).add(f);
+            } else {
+                Predicate pred = filterPredicateFunction(root, builder, 
criteriaQuery).apply(f);
+                otherPredicates.add(isNegated ? builder.not(pred) : pred);
+            }
+        }
+
+        List<Predicate> allPredicates = new ArrayList<>(otherPredicates);
+        for (List<AttributeFilter<?>> groupFilters : groups.values()) {
+            if (groupFilters.size() == 1) {
+                
allPredicates.add(buildCollectionPredicate(groupFilters.get(0), root, builder, 
criteriaQuery, isNegated));
+            } else {
+                
allPredicates.add(buildMultiFilterCollectionPredicate(groupFilters, root, 
builder, criteriaQuery, isAnd, isNegated));
+            }

Review Comment:
   what would happen if we call buildMultiFilterCollectionPredicate on 
groupFilters size=1 ? I mean, don't we have the "single-group" method while it 
could be done using the other?



##########
data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/JPAQuery.java:
##########
@@ -156,17 +185,145 @@ protected final Predicate 
buildPredicateFunction(AttributeFilter filter, Root<E>
                 return builder
                         .lessThanOrEqualTo(getAttributePath(root, 
filter.getAttribute()), (Comparable) filter.getValue());
             case OR:
-                return builder.or(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, false, false);
             case AND:
-                return builder.and(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, true, false);
             case NOT:
-                return builder.not(filterPredicateFunction(root, 
builder).apply((AttributeFilter<?>) filter.getValue()));
+                AttributeFilter<?> innerFilter = (AttributeFilter<?>) 
filter.getValue();
+
+                // Handle NOT with AND/OR: Apply De Morgan's Law by negating 
and flipping the operator
+                if (innerFilter.getCondition() == FilterCondition.AND || 
innerFilter.getCondition() == FilterCondition.OR) {
+                    // NOT (A AND B) = NOT A OR NOT B, NOT (A OR B) = NOT A 
AND NOT B
+                    boolean flipToAnd = innerFilter.getCondition() == 
FilterCondition.OR;
+                    return buildGroupedPredicate(innerFilter, root, builder, 
criteriaQuery, flipToAnd, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute()) &&
+                        (innerFilter.getCondition() == 
FilterCondition.CONTAINS ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ALL ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ANY ||
+                                innerFilter.getCondition() == 
FilterCondition.EQUAL)) {
+                    return buildCollectionPredicate(innerFilter, root, 
builder, criteriaQuery, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute())) {
+                    return buildNegatedCollectionPredicate(innerFilter, root, 
builder, criteriaQuery);
+                }
+
+                return builder.not(filterPredicateFunction(root, builder, 
criteriaQuery).apply(innerFilter));
             default:
                 return null;
         }
 
     }
 
+    /**
+     * Builds predicates for AND/OR, grouping CONTAINS filters on same 
collection into single EXISTS.
+     * 
+     * @param isNegated if true, negates each predicate (for NOT operations 
with De Morgan's Law)
+     */
+    private Predicate buildGroupedPredicate(AttributeFilter<?> filter, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
isAnd, boolean isNegated) {
+
+        List<AttributeFilter<?>> nestedFilters = (List<AttributeFilter<?>>) 
filter.getValue();
+
+        java.util.Map<String, List<AttributeFilter<?>>> groups = new 
java.util.HashMap<>();
+        List<Predicate> otherPredicates = new ArrayList<>();
+
+        for (AttributeFilter<?> f : nestedFilters) {
+            if (f.getAttribute() != null && 
isCollectionAttribute(f.getAttribute()) &&
+                    (f.getCondition() == FilterCondition.CONTAINS ||
+                            f.getCondition() == FilterCondition.CONTAINS_ALL ||
+                            f.getCondition() == FilterCondition.CONTAINS_ANY ||
+                            f.getCondition() == FilterCondition.EQUAL)) {
+                String collection = f.getAttribute().split("\\.")[0];
+                groups.computeIfAbsent(collection, k -> new 
ArrayList<>()).add(f);
+            } else {
+                Predicate pred = filterPredicateFunction(root, builder, 
criteriaQuery).apply(f);
+                otherPredicates.add(isNegated ? builder.not(pred) : pred);
+            }
+        }
+
+        List<Predicate> allPredicates = new ArrayList<>(otherPredicates);
+        for (List<AttributeFilter<?>> groupFilters : groups.values()) {
+            if (groupFilters.size() == 1) {
+                
allPredicates.add(buildCollectionPredicate(groupFilters.get(0), root, builder, 
criteriaQuery, isNegated));
+            } else {
+                
allPredicates.add(buildMultiFilterCollectionPredicate(groupFilters, root, 
builder, criteriaQuery, isAnd, isNegated));
+            }
+        }
+
+        return isAnd ? builder.and(allPredicates.toArray(new Predicate[0]))
+                : builder.or(allPredicates.toArray(new Predicate[0]));
+    }
+
+    /**
+     * Builds single EXISTS with HAVING for multiple CONTAINS filters on same 
collection.
+     * Example: [{ comments.id: "A" }, { comments.status: "ACTIVE" }]
+     * → EXISTS(... HAVING SUM(id='A')>0 AND SUM(status='ACTIVE')>0)
+     * 
+     * @param isNegated if true, uses = 0 instead of > 0 and applies De 
Morgan's Law
+     */
+    private Predicate 
buildMultiFilterCollectionPredicate(List<AttributeFilter<?>> filters, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
combineWithAnd, boolean isNegated) {
+
+        String collectionName = filters.get(0).getAttribute().split("\\.")[0];
+
+        Subquery<Integer> subquery = criteriaQuery.subquery(Integer.class);
+        Root<E> subRoot = subquery.from(entityClass);
+        Join<?, ?> collectionJoin = subRoot.join(collectionName);
+
+        List<Predicate> havingConditions = new ArrayList<>();
+
+        for (AttributeFilter<?> filter : filters) {
+            String property = filter.getAttribute().split("\\.")[1];
+            List<Object> values = (filter.getCondition() == 
FilterCondition.CONTAINS || filter.getCondition() == FilterCondition.EQUAL)

Review Comment:
   Could we perhaps alter AttributeFilter class by adding method that tells us 
if the value it holds is collection or single value? 
   So that then we'd be able to call `filter.isMultipleValues()` or similar? I 
noticed we have this conditional in 2 places at least. Or perhaps at least add 
static method to AttributeFilter, that accepts FilterCondition and tells us if 
expects multiple values or not? With that we could also FilterCondition enum to 
hold for each operation the boolean and add a method, e.g. IN would expect 
multiple values, CONTAINS would expect single value, etc. The AttributeFilter's 
static method then can only invoke FilterCondition#expectsMultipleValues() (or 
similar) .



##########
data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/JPAQuery.java:
##########
@@ -156,17 +185,145 @@ protected final Predicate 
buildPredicateFunction(AttributeFilter filter, Root<E>
                 return builder
                         .lessThanOrEqualTo(getAttributePath(root, 
filter.getAttribute()), (Comparable) filter.getValue());
             case OR:
-                return builder.or(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, false, false);
             case AND:
-                return builder.and(getRecursivePredicate(filter, root, 
builder).toArray(new Predicate[] {}));
+                return buildGroupedPredicate(filter, root, builder, 
criteriaQuery, true, false);
             case NOT:
-                return builder.not(filterPredicateFunction(root, 
builder).apply((AttributeFilter<?>) filter.getValue()));
+                AttributeFilter<?> innerFilter = (AttributeFilter<?>) 
filter.getValue();
+
+                // Handle NOT with AND/OR: Apply De Morgan's Law by negating 
and flipping the operator
+                if (innerFilter.getCondition() == FilterCondition.AND || 
innerFilter.getCondition() == FilterCondition.OR) {
+                    // NOT (A AND B) = NOT A OR NOT B, NOT (A OR B) = NOT A 
AND NOT B
+                    boolean flipToAnd = innerFilter.getCondition() == 
FilterCondition.OR;
+                    return buildGroupedPredicate(innerFilter, root, builder, 
criteriaQuery, flipToAnd, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute()) &&
+                        (innerFilter.getCondition() == 
FilterCondition.CONTAINS ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ALL ||
+                                innerFilter.getCondition() == 
FilterCondition.CONTAINS_ANY ||
+                                innerFilter.getCondition() == 
FilterCondition.EQUAL)) {
+                    return buildCollectionPredicate(innerFilter, root, 
builder, criteriaQuery, true);
+                }
+
+                if (innerFilter.getAttribute() != null && 
isCollectionAttribute(innerFilter.getAttribute())) {
+                    return buildNegatedCollectionPredicate(innerFilter, root, 
builder, criteriaQuery);
+                }
+
+                return builder.not(filterPredicateFunction(root, builder, 
criteriaQuery).apply(innerFilter));
             default:
                 return null;
         }
 
     }
 
+    /**
+     * Builds predicates for AND/OR, grouping CONTAINS filters on same 
collection into single EXISTS.
+     * 
+     * @param isNegated if true, negates each predicate (for NOT operations 
with De Morgan's Law)
+     */
+    private Predicate buildGroupedPredicate(AttributeFilter<?> filter, Root<E> 
root,
+            CriteriaBuilder builder, CriteriaQuery<?> criteriaQuery, boolean 
isAnd, boolean isNegated) {
+
+        List<AttributeFilter<?>> nestedFilters = (List<AttributeFilter<?>>) 
filter.getValue();
+
+        java.util.Map<String, List<AttributeFilter<?>>> groups = new 
java.util.HashMap<>();
+        List<Predicate> otherPredicates = new ArrayList<>();
+
+        for (AttributeFilter<?> f : nestedFilters) {
+            if (f.getAttribute() != null && 
isCollectionAttribute(f.getAttribute()) &&
+                    (f.getCondition() == FilterCondition.CONTAINS ||

Review Comment:
   If we're able to name a method nicely, I'd consider extending 
FilterCondition enum by a field and method that would return boolean and 
simplify this if to `f.getCondition().isXY()` .... is it `isCollection()` what 
we're checking here, i.e. filtering conditions based on fact if they are to be 
used on collections? Then I'd say it's an obvious candidate for such enum 
extension, cause it directly describes the value.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to