This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new 6190cd34d8 Rationalize AdminRealmsFilter for AnySearchDAO impls (#1490)
6190cd34d8 is described below

commit 6190cd34d89b64ed49fd88386d147372d877bdce
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Thu Aug 13 09:50:54 2026 +0200

    Rationalize AdminRealmsFilter for AnySearchDAO impls (#1490)
---
 .../common/dao/AbstractAnySearchDAO.java           | 40 ++++++++++++++
 .../jpa/dao/AbstractJPAAnySearchDAO.java           | 62 +++++-----------------
 .../persistence/neo4j/dao/Neo4jAnySearchDAO.java   | 50 +++--------------
 .../dao/ElasticsearchAnySearchDAO.java             | 57 +++++---------------
 .../dao/ElasticsearchAnySearchDAOTest.java         |  8 +--
 .../opensearch/dao/OpenSearchAnySearchDAO.java     | 57 +++++---------------
 .../opensearch/dao/OpenSearchAnySearchDAOTest.java |  8 +--
 7 files changed, 96 insertions(+), 186 deletions(-)

diff --git 
a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAnySearchDAO.java
 
b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAnySearchDAO.java
index 106ee3bc6b..52caba13a7 100644
--- 
a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAnySearchDAO.java
+++ 
b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAnySearchDAO.java
@@ -20,12 +20,16 @@ package org.apache.syncope.core.persistence.common.dao;
 
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
@@ -44,6 +48,7 @@ import 
org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.utils.RealmUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.data.domain.PageRequest;
@@ -54,6 +59,10 @@ import org.springframework.util.CollectionUtils;
 
 public abstract class AbstractAnySearchDAO extends AbstractSearchDAO 
implements AnySearchDAO {
 
+    public record AdminRealmsFilter<T>(T filter, Set<Pair<AnyTypeKind, 
String>> managed) {
+
+    }
+
     protected static final Logger LOG = 
LoggerFactory.getLogger(AnySearchDAO.class);
 
     private static final Set<String> ORDER_BY_NOT_ALLOWED = Set.of(
@@ -126,6 +135,37 @@ public abstract class AbstractAnySearchDAO extends 
AbstractSearchDAO implements
         return conditions.isEmpty() ? List.of() : 
search(SearchCond.and(conditions), anyTypeKind);
     }
 
+    protected <T> AdminRealmsFilter<T> processRealms(
+            final Realm base,
+            final boolean recursive,
+            final Set<String> adminRealms,
+            final Function<Set<String>, T> filterBuilder) {
+
+        Set<String> realmKeys = new HashSet<>();
+        Set<Pair<AnyTypeKind, String>> managed = new HashSet<>();
+
+        adminRealms.forEach(realmPath -> 
RealmUtils.ManagerRealm.of(realmPath).ifPresentOrElse(
+                realm -> managed.add(Pair.of(realm.kind(), realm.anyKey())),
+                () -> {
+                    Realm realm = 
realmSearchDAO.findByFullPath(realmPath).orElseThrow(() -> {
+                        SyncopeClientException noRealm = 
SyncopeClientException.build(ClientExceptionType.InvalidRealm);
+                        noRealm.getElements().add("Invalid realm specified: " 
+ realmPath);
+                        return noRealm;
+                    });
+
+                    if (recursive) {
+                        
realmKeys.addAll(realmSearchDAO.findDescendants(realm.getFullPath(), 
base.getFullPath()).
+                                stream().map(Realm::getKey).toList());
+                    } else {
+                        if (RealmUtils.subtree(realm.getFullPath(), 
base.getFullPath())) {
+                            realmKeys.add(realm.getKey());
+                        }
+                    }
+                }));
+
+        return new AdminRealmsFilter<>(filterBuilder.apply(realmKeys), 
managed);
+    }
+
     protected abstract long doCount(
             Realm base, boolean recursive, Set<String> adminRealms, SearchCond 
cond, AnyTypeKind kind);
 
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
index 1a9e660d58..0530f2dd99 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
@@ -29,12 +29,9 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.service.JAXRSService;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -60,7 +57,6 @@ import 
org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.apache.syncope.core.persistence.api.utils.RealmUtils;
 import org.apache.syncope.core.persistence.common.dao.AbstractAnySearchDAO;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
@@ -70,10 +66,6 @@ import org.springframework.data.domain.Sort;
  */
 abstract class AbstractJPAAnySearchDAO extends AbstractAnySearchDAO {
 
-    protected record AdminRealmsFilter(AnySearchNode.Leaf filter, 
Set<Pair<AnyTypeKind, String>> managed) {
-
-    }
-
     protected record QueryInfo(AnySearchNode node, Set<String> plainSchemas) {
 
     }
@@ -620,52 +612,24 @@ abstract class AbstractJPAAnySearchDAO extends 
AbstractAnySearchDAO {
         };
     }
 
-    protected AnySearchNode.Leaf buildAdminRealmsFilter(
-            final Set<String> realmKeys,
-            final SearchSupport svs,
-            final List<Object> parameters) {
-
-        if (realmKeys.isEmpty()) {
-            return new AnySearchNode.Leaf(defaultSV(svs), 
StringUtils.substringAfter(anyId(svs), '.') + " IS NOT NULL");
-        }
-
-        String realmKeysArg = realmKeys.stream().
-                map(realmKey -> "?" + setParameter(parameters, realmKey)).
-                collect(Collectors.joining(","));
-        return new AnySearchNode.Leaf(defaultSV(svs), "realm_id IN (" + 
realmKeysArg + ")");
-    }
-
-    protected AdminRealmsFilter getAdminRealmsFilter(
+    protected AdminRealmsFilter<AnySearchNode.Leaf> getAdminRealmsFilter(
             final Realm base,
             final boolean recursive,
             final Set<String> adminRealms,
             final List<Object> parameters,
             final SearchSupport svs) {
 
-        Set<String> realmKeys = new HashSet<>();
-        Set<Pair<AnyTypeKind, String>> managed = new HashSet<>();
-
-        if (recursive) {
-            adminRealms.forEach(realmPath -> 
RealmUtils.ManagerRealm.of(realmPath).ifPresentOrElse(
-                    realm -> managed.add(Pair.of(realm.kind(), 
realm.anyKey())),
-                    () -> {
-                        Realm realm = 
realmSearchDAO.findByFullPath(realmPath).orElseThrow(() -> {
-                            SyncopeClientException noRealm =
-                                    
SyncopeClientException.build(ClientExceptionType.InvalidRealm);
-                            noRealm.getElements().add("Invalid realm 
specified: " + realmPath);
-                            return noRealm;
-                        });
-
-                        
realmKeys.addAll(realmSearchDAO.findDescendants(realm.getFullPath(), 
base.getFullPath()).
-                                stream().map(Realm::getKey).toList());
-                    }));
-        } else {
-            if 
(RealmUtils.SubtreePredicate.of(adminRealms).test(base.getFullPath())) {
-                realmKeys.add(base.getKey());
+        return processRealms(base, recursive, adminRealms, realmKeys -> {
+            if (realmKeys.isEmpty()) {
+                return new AnySearchNode.Leaf(
+                        defaultSV(svs), StringUtils.substringAfter(anyId(svs), 
'.') + " IS NOT NULL");
             }
-        }
 
-        return new AdminRealmsFilter(buildAdminRealmsFilter(realmKeys, svs, 
parameters), managed);
+            String realmKeysArg = realmKeys.stream().
+                    map(realmKey -> "?" + setParameter(parameters, realmKey)).
+                    collect(Collectors.joining(","));
+            return new AnySearchNode.Leaf(defaultSV(svs), "realm_id IN (" + 
realmKeysArg + ")");
+        });
     }
 
     protected void visitNode(
@@ -771,7 +735,8 @@ abstract class AbstractJPAAnySearchDAO extends 
AbstractAnySearchDAO {
         SearchSupport svs = new SearchViewSupport(kind);
 
         // 1. get admin realms filter
-        AdminRealmsFilter filter = getAdminRealmsFilter(base, recursive, 
adminRealms, parameters, svs);
+        AdminRealmsFilter<AnySearchNode.Leaf> filter =
+                getAdminRealmsFilter(base, recursive, adminRealms, parameters, 
svs);
 
         // 2. transform search condition
         QueryInfo queryInfo = getQuery(
@@ -936,7 +901,8 @@ abstract class AbstractJPAAnySearchDAO extends 
AbstractAnySearchDAO {
         SearchSupport svs = new SearchViewSupport(kind);
 
         // 1. get admin realms filter
-        AdminRealmsFilter filter = getAdminRealmsFilter(base, recursive, 
adminRealms, parameters, svs);
+        AdminRealmsFilter<AnySearchNode.Leaf> filter =
+                getAdminRealmsFilter(base, recursive, adminRealms, parameters, 
svs);
 
         // 2. transform search condition
         QueryInfo queryInfo = getQuery(
diff --git 
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAnySearchDAO.java
 
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAnySearchDAO.java
index 2842f82944..a433c9fb2e 100644
--- 
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAnySearchDAO.java
+++ 
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAnySearchDAO.java
@@ -30,7 +30,6 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Strings;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.commons.text.TextStringBuilder;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
@@ -62,7 +61,6 @@ import 
org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.apache.syncope.core.persistence.api.utils.RealmUtils;
 import org.apache.syncope.core.persistence.common.dao.AbstractAnySearchDAO;
 import org.apache.syncope.core.persistence.neo4j.dao.repo.AnyRepoExt;
 import org.apache.syncope.core.persistence.neo4j.entity.AbstractAny;
@@ -88,10 +86,6 @@ import org.springframework.data.util.Streamable;
 
 public class Neo4jAnySearchDAO extends AbstractAnySearchDAO {
 
-    protected record AdminRealmsFilter(String filter, Set<Pair<AnyTypeKind, 
String>> managed) {
-
-    }
-
     protected record AnyCondQuery(String query, String field) {
 
     }
@@ -180,47 +174,19 @@ public class Neo4jAnySearchDAO extends 
AbstractAnySearchDAO {
         return clause.indexOf('*') != -1;
     }
 
-    protected String buildAdminRealmsFilter(
-            final Set<String> realmKeys,
-            final Map<String, Object> parameters) {
-
-        if (realmKeys.isEmpty()) {
-            return "(n)-[]-(:" + Neo4jRealm.NODE + ")";
-        }
-
-        return "(n)-[]-(r:" + Neo4jRealm.NODE + ") WHERE r.id IN $" + 
setParameter(parameters, realmKeys);
-    }
-
-    protected AdminRealmsFilter getAdminRealmsFilter(
+    protected AdminRealmsFilter<String> getAdminRealmsFilter(
             final Realm base,
             final boolean recursive,
             final Set<String> adminRealms,
             final Map<String, Object> parameters) {
 
-        Set<String> realmKeys = new HashSet<>();
-        Set<Pair<AnyTypeKind, String>> managed = new HashSet<>();
-
-        if (recursive) {
-            adminRealms.forEach(realmPath -> 
RealmUtils.ManagerRealm.of(realmPath).ifPresentOrElse(
-                    realm -> managed.add(Pair.of(realm.kind(), 
realm.anyKey())),
-                    () -> {
-                        Realm realm = 
realmSearchDAO.findByFullPath(realmPath).orElseThrow(() -> {
-                            SyncopeClientException noRealm =
-                                    
SyncopeClientException.build(ClientExceptionType.InvalidRealm);
-                            noRealm.getElements().add("Invalid realm 
specified: " + realmPath);
-                            return noRealm;
-                        });
-
-                        
realmKeys.addAll(realmSearchDAO.findDescendants(realm.getFullPath(), 
base.getFullPath()).
-                                stream().map(Realm::getKey).toList());
-                    }));
-        } else {
-            if 
(RealmUtils.SubtreePredicate.of(adminRealms).test(base.getFullPath())) {
-                realmKeys.add(base.getKey());
+        return processRealms(base, recursive, adminRealms, realmKeys -> {
+            if (realmKeys.isEmpty()) {
+                return "(n)-[]-(:" + Neo4jRealm.NODE + ")";
             }
-        }
 
-        return new AdminRealmsFilter(buildAdminRealmsFilter(realmKeys, 
parameters), managed);
+            return "(n)-[]-(r:" + Neo4jRealm.NODE + ") WHERE r.id IN $" + 
setParameter(parameters, realmKeys);
+        });
     }
 
     protected String getQuery(
@@ -910,7 +876,7 @@ public class Neo4jAnySearchDAO extends AbstractAnySearchDAO 
{
 
         Map<String, Object> parameters = new HashMap<>();
 
-        AdminRealmsFilter filter = getAdminRealmsFilter(base, recursive, 
adminRealms, parameters);
+        AdminRealmsFilter<String> filter = getAdminRealmsFilter(base, 
recursive, adminRealms, parameters);
 
         // 1. get the query string from the search condition
         QueryInfo queryInfo = getQuery(
@@ -979,7 +945,7 @@ public class Neo4jAnySearchDAO extends AbstractAnySearchDAO 
{
 
         Map<String, Object> parameters = new HashMap<>();
 
-        AdminRealmsFilter filter = getAdminRealmsFilter(base, recursive, 
adminRealms, parameters);
+        AdminRealmsFilter<String> filter = getAdminRealmsFilter(base, 
recursive, adminRealms, parameters);
 
         // 1. get the query string from the search condition
         QueryInfo queryInfo = getQuery(
diff --git 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
index 1288133f31..7464e165e7 100644
--- 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
+++ 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
@@ -36,18 +36,14 @@ import 
co.elastic.clients.elasticsearch.core.search.SourceConfig;
 import co.elastic.clients.json.JsonData;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.service.JAXRSService;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -74,7 +70,6 @@ import 
org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.utils.FormatUtils;
-import org.apache.syncope.core.persistence.api.utils.RealmUtils;
 import org.apache.syncope.core.persistence.common.dao.AbstractAnySearchDAO;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.ext.elasticsearch.client.ElasticsearchUtils;
@@ -87,10 +82,6 @@ import org.springframework.util.CollectionUtils;
  */
 public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
 
-    protected record AdminRealmsFilter(Optional<Query> query, 
Set<Pair<AnyTypeKind, String>> managed) {
-
-    }
-
     protected static final Set<String> ID_PROPS = Set.of("key", "id", "_id");
 
     protected final ElasticsearchClient client;
@@ -123,44 +114,22 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
         this.indexMaxResultWindow = indexMaxResultWindow;
     }
 
-    protected AdminRealmsFilter getAdminRealmsFilter(
+    protected AdminRealmsFilter<Optional<Query>> getAdminRealmsFilter(
             final Realm base,
             final boolean recursive,
             final Set<String> adminRealms) {
 
-        Set<Pair<AnyTypeKind, String>> managed = new HashSet<>();
-        List<Query> queries = new ArrayList<>();
-
-        if (recursive) {
-            adminRealms.forEach(realmPath -> 
RealmUtils.ManagerRealm.of(realmPath).ifPresentOrElse(
-                    realm -> managed.add(Pair.of(realm.kind(), 
realm.anyKey())),
-                    () -> {
-                        Realm realm = 
realmSearchDAO.findByFullPath(realmPath).orElseThrow(() -> {
-                            SyncopeClientException noRealm =
-                                    
SyncopeClientException.build(ClientExceptionType.InvalidRealm);
-                            noRealm.getElements().add("Invalid realm 
specified: " + realmPath);
-                            return noRealm;
-                        });
-
-                        realmSearchDAO.findDescendants(realm.getFullPath(), 
base.getFullPath()).
-                                stream().map(Realm::getKey).forEach(descendant 
-> queries.add(
-                                new Query.Builder().term(QueryBuilders.term().
-                                        
field("realm").value(descendant).caseInsensitive(false).build()).
-                                        build()));
-                    }));
-        } else {
-            if 
(RealmUtils.SubtreePredicate.of(adminRealms).test(base.getFullPath())) {
-                queries.add(new Query.Builder().term(QueryBuilders.term().
-                        
field("realm").value(base.getKey()).caseInsensitive(false).build()).
-                        build());
+        return processRealms(base, recursive, adminRealms, realmKeys -> {
+            if (realmKeys.isEmpty()) {
+                return Optional.empty();
             }
-        }
 
-        return new AdminRealmsFilter(
-                managed.isEmpty()
-                ? Optional.of(new 
Query.Builder().disMax(QueryBuilders.disMax().queries(queries).build()).build())
-                : Optional.empty(),
-                managed);
+            List<Query> queries = realmKeys.stream().
+                    map(realm -> new Query.Builder().term(QueryBuilders.term().
+                    
field("realm").value(realm).caseInsensitive(false).build()).
+                    build()).toList();
+            return Optional.of(new 
Query.Builder().disMax(QueryBuilders.disMax().queries(queries).build()).build());
+        });
     }
 
     protected Query getQuery(
@@ -184,13 +153,13 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
                         build();
             }
         } else {
-            AdminRealmsFilter filter = getAdminRealmsFilter(base, recursive, 
adminRealms);
+            AdminRealmsFilter<Optional<Query>> filter = 
getAdminRealmsFilter(base, recursive, adminRealms);
             query = getQuery(buildEffectiveCond(cond, filter.managed(), kind), 
kind);
 
-            if (filter.query().isPresent()) {
+            if (filter.filter().isPresent()) {
                 query = new Query.Builder().bool(
                         QueryBuilders.bool().
-                                filter(filter.query().get()).
+                                filter(filter.filter().get()).
                                 filter(query).build()).
                         build();
             }
diff --git 
a/ext/elasticsearch/persistence/src/test/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAOTest.java
 
b/ext/elasticsearch/persistence/src/test/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAOTest.java
index 8507d071f7..187b454ab6 100644
--- 
a/ext/elasticsearch/persistence/src/test/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAOTest.java
+++ 
b/ext/elasticsearch/persistence/src/test/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAOTest.java
@@ -119,23 +119,23 @@ public class ElasticsearchAnySearchDAOTest {
 
         // 2. test
         Set<String> adminRealms = Set.of(SyncopeConstants.ROOT_REALM);
-        ElasticsearchAnySearchDAO.AdminRealmsFilter filter =
+        ElasticsearchAnySearchDAO.AdminRealmsFilter<Optional<Query>> filter =
                 searchDAO.getAdminRealmsFilter(root, true, adminRealms);
 
         assertThat(new Query.Builder().disMax(QueryBuilders.disMax().queries(
                 new 
Query.Builder().term(QueryBuilders.term().caseInsensitive(false).
                         
field("realm").value("rootKey").caseInsensitive(false).build()).
                         build()).build()).build()).
-                usingRecursiveComparison().isEqualTo(filter.query().get());
+                usingRecursiveComparison().isEqualTo(filter.filter().get());
         assertEquals(Set.of(), filter.managed());
     }
 
     @Test
     public void getAdminRealmsFilter4manager() {
         Set<String> adminRealms = Set.of(new RealmUtils.ManagerRealm("/any", 
AnyTypeKind.GROUP, "groupKey").output());
-        ElasticsearchAnySearchDAO.AdminRealmsFilter filter =
+        ElasticsearchAnySearchDAO.AdminRealmsFilter<Optional<Query>> filter =
                 searchDAO.getAdminRealmsFilter(realmDAO.getRoot(), true, 
adminRealms);
-        assertFalse(filter.query().isPresent());
+        assertFalse(filter.filter().isPresent());
         assertEquals(Set.of(Pair.of(AnyTypeKind.GROUP, "groupKey")), 
filter.managed());
     }
 
diff --git 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
index cdc55934b2..d521cfcd28 100644
--- 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
+++ 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
@@ -20,18 +20,14 @@ package org.apache.syncope.core.persistence.opensearch.dao;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.service.JAXRSService;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -58,7 +54,6 @@ import 
org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.utils.FormatUtils;
-import org.apache.syncope.core.persistence.api.utils.RealmUtils;
 import org.apache.syncope.core.persistence.common.dao.AbstractAnySearchDAO;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.ext.opensearch.client.OpenSearchUtils;
@@ -86,10 +81,6 @@ import org.springframework.util.CollectionUtils;
  */
 public class OpenSearchAnySearchDAO extends AbstractAnySearchDAO {
 
-    protected record AdminRealmsFilter(Optional<Query> query, 
Set<Pair<AnyTypeKind, String>> managed) {
-
-    }
-
     protected static final Set<String> ID_PROPS = Set.of("key", "id", "_id");
 
     protected final OpenSearchClient client;
@@ -122,44 +113,22 @@ public class OpenSearchAnySearchDAO extends 
AbstractAnySearchDAO {
         this.indexMaxResultWindow = indexMaxResultWindow;
     }
 
-    protected AdminRealmsFilter getAdminRealmsFilter(
+    protected AdminRealmsFilter<Optional<Query>> getAdminRealmsFilter(
             final Realm base,
             final boolean recursive,
             final Set<String> adminRealms) {
 
-        Set<Pair<AnyTypeKind, String>> managed = new HashSet<>();
-        List<Query> queries = new ArrayList<>();
-
-        if (recursive) {
-            adminRealms.forEach(realmPath -> 
RealmUtils.ManagerRealm.of(realmPath).ifPresentOrElse(
-                    realm -> managed.add(Pair.of(realm.kind(), 
realm.anyKey())),
-                    () -> {
-                        Realm realm = 
realmSearchDAO.findByFullPath(realmPath).orElseThrow(() -> {
-                            SyncopeClientException noRealm =
-                                    
SyncopeClientException.build(ClientExceptionType.InvalidRealm);
-                            noRealm.getElements().add("Invalid realm 
specified: " + realmPath);
-                            return noRealm;
-                        });
-
-                        realmSearchDAO.findDescendants(realm.getFullPath(), 
base.getFullPath()).
-                                stream().map(Realm::getKey).forEach(descendant 
-> queries.add(
-                                new Query.Builder().term(QueryBuilders.term().
-                                        
field("realm").value(FieldValue.of(descendant)).caseInsensitive(false).build()).
-                                        build()));
-                    }));
-        } else {
-            if 
(RealmUtils.SubtreePredicate.of(adminRealms).test(base.getFullPath())) {
-                queries.add(new Query.Builder().term(QueryBuilders.term().
-                        
field("realm").value(FieldValue.of(base.getKey())).caseInsensitive(false).build()).
-                        build());
+        return processRealms(base, recursive, adminRealms, realmKeys -> {
+            if (realmKeys.isEmpty()) {
+                return Optional.empty();
             }
-        }
 
-        return new AdminRealmsFilter(
-                managed.isEmpty()
-                ? Optional.of(new 
Query.Builder().disMax(QueryBuilders.disMax().queries(queries).build()).build())
-                : Optional.empty(),
-                managed);
+            List<Query> queries = realmKeys.stream().
+                    map(realm -> new Query.Builder().term(QueryBuilders.term().
+                    
field("realm").value(FieldValue.of(realm)).caseInsensitive(false).build()).
+                    build()).toList();
+            return Optional.of(new 
Query.Builder().disMax(QueryBuilders.disMax().queries(queries).build()).build());
+        });
     }
 
     protected Query getQuery(
@@ -183,13 +152,13 @@ public class OpenSearchAnySearchDAO extends 
AbstractAnySearchDAO {
                         build();
             }
         } else {
-            AdminRealmsFilter filter = getAdminRealmsFilter(base, recursive, 
adminRealms);
+            AdminRealmsFilter<Optional<Query>> filter = 
getAdminRealmsFilter(base, recursive, adminRealms);
             query = getQuery(buildEffectiveCond(cond, filter.managed(), kind), 
kind);
 
-            if (filter.query().isPresent()) {
+            if (filter.filter().isPresent()) {
                 query = new Query.Builder().bool(
                         QueryBuilders.bool().
-                                filter(filter.query().get()).
+                                filter(filter.filter().get()).
                                 filter(query).build()).
                         build();
             }
diff --git 
a/ext/opensearch/persistence/src/test/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAOTest.java
 
b/ext/opensearch/persistence/src/test/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAOTest.java
index 20998de3ba..560386ee5d 100644
--- 
a/ext/opensearch/persistence/src/test/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAOTest.java
+++ 
b/ext/opensearch/persistence/src/test/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAOTest.java
@@ -120,23 +120,23 @@ public class OpenSearchAnySearchDAOTest {
 
         // 2. test
         Set<String> adminRealms = Set.of(SyncopeConstants.ROOT_REALM);
-        OpenSearchAnySearchDAO.AdminRealmsFilter filter =
+        OpenSearchAnySearchDAO.AdminRealmsFilter<Optional<Query>> filter =
                 searchDAO.getAdminRealmsFilter(root, true, adminRealms);
 
         assertThat(new Query.Builder().disMax(QueryBuilders.disMax().queries(
                 new 
Query.Builder().term(QueryBuilders.term().caseInsensitive(false).
                         
field("realm").value(FieldValue.of("rootKey")).caseInsensitive(false).build()).
                         build()).build()).build()).
-                usingRecursiveComparison().isEqualTo(filter.query().get());
+                usingRecursiveComparison().isEqualTo(filter.filter().get());
         assertEquals(Set.of(), filter.managed());
     }
 
     @Test
     public void getAdminRealmsFilter4manager() {
         Set<String> adminRealms = Set.of(new RealmUtils.ManagerRealm("/any", 
AnyTypeKind.GROUP, "groupKey").output());
-        OpenSearchAnySearchDAO.AdminRealmsFilter filter =
+        OpenSearchAnySearchDAO.AdminRealmsFilter<Optional<Query>> filter =
                 searchDAO.getAdminRealmsFilter(realmDAO.getRoot(), true, 
adminRealms);
-        assertFalse(filter.query().isPresent());
+        assertFalse(filter.filter().isPresent());
         assertEquals(Set.of(Pair.of(AnyTypeKind.GROUP, "groupKey")), 
filter.managed());
     }
 

Reply via email to