From b946328fcb7b6e121733dc1dc5ca202cd7dea4c9 Mon Sep 17 00:00:00 2001
From: Viktor Kovtun <viktor.kovtun@id.ethz.ch>
Date: Thu, 16 Apr 2020 17:24:42 +0200
Subject: [PATCH] SSDM-9369 Made the testLogging() full text search test pass
 correctly.

---
 ...bstractSearchObjectsOperationExecutor.java |   6 +-
 .../SearchGloballyOperationExecutor.java      |  21 +--
 .../asapi/v3/search/dao/ISQLSearchDAO.java    |  16 +++
 .../v3/search/dao/PostgresSearchDAO.java      |  30 +++-
 ...ID2PETranslator.java => IID2PEMapper.java} |   9 +-
 ...ityTranslator.java => IdentityMapper.java} |   4 +-
 .../v3/search/mapper/AttributesMapper.java    |   2 +-
 .../v3/search/mapper/CriteriaMapper.java      |   5 +-
 .../AbstractCompositeEntitySearchManager.java |   4 +-
 .../planner/AbstractLocalSearchManager.java   |  10 +-
 .../search/planner/AbstractSearchManager.java |   3 +-
 .../planner/ContentCopySearchManager.java     |   6 +-
 .../search/planner/DataSetSearchManager.java  |   6 +-
 .../planner/DataSetTypeSearchManager.java     |   6 +-
 .../planner/EntityTypeSearchManager.java      |   6 +-
 .../planner/ExperimentSearchManager.java      |   6 +-
 .../planner/ExperimentTypeSearchManager.java  |   6 +-
 .../planner/ExternalDmsSearchManager.java     |   6 +-
 .../planner/FileFormatTypeSearchManager.java  |   6 +-
 .../search/planner/GlobalSearchManager.java   |  94 ++++++++++---
 .../search/planner/IGlobalSearchManager.java  |  12 +-
 .../search/planner/ILocalSearchManager.java   |   6 +-
 .../v3/search/planner/ISearchManager.java     |  22 +--
 .../LinkedDataSetKindSearchManager.java       |   6 +-
 .../planner/LocatorTypeSearchManager.java     |   6 +-
 .../search/planner/MaterialSearchManager.java |   6 +-
 .../planner/MaterialTypeSearchManager.java    |   6 +-
 .../search/planner/PersonSearchManager.java   |   6 +-
 .../PhysicalDataSetKindSearchManager.java     |   6 +-
 .../search/planner/ProjectSearchManager.java  |   6 +-
 .../PropertyAssignmentSearchManager.java      |   6 +-
 .../planner/PropertyTypeSearchManager.java    |   6 +-
 .../planner/SampleContainerSearchManager.java |   6 +-
 .../search/planner/SampleSearchManager.java   |   6 +-
 .../planner/SampleTypeSearchManager.java      |   6 +-
 .../SemanticAnnotationSearchManager.java      |   6 +-
 .../v3/search/planner/SpaceSearchManager.java |   6 +-
 .../planner/StorageFormatSearchManager.java   |   6 +-
 .../v3/search/planner/TagSearchManager.java   |   6 +-
 .../search/translator/CriteriaTranslator.java |   9 +-
 .../GlobalSearchCriteriaTranslator.java       | 133 ++++++++++++++++++
 .../v3/search/translator/SQLLexemes.java      |  16 +++
 .../GlobalSearchTextConditionTranslator.java  |  57 --------
 .../condition/utils/TranslatorUtils.java      |   8 ++
 .../source/java/genericApplicationContext.xml |   3 +-
 45 files changed, 395 insertions(+), 219 deletions(-)
 rename openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/{IID2PETranslator.java => IID2PEMapper.java} (76%)
 rename openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/{IdentityTranslator.java => IdentityMapper.java} (87%)
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/GlobalSearchCriteriaTranslator.java
 delete mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/GlobalSearchTextConditionTranslator.java

diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/search/AbstractSearchObjectsOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/search/AbstractSearchObjectsOperationExecutor.java
index f050bd5832f..da396060ae2 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/search/AbstractSearchObjectsOperationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/search/AbstractSearchObjectsOperationExecutor.java
@@ -22,9 +22,7 @@ import java.util.stream.Collectors;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.*;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.ILocalSearchManager;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.ISearchManager;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -245,7 +243,7 @@ public abstract class AbstractSearchObjectsOperationExecutor<OBJECT, OBJECT_PE,
         // There results from the manager should already be filtered.
         final Set<Long> allResultsIds = getSearchManager().searchForIDs(userId, authorisationInformation, criteria, null, ID_COLUMN);
         final List<Long> sortedAndPagedResultIds = sortAndPage(allResultsIds, fetchOptions);
-        final List<OBJECT_PE> sortedAndPagedResultPEs = getSearchManager().translate(sortedAndPagedResultIds);
+        final List<OBJECT_PE> sortedAndPagedResultPEs = getSearchManager().map(sortedAndPagedResultIds);
         final Map<OBJECT_PE, OBJECT> sortedAndPagedResultV3DTOs = doTranslate(translationContext, sortedAndPagedResultPEs, fetchOptions);
 
         final List<OBJECT> finalResults = new ArrayList<>(sortedAndPagedResultV3DTOs.values());
@@ -268,7 +266,7 @@ public abstract class AbstractSearchObjectsOperationExecutor<OBJECT, OBJECT_PE,
         return sortedFinalResults;
     }
 
-    protected List<Long> sortAndPage(final Set<Long> ids, final FetchOptions<OBJECT> fo)
+    private List<Long> sortAndPage(final Set<Long> ids, final FetchOptions<OBJECT> fo)
     {
         //
         // Filter out sorts to ignore
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/globalsearch/SearchGloballyOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/globalsearch/SearchGloballyOperationExecutor.java
index c60ec37ee2e..598067311f5 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/globalsearch/SearchGloballyOperationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/globalsearch/SearchGloballyOperationExecutor.java
@@ -94,18 +94,19 @@ public class SearchGloballyOperationExecutor
         final TranslationContext translationContext = new TranslationContext(context.getSession());
 
         // There results from the manager should already be filtered.
-        final Set<Long> sampleResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.SAMPLE);
-        final Set<Long> experimentResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.EXPERIMENT);
-        final Set<Long> dataSetResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.DATA_SET);
-        final Set<Long> materialResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.MATERIAL);
+        final Set<Map<String, Object>> sampleResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.SAMPLE);
+        final Set<Map<String, Object>> experimentResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null,
+                TableMapper.EXPERIMENT);
+        final Set<Map<String, Object>> dataSetResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.DATA_SET);
+        final Set<Map<String, Object>> materialResultsIds = globalSearchManager.searchForIDs(userId, authorisationInformation, criteria, null, TableMapper.MATERIAL);
 
-        final Set<Long> allResultsIds = new HashSet<>(sampleResultsIds);
+        final Set<Map<String, Object>> allResultsIds = new HashSet<>(sampleResultsIds);
         allResultsIds.addAll(experimentResultsIds);
         allResultsIds.addAll(dataSetResultsIds);
         allResultsIds.addAll(materialResultsIds);
 
-        final List<Long> sortedAndPagedResultIds = sortAndPage(allResultsIds, fetchOptions);
-        final List<MatchingEntity> sortedAndPagedResultPEs = globalSearchManager.translate(sortedAndPagedResultIds);
+        final List<Map<String, Object>> sortedAndPagedResultIds = sortAndPage(allResultsIds, fetchOptions);
+        final List<MatchingEntity> sortedAndPagedResultPEs = globalSearchManager.map(sortedAndPagedResultIds);
         final Map<MatchingEntity, GlobalSearchObject> sortedAndPagedResultV3DTOs = doTranslate(translationContext, sortedAndPagedResultPEs, fetchOptions);
 
         final List<GlobalSearchObject> finalResults = new ArrayList<>(sortedAndPagedResultV3DTOs.values());
@@ -116,12 +117,12 @@ public class SearchGloballyOperationExecutor
         return results;
     }
 
-    protected List<Long> sortAndPage(final Set<Long> ids, final FetchOptions<GlobalSearchObject> fo)
+    protected List<Map<String, Object>> sortAndPage(final Set<Map<String, Object>> results, final FetchOptions<GlobalSearchObject> fo)
     {
         final SortOptions<GlobalSearchObject> sortOptions = fo.getSortBy();
-        final Set<Long> orderedIDs = (sortOptions != null) ? globalSearchManager.sortIDs(ids, sortOptions) : ids;
+        final Set<Map<String, Object>> orderedIDs = (sortOptions != null) ? globalSearchManager.sortIDs(results, sortOptions) : results;
 
-        final List<Long> toPage = new ArrayList<>(orderedIDs);
+        final List<Map<String, Object>> toPage = new ArrayList<>(orderedIDs);
         final Integer fromRecord = fo.getFrom();
         final Integer recordsCount = fo.getCount();
         final boolean hasPaging = fromRecord != null && recordsCount != null;
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/ISQLSearchDAO.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/ISQLSearchDAO.java
index 012250d7196..b5ba46cb916 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/ISQLSearchDAO.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/ISQLSearchDAO.java
@@ -16,10 +16,12 @@
 
 package ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao;
 
+import java.util.Map;
 import java.util.Set;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractCompositeSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchCriteria;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
@@ -40,6 +42,20 @@ public interface ISQLSearchDAO
     Set<Long> queryDBWithNonRecursiveCriteria(final Long userId, final AbstractCompositeSearchCriteria criterion, final TableMapper tableMapper,
             final String idsColumnName, final AuthorisationInformation authorisationInformation);
 
+    /**
+     * Queries the DB only with non recursive global text search criteria.
+     *
+     * @param userId ID of the user who makes the query.
+     * @param criterion the global text search criterion to search by.
+     * @param tableMapper table mapper that contains extra information about tables related to the entities which can have parent-child relationships.
+     * @param idsColumnName name of the column to select by, if {@code null} {@link ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.ID_COLUMN}
+     *     is used.
+     * @param authorisationInformation
+     * @return set of numbers which represent the IDs of the scpecified ID column name.
+     */
+    Set<Map<String, Object>> queryDBWithNonRecursiveCriteria(final Long userId, final GlobalSearchCriteria criterion, final TableMapper tableMapper,
+            final String idsColumnName, final AuthorisationInformation authorisationInformation);
+
     /**
      * Finds child IDs which correspond to parent IDs.
      *
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/PostgresSearchDAO.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/PostgresSearchDAO.java
index 2da882f3ca1..c227ba742b9 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/PostgresSearchDAO.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/dao/PostgresSearchDAO.java
@@ -18,14 +18,12 @@ package ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.*;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchCriteria;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.CriteriaMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.sql.ISQLExecutor;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.CriteriaTranslator;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.OrderTranslator;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SelectQuery;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.TranslationVo;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.*;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.TranslatorUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
@@ -78,6 +76,30 @@ public class PostgresSearchDAO implements ISQLSearchDAO
         ).collect(Collectors.toSet());
     }
 
+    @Override
+    public Set<Map<String, Object>> queryDBWithNonRecursiveCriteria(final Long userId, final GlobalSearchCriteria criterion,
+            final TableMapper tableMapper, final String idsColumnName, final AuthorisationInformation authorisationInformation)
+    {
+        final Collection<ISearchCriteria> criteria = criterion.getCriteria();
+        final SearchOperator operator = criterion.getOperator();
+
+        final String finalIdColumnName = (idsColumnName == null) ? ID_COLUMN : idsColumnName;
+
+        final TranslationVo translationVo = new TranslationVo();
+        translationVo.setUserId(userId);
+        translationVo.setTableMapper(tableMapper);
+        translationVo.setParentCriterion(criterion);
+        translationVo.setCriteria(criteria);
+        translationVo.setOperator(operator);
+        translationVo.setIdColumnName(finalIdColumnName);
+        translationVo.setAuthorisationInformation(authorisationInformation);
+
+        final SelectQuery selectQuery = GlobalSearchCriteriaTranslator.translate(translationVo);
+        final List<Map<String, Object>> result = sqlExecutor.execute(selectQuery.getQuery(), selectQuery.getArgs());
+
+        return new LinkedHashSet<>(result);
+    }
+
     @Override
     public Set<Long> findChildIDs(final TableMapper tableMapper, final Set<Long> parentIdSet)
     {
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IID2PETranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IID2PEMapper.java
similarity index 76%
rename from openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IID2PETranslator.java
rename to openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IID2PEMapper.java
index a145f81d5c0..fd2134fd62c 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IID2PETranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IID2PEMapper.java
@@ -19,13 +19,14 @@ package ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate;
 import java.util.List;
 
 /**
- * Translator from long IDs to {@link OBJECT_PE} type.
+ * Mapper from {@link ID} to {@link OBJECT_PE} type.
  *
- * @param <OBJECT_PE>
+ * @param <ID> the type to map from.
+ * @param <OBJECT_PE> the type to map to.
  */
-public interface IID2PETranslator<OBJECT_PE>
+public interface IID2PEMapper<ID, OBJECT_PE>
 {
 
-    List<OBJECT_PE> translate(final List<Long> ids);
+    List<OBJECT_PE> map(final List<ID> ids);
 
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IdentityTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IdentityMapper.java
similarity index 87%
rename from openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IdentityTranslator.java
rename to openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IdentityMapper.java
index 8df9f1dfec8..ae9e57a8e2b 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IdentityTranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/hibernate/IdentityMapper.java
@@ -21,11 +21,11 @@ import java.util.List;
 /**
  * Translator that translates IDs to the same values.
  */
-public class IdentityTranslator implements IID2PETranslator<Long>
+public class IdentityMapper implements IID2PEMapper<Long, Long>
 {
 
     @Override
-    public List<Long> translate(final List<Long> ids)
+    public List<Long> map(final List<Long> ids)
     {
         return ids;
     }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/AttributesMapper.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/AttributesMapper.java
index fa44bfe865e..f2ac16f6a03 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/AttributesMapper.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/AttributesMapper.java
@@ -26,7 +26,7 @@ import static ch.systemsx.cisd.openbis.generic.shared.dto.TableNames.*;
 
 public class AttributesMapper
 {
-    private static final String PERM_ID_ATTRIBUTE = "perm id";
+    public static final String PERM_ID_ATTRIBUTE = "perm id";
 
     private static final Map<String, String> ATTRIBUTE_ID_TO_COLUMN_NAME = new HashMap<>();
 
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java
index c12a1cebdee..08450cd1fd4 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java
@@ -39,7 +39,7 @@ import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.*;
  */
 public class CriteriaMapper {
 
-    private static final Map<Class<? extends ISearchCriteria>, ISearchManager<?>>
+    private static final Map<Class<? extends ISearchCriteria>, ISearchManager>
             CRITERIA_TO_MANAGER_MAP = new HashMap<>();
 
     /**
@@ -106,7 +106,6 @@ public class CriteriaMapper {
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(FirstNameSearchCriteria.class, new FirstNameSearchConditionTranslator());
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(GitCommitHashSearchCriteria.class, stringFieldSearchConditionTranslator);
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(GitRepositoryIdSearchCriteria.class, stringFieldSearchConditionTranslator);
-        CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(GlobalSearchTextCriteria.class, new GlobalSearchTextConditionTranslator());
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(IdSearchCriteria.class, new IdSearchConditionTranslator());
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(IdsSearchCriteria.class, collectionFieldSearchConditionTranslator);
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(IdentifierSearchCriteria.class, new IdentifierSearchConditionTranslator());
@@ -246,7 +245,7 @@ public class CriteriaMapper {
                 applicationContext.getBean("global-search-manager", IGlobalSearchManager.class));
     }
 
-    public static Map<Class<? extends ISearchCriteria>, ISearchManager<?>> getCriteriaToManagerMap()
+    public static Map<Class<? extends ISearchCriteria>, ISearchManager> getCriteriaToManagerMap()
     {
         return CRITERIA_TO_MANAGER_MAP;
     }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractCompositeEntitySearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractCompositeEntitySearchManager.java
index 2e2239b3076..81abe23f1ba 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractCompositeEntitySearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractCompositeEntitySearchManager.java
@@ -22,7 +22,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchOperator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames;
 
@@ -38,7 +38,7 @@ public abstract class AbstractCompositeEntitySearchManager<CRITERIA extends Abst
 {
 
     public AbstractCompositeEntitySearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<OBJECT_PE> idsTranslator)
+            final IID2PEMapper<Long, OBJECT_PE> idsTranslator)
     {
         super(searchDAO, authProvider, idsTranslator);
     }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractLocalSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractLocalSearchManager.java
index c4005b8c663..3db0e7e8601 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractLocalSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractLocalSearchManager.java
@@ -24,7 +24,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchOperator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.*;
@@ -39,10 +39,10 @@ public abstract class AbstractLocalSearchManager<CRITERIA extends ISearchCriteri
         implements ILocalSearchManager<CRITERIA, OBJECT, OBJECT_PE>
 {
 
-    private final IID2PETranslator<OBJECT_PE> idsTranslator;
+    private final IID2PEMapper<Long, OBJECT_PE> idsTranslator;
 
     public AbstractLocalSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<OBJECT_PE> idsTranslator)
+            final IID2PEMapper<Long, OBJECT_PE> idsTranslator)
     {
         super(authProvider, searchDAO);
         this.idsTranslator = idsTranslator;
@@ -140,8 +140,8 @@ public abstract class AbstractLocalSearchManager<CRITERIA extends ISearchCriteri
         return smallestSet;
     }
 
-    public List<OBJECT_PE> translate(final List<Long> ids) {
-        return idsTranslator.translate(ids);
+    public List<OBJECT_PE> map(final List<Long> ids) {
+        return idsTranslator.map(ids);
     }
 
     protected Set<Long> doSortIDs(final Set<Long> filteredIDs, final SortOptions<OBJECT> sortOptions, final TableMapper tableMapper)
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractSearchManager.java
index 3f2c095eabd..0690df95d76 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/AbstractSearchManager.java
@@ -13,7 +13,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import java.util.*;
 import java.util.stream.Collectors;
 
-public abstract class AbstractSearchManager<OBJECT> implements ISearchManager<OBJECT>
+public abstract class AbstractSearchManager<OBJECT>
 {
 
     protected final ISQLAuthorisationInformationProviderDAO authProvider;
@@ -37,7 +37,6 @@ public abstract class AbstractSearchManager<OBJECT> implements ISearchManager<OB
         return collection != null && !collection.isEmpty();
     }
 
-    @Override
     public Set<Long> filterIDsByUserRights(final Long userId, final AuthorisationInformation authorisationInformation, final Set<Long> ids)
     {
         if (authorisationInformation.isInstanceRole())
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ContentCopySearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ContentCopySearchManager.java
index 94db387e4f7..c8469c578f4 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ContentCopySearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ContentCopySearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.ContentCopySearch
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames;
 
@@ -38,9 +38,9 @@ public class ContentCopySearchManager extends AbstractLocalSearchManager<Content
 {
 
     public ContentCopySearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetSearchManager.java
index aefaea5fa44..fa2f80c92b0 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetSearchManager.java
@@ -29,7 +29,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCrit
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Collection;
@@ -45,9 +45,9 @@ public class DataSetSearchManager extends AbstractCompositeEntitySearchManager<D
 {
 
     public DataSetSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     protected Class<? extends AbstractCompositeSearchCriteria> getContainerSearchCriteriaClass()
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetTypeSearchManager.java
index 20c7f61a96b..6001712ad74 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/DataSetTypeSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetTypeSearch
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class DataSetTypeSearchManager extends AbstractLocalSearchManager<DataSet
 {
 
     public DataSetTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/EntityTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/EntityTypeSearchManager.java
index 5d19b29c2e6..87d1e928ba2 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/EntityTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/EntityTypeSearchManager.java
@@ -22,7 +22,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSear
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -39,9 +39,9 @@ public class EntityTypeSearchManager extends AbstractLocalSearchManager<EntityTy
 {
 
     public EntityTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentSearchManager.java
index 2ab3fbc56d4..70fdf9963bc 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentSear
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class ExperimentSearchManager extends AbstractLocalSearchManager<Experime
 {
     public ExperimentSearchManager(final ISQLSearchDAO searchDAO,
             final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentTypeSearchManager.java
index afbd99c5383..5d4173fb096 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExperimentTypeSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentType
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class ExperimentTypeSearchManager extends AbstractLocalSearchManager<Expe
 {
 
     public ExperimentTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExternalDmsSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExternalDmsSearchManager.java
index 71fb55d3491..0d82f3d9a84 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExternalDmsSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ExternalDmsSearchManager.java
@@ -22,7 +22,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.ExternalDmsSearch
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalDataManagementSystem;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames;
@@ -38,9 +38,9 @@ public class ExternalDmsSearchManager extends AbstractLocalSearchManager<Externa
 {
 
     public ExternalDmsSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/FileFormatTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/FileFormatTypeSearchManager.java
index 8eb9cb8ae70..5cc01eb56e3 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/FileFormatTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/FileFormatTypeSearchManager.java
@@ -22,7 +22,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.FileFormatTypeSea
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
 
@@ -39,9 +39,9 @@ public class FileFormatTypeSearchManager extends AbstractLocalSearchManager<File
 {
 
     public FileFormatTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/GlobalSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/GlobalSearchManager.java
index 5aa9b5168c7..663a530f4a8 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/GlobalSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/GlobalSearchManager.java
@@ -6,40 +6,75 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchCriter
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.*;
 
 import java.util.*;
+import java.util.stream.Collectors;
 
-public class GlobalSearchManager extends AbstractSearchManager<GlobalSearchObject> implements IGlobalSearchManager
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.GlobalSearchCriteriaTranslator.*;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.*;
+
+public class GlobalSearchManager implements IGlobalSearchManager
 {
 
-    private final IID2PETranslator<MatchingEntity> idsTranslator;
+    protected final ISQLAuthorisationInformationProviderDAO authProvider;
+
+    private final ISQLSearchDAO searchDAO;
 
-    public GlobalSearchManager(final ISQLAuthorisationInformationProviderDAO authProvider, final ISQLSearchDAO searchDAO, final IID2PETranslator<MatchingEntity> idsTranslator)
+    public GlobalSearchManager(final ISQLAuthorisationInformationProviderDAO authProvider, final ISQLSearchDAO searchDAO)
     {
-        super(authProvider, searchDAO);
-        this.idsTranslator = idsTranslator;
+        this.searchDAO = searchDAO;
+        this.authProvider = authProvider;
     }
 
     @Override
-    public Set<Long> searchForIDs(final Long userId, final AuthorisationInformation authorisationInformation, final GlobalSearchCriteria criteria,
+    public Set<Map<String, Object>> searchForIDs(final Long userId, final AuthorisationInformation authorisationInformation, final GlobalSearchCriteria criteria,
             final String idsColumnName, final TableMapper tableMapper)
     {
-        ///////////// TODO: probably subcriteria should be used in this query not the main criteria.
-        final Set<Long> mainCriteriaIntermediateResults = getSearchDAO().queryDBWithNonRecursiveCriteria(userId, criteria, tableMapper,
-                idsColumnName, authorisationInformation);
+        final Set<Map<String, Object>> mainCriteriaIntermediateResults = searchDAO.queryDBWithNonRecursiveCriteria(userId,
+                criteria, tableMapper, idsColumnName, authorisationInformation);
 
         // If we have results, we use them
         // If we don't have results and criteria are not empty, there are no results.
-        final Set<Long> resultBeforeFiltering =
+        final Set<Map<String, Object>> resultBeforeFiltering =
                 containsValues(mainCriteriaIntermediateResults) ? mainCriteriaIntermediateResults : Collections.emptySet();
 
-        return filterIDsByUserRights(userId, authorisationInformation, resultBeforeFiltering);
+        return filterResultsByUserRights(authorisationInformation, resultBeforeFiltering);
     }
 
     @Override
+    public Set<Map<String, Object>> sortIDs(final Set<Map<String, Object>> filteredIDs, final SortOptions<GlobalSearchObject> sortOptions)
+    {
+        // TODO: implement sorting.
+        return filteredIDs;
+    }
+
+    /**
+     * Checks whether a collection contains any values.
+     *
+     * @param collection collection to be checked for values.
+     * @return {@code false} if collection is {@code null} or empty, true otherwise.
+     */
+    protected static boolean containsValues(final Collection<?> collection)
+    {
+        return collection != null && !collection.isEmpty();
+    }
+
+    private Set<Map<String, Object>> filterResultsByUserRights(final AuthorisationInformation authorisationInformation,
+            final Set<Map<String, Object>> result)
+    {
+        if (authorisationInformation.isInstanceRole())
+        {
+            return result;
+        } else
+        {
+            final Set<Long> allIds = result.stream().map(fieldMap -> (Long) fieldMap.get(ID_COLUMN)).collect(Collectors.toSet());
+            final Set<Long> filteredIds = doFilterIDsByUserRights(allIds, authorisationInformation);
+            return result.stream().filter(fieldMap -> filteredIds.contains((Long) fieldMap.get(ID_COLUMN))).collect(Collectors.toSet());
+        }
+    }
+
     protected Set<Long> doFilterIDsByUserRights(final Set<Long> ids, final AuthorisationInformation authorisationInformation)
     {
         // TODO: filtering is needed.
@@ -47,16 +82,33 @@ public class GlobalSearchManager extends AbstractSearchManager<GlobalSearchObjec
     }
 
     @Override
-    public Set<Long> sortIDs(final Set<Long> filteredIDs, final SortOptions<GlobalSearchObject> sortOptions)
+    public List<MatchingEntity> map(final List<Map<String, Object>> records)
     {
-        // TODO: implement sorting.
-        return filteredIDs;
-    }
+        return records.stream().map((fieldsMap) -> {
+            final MatchingEntity matchingEntity = new MatchingEntity();
+            matchingEntity.setCode((String) fieldsMap.get(CODE_COLUMN));
+            matchingEntity.setEntityKind(EntityKind.valueOf((String) fieldsMap.get(OBJECT_KIND_ALIAS)));
+//            matchingEntity.setEntityType();
+            matchingEntity.setId((Long) fieldsMap.get(ID_COLUMN));
+            matchingEntity.setPermId((String) fieldsMap.get(PERM_ID_COLUMN));
 
-    @Override
-    public List<MatchingEntity> translate(final List<Long> ids)
-    {
-        return idsTranslator.translate(ids);
+            matchingEntity.setIdentifier((String) fieldsMap.get(IDENTIFIER_ALIAS));
+            
+//            SearchDomainSearchResult searchResult = searchDomain.getSearchResult();
+//            matchingEntity.setSearchDomain(searchResult.getSearchDomain().getLabel());
+
+//            if (searchResult.getScore() != null)
+//            {
+            matchingEntity.setScore((Float) fieldsMap.get(RANK_ALIAS));
+//            }
+
+//            ISearchDomainResultLocation resultLocation = searchResult.getResultLocation();
+//            List<PropertyMatch> matches = createMatches(searchString, resultLocation);
+//            matchingEntity.setMatches(matches);
+//            translatedEntities.add(matchingEntity);
+
+            return matchingEntity;
+        }).collect(Collectors.toList());
     }
 
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/IGlobalSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/IGlobalSearchManager.java
index b361d10dd4c..0b17c76b33e 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/IGlobalSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/IGlobalSearchManager.java
@@ -16,16 +16,18 @@
 
 package ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.GlobalSearchObject;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchCriteria;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 
+import java.util.Map;
 import java.util.Set;
 
-public interface IGlobalSearchManager extends IID2PETranslator<MatchingEntity>, ISearchManager<GlobalSearchObject>
+public interface IGlobalSearchManager extends IID2PEMapper<Map<String, Object>, MatchingEntity>, ISearchManager
 {
 
     /**
@@ -39,7 +41,9 @@ public interface IGlobalSearchManager extends IID2PETranslator<MatchingEntity>,
      * @param tableMapper the table mapper that points to the table to run global search on.
      * @return set of IDs of found entities.
      */
-    Set<Long> searchForIDs(final Long userId, final AuthorisationInformation authorisationInformation, final GlobalSearchCriteria criteria,
-            final String idsColumnName, final TableMapper tableMapper);
+    Set<Map<String, Object>> searchForIDs(final Long userId, final AuthorisationInformation authorisationInformation,
+            final GlobalSearchCriteria criteria, final String idsColumnName, final TableMapper tableMapper);
+
+    Set<Map<String, Object>> sortIDs(Set<Map<String, Object>> filteredIDs, SortOptions<GlobalSearchObject> sortOptions);
 
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ILocalSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ILocalSearchManager.java
index fe6f31bb433..c21d44e0903 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ILocalSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ILocalSearchManager.java
@@ -22,9 +22,9 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractCompositeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 
-public interface ILocalSearchManager<CRITERIA extends ISearchCriteria, OBJECT, OBJECT_PE> extends ISearchManager<OBJECT>, IID2PETranslator<OBJECT_PE>
+public interface ILocalSearchManager<CRITERIA extends ISearchCriteria, OBJECT, OBJECT_PE> extends ISearchManager, IID2PEMapper<Long, OBJECT_PE>
 {
 
     /**
@@ -41,4 +41,6 @@ public interface ILocalSearchManager<CRITERIA extends ISearchCriteria, OBJECT, O
     Set<Long> searchForIDs(final Long userId, final AuthorisationInformation authorisationInformation, final CRITERIA criteria,
             final AbstractCompositeSearchCriteria parentCriteria, final String idsColumnName);
 
+    Set<Long> sortIDs(Set<Long> filteredIDs, SortOptions<OBJECT> sortOptions);
+
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ISearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ISearchManager.java
index 811ad9ccd99..3ea6b366677 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ISearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ISearchManager.java
@@ -16,27 +16,7 @@
 
 package ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner;
 
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOptions;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractCompositeSearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
-
-import java.util.Set;
-
-public interface ISearchManager<OBJECT>
+public interface ISearchManager
 {
 
-    /**
-     * Filters IDs of certain
-     *
-     * @param userId
-     * @param authorisationInformation
-     * @param ids
-     * @return
-     */
-    Set<Long> filterIDsByUserRights(Long userId, final AuthorisationInformation authorisationInformation, Set<Long> ids);
-
-    Set<Long> sortIDs(Set<Long> filteredIDs, SortOptions<OBJECT> sortOptions);
-
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LinkedDataSetKindSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LinkedDataSetKindSearchManager.java
index e5b20c3dbfd..c43a917e60c 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LinkedDataSetKindSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LinkedDataSetKindSearchManager.java
@@ -24,7 +24,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.LinkedDataSearchC
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 
 import java.util.Collections;
 import java.util.Set;
@@ -42,9 +42,9 @@ public class LinkedDataSetKindSearchManager extends AbstractLocalSearchManager<L
 {
 
     public LinkedDataSetKindSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LocatorTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LocatorTypeSearchManager.java
index 928147703bb..6c2445ef1f4 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LocatorTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/LocatorTypeSearchManager.java
@@ -22,7 +22,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.LocatorTypeSearch
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType;
 
@@ -39,9 +39,9 @@ public class LocatorTypeSearchManager extends AbstractLocalSearchManager<Locator
 {
 
     public LocatorTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialSearchManager.java
index bf2f08c954d..efb437b764f 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialSearchManager.java
@@ -26,7 +26,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleParentsSearc
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Collections;
@@ -41,9 +41,9 @@ public class MaterialSearchManager extends AbstractCompositeEntitySearchManager<
 {
 
     public MaterialSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialTypeSearchManager.java
index d51061a64ae..5acca3fa3af 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/MaterialTypeSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.search.MaterialTypeSear
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -39,9 +39,9 @@ public class MaterialTypeSearchManager extends AbstractLocalSearchManager<Materi
 {
 
     public MaterialTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PersonSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PersonSearchManager.java
index 0f55f9a9dce..67bf0bd4f2f 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PersonSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PersonSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.search.PersonSearchCriter
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class PersonSearchManager extends AbstractLocalSearchManager<PersonSearch
 {
 
     public PersonSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PhysicalDataSetKindSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PhysicalDataSetKindSearchManager.java
index 40d84680180..d89d0c8c06a 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PhysicalDataSetKindSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PhysicalDataSetKindSearchManager.java
@@ -24,7 +24,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.PhysicalDataSearc
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 
 import java.util.Collections;
 import java.util.Set;
@@ -41,9 +41,9 @@ public class PhysicalDataSetKindSearchManager extends AbstractLocalSearchManager
 {
 
     public PhysicalDataSetKindSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ProjectSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ProjectSearchManager.java
index d937ef6b3db..dcefa1528d6 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ProjectSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/ProjectSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.search.ProjectSearchCrit
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class ProjectSearchManager extends AbstractLocalSearchManager<ProjectSear
 {
 
     public ProjectSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyAssignmentSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyAssignmentSearchManager.java
index 8b1d4e5ec9b..660f9666b13 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyAssignmentSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyAssignmentSearchManager.java
@@ -26,7 +26,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInfo
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.IPropertyAssignmentSearchDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.HashSet;
@@ -46,9 +46,9 @@ public class PropertyAssignmentSearchManager extends
     private IPropertyAssignmentSearchDAO assignmentsSearchDAO;
 
     public PropertyAssignmentSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator, final IPropertyAssignmentSearchDAO assignmentsSearchDAO)
+            final IID2PEMapper idsMapper, final IPropertyAssignmentSearchDAO assignmentsSearchDAO)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
         this.assignmentsSearchDAO = assignmentsSearchDAO;
     }
 
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyTypeSearchManager.java
index 3ee783beb52..b258df006a1 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/PropertyTypeSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyTypeSear
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class PropertyTypeSearchManager extends AbstractLocalSearchManager<Proper
 {
 
     public PropertyTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleContainerSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleContainerSearchManager.java
index 76db421cc9c..a181f0353f2 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleContainerSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleContainerSearchManager.java
@@ -25,7 +25,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleParentsSearc
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -39,9 +39,9 @@ public class SampleContainerSearchManager extends AbstractCompositeEntitySearchM
 {
 
     public SampleContainerSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleSearchManager.java
index 8aca6c847dd..52e5fabba57 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleSearchManager.java
@@ -25,7 +25,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriter
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -39,9 +39,9 @@ public class SampleSearchManager extends AbstractCompositeEntitySearchManager<Sa
 {
 
     public SampleSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleTypeSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleTypeSearchManager.java
index a3d8283ca5f..62219a952bc 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleTypeSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SampleTypeSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleTypeSearchCr
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -37,9 +37,9 @@ public class SampleTypeSearchManager extends AbstractLocalSearchManager<SampleTy
 {
 
     public SampleTypeSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SemanticAnnotationSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SemanticAnnotationSearchManager.java
index adf9e324fa6..d426bf61795 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SemanticAnnotationSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SemanticAnnotationSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.search.Semant
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -38,9 +38,9 @@ public class SemanticAnnotationSearchManager extends
 {
 
     public SemanticAnnotationSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator idsTranslator)
+            final IID2PEMapper idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SpaceSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SpaceSearchManager.java
index 8ff8b796830..d9c771a9d6f 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SpaceSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/SpaceSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.search.SpaceSearchCriteria
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Collections;
@@ -38,9 +38,9 @@ public class SpaceSearchManager extends AbstractLocalSearchManager<SpaceSearchCr
 {
 
     public SpaceSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/StorageFormatSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/StorageFormatSearchManager.java
index 8bbb916947a..a01225747f4 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/StorageFormatSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/StorageFormatSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.StorageFormatSear
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Set;
@@ -39,9 +39,9 @@ public class StorageFormatSearchManager extends AbstractLocalSearchManager<Stora
 {
 
     public StorageFormatSearchManager(final ISQLSearchDAO searchDAO,
-            final ISQLAuthorisationInformationProviderDAO authProvider, final IID2PETranslator<Long> idsTranslator)
+            final ISQLAuthorisationInformationProviderDAO authProvider, final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/TagSearchManager.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/TagSearchManager.java
index eaea70a54a3..6c713ce4526 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/TagSearchManager.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/planner/TagSearchManager.java
@@ -23,7 +23,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.tag.search.TagSearchCriteria;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.ISQLAuthorisationInformationProviderDAO;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.dao.ISQLSearchDAO;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PETranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IID2PEMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
 
 import java.util.Collection;
@@ -40,9 +40,9 @@ public class TagSearchManager extends AbstractLocalSearchManager<TagSearchCriter
 {
 
     public TagSearchManager(final ISQLSearchDAO searchDAO, final ISQLAuthorisationInformationProviderDAO authProvider,
-            final IID2PETranslator<Long> idsTranslator)
+            final IID2PEMapper<Long, Long> idsMapper)
     {
-        super(searchDAO, authProvider, idsTranslator);
+        super(searchDAO, authProvider, idsMapper);
     }
 
     @Override
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/CriteriaTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/CriteriaTranslator.java
index c7e0f11f19a..e8e3b782feb 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/CriteriaTranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/CriteriaTranslator.java
@@ -26,14 +26,12 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.EntityTypePermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentTypeSearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.search.MaterialTypeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleTypeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.tag.search.TagSearchCriteria;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.auth.AuthorisationInformation;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.CriteriaMapper;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.IGlobalSearchManager;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.ILocalSearchManager;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.ISearchManager;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.IConditionTranslator;
@@ -66,6 +64,11 @@ public class CriteriaTranslator
 
     public static final String MAIN_TABLE_ALIAS = getAlias(new AtomicInteger(0));
 
+    private CriteriaTranslator()
+    {
+        throw new UnsupportedOperationException();
+    }
+
     public static SelectQuery translate(final TranslationVo vo)
     {
         if (vo.getCriteria() == null)
@@ -161,7 +164,7 @@ public class CriteriaTranslator
             final StringBuilder sqlBuilder, ISearchCriteria criterion)
     {
         final TableMapper tableMapper = vo.getTableMapper();
-        final ISearchManager<?> subqueryManager = (criterion instanceof EntityTypeSearchCriteria)
+        final ISearchManager subqueryManager = (criterion instanceof EntityTypeSearchCriteria)
                 ? CriteriaMapper.getEntityKindToManagerMap().get(tableMapper.getEntityKind())
                 : CriteriaMapper.getCriteriaToManagerMap().get(criterion.getClass());
         final AbstractCompositeSearchCriteria parentCriterion = vo.getParentCriterion();
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/GlobalSearchCriteriaTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/GlobalSearchCriteriaTranslator.java
new file mode 100644
index 00000000000..febd65aaa2c
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/GlobalSearchCriteriaTranslator.java
@@ -0,0 +1,133 @@
+package ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchTextCriteria;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.AttributesMapper;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
+
+import java.util.List;
+import java.util.Spliterator;
+import java.util.stream.StreamSupport;
+
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.CriteriaTranslator.MAIN_TABLE_ALIAS;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.*;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.TranslatorUtils.buildFullIdentifierConcatenationString;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.*;
+
+public class GlobalSearchCriteriaTranslator
+{
+    private static final String REG_CONFIG = "simple";
+
+    public static final String OBJECT_KIND_ALIAS = "object_kind";
+
+    public static final String RANK_ALIAS = "rank";
+
+    public static final String IDENTIFIER_ALIAS = "identifier";
+
+    private GlobalSearchCriteriaTranslator()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public static SelectQuery translate(final TranslationVo vo)
+    {
+        if (vo.getCriteria() == null)
+        {
+            throw new IllegalArgumentException("Null criteria provided.");
+        }
+
+        final StringBuilder sqlBuilder = new StringBuilder();
+
+        final Spliterator<ISearchCriteria> spliterator = vo.getCriteria().stream().spliterator();
+        if (spliterator.tryAdvance((criterion) -> translateCriterion(sqlBuilder, vo, (GlobalSearchTextCriteria) criterion)))
+        {
+            StreamSupport.stream(spliterator, false).forEach((criterion) -> {
+                sqlBuilder.append(NL);
+                switch (vo.getOperator())
+                {
+                    case AND:
+                    {
+                        sqlBuilder.append(INTERSECT);
+                        break;
+                    }
+                    case OR:
+                    {
+                        sqlBuilder.append(UNION);
+                        break;
+                    }
+                }
+                sqlBuilder.append(NL);
+
+                translateCriterion(sqlBuilder, vo, (GlobalSearchTextCriteria) criterion);
+            });
+        }
+
+        return new SelectQuery(sqlBuilder.toString(), vo.getArgs());
+    }
+
+    private static void translateCriterion(final StringBuilder sqlBuilder, final TranslationVo vo, final GlobalSearchTextCriteria criterion)
+    {
+        final TableMapper tableMapper = vo.getTableMapper();
+        final Object value = criterion.getFieldValue().getValue();
+        final List<Object> args = vo.getArgs();
+
+        final String entitiesTable = tableMapper.getEntitiesTable();
+        final String samplesTableName = TableMapper.SAMPLE.getEntitiesTable();
+        final String projectsTableName = TableMapper.PROJECT.getEntitiesTable();
+        final String experimentsTableName = TableMapper.EXPERIMENT.getEntitiesTable();
+
+        final boolean hasSpaces = entitiesTable.equals(samplesTableName) || entitiesTable.equals(projectsTableName);
+        final boolean hasProjects = entitiesTable.equals(samplesTableName) || entitiesTable.equals(experimentsTableName);
+        final String spacesTableAlias = hasSpaces ? "spc" : null;
+        final String projectsTableAlias = hasProjects ? "prj" : null;
+        final String samplesTableAlias = tableMapper == TableMapper.SAMPLE ? MAIN_TABLE_ALIAS : null;
+
+        // SELECT
+
+        sqlBuilder.append(SELECT).append(SP).append(MAIN_TABLE_ALIAS).append(PERIOD).append(ID_COLUMN).append(COMMA).append(SP)
+                .append(MAIN_TABLE_ALIAS).append(PERIOD).append(CODE_COLUMN).append(COMMA).append(SP)
+                .append(SQ).append(tableMapper.getEntityKind()).append(SQ).append(SP).append(OBJECT_KIND_ALIAS).append(COMMA).append(SP);
+
+        sqlBuilder.append(MAIN_TABLE_ALIAS).append(PERIOD)
+                .append(AttributesMapper.getColumnName(AttributesMapper.PERM_ID_ATTRIBUTE, entitiesTable, null)).append(COMMA).append(SP);
+
+        buildFullIdentifierConcatenationString(sqlBuilder, spacesTableAlias, projectsTableAlias, samplesTableAlias);
+        sqlBuilder.append(IDENTIFIER_ALIAS).append(COMMA).append(SP);
+
+        sqlBuilder.append(TS_RANK).append(LP).append(MAIN_TABLE_ALIAS).append(PERIOD).append(TSVECTOR_DOCUMENT).append(COMMA).append(SP);
+
+        buildTsQueryPart(sqlBuilder, value, args);
+        sqlBuilder.append(RP).append(SP).append(RANK_ALIAS).append(NL);
+
+        // FROM
+
+        sqlBuilder.append(FROM).append(SP).append(entitiesTable).append(SP).append(MAIN_TABLE_ALIAS).append(NL);
+
+        if (hasProjects)
+        {
+            sqlBuilder.append(LEFT_JOIN).append(SP).append(projectsTableName).append(SP).append(projectsTableAlias).append(SP)
+                    .append(ON).append(SP).append(MAIN_TABLE_ALIAS).append(PERIOD).append(PROJECT_COLUMN).append(SP).append(EQ).append(SP)
+                    .append(projectsTableAlias).append(PERIOD).append(ID_COLUMN).append(NL);
+        }
+
+        if (hasSpaces)
+        {
+            sqlBuilder.append(LEFT_JOIN).append(SP).append(TableMapper.SPACE.getEntitiesTable()).append(SP).append(spacesTableAlias).append(SP)
+                    .append(ON).append(SP).append(MAIN_TABLE_ALIAS).append(PERIOD).append(SPACE_COLUMN).append(SP).append(EQ).append(SP)
+                    .append(spacesTableAlias).append(PERIOD).append(ID_COLUMN).append(NL);
+        }
+
+        // WHERE
+
+        sqlBuilder.append(WHERE).append(SP).append(TSVECTOR_DOCUMENT).append(SP).append(DOUBLE_AT).append(SP);
+
+        buildTsQueryPart(sqlBuilder, value, args);
+    }
+
+    private static void buildTsQueryPart(final StringBuilder sqlBuilder, final Object value, final List<Object> args)
+    {
+        sqlBuilder.append(PLAINTO_TSQUERY).append(LP).append(SQ).append(REG_CONFIG).append(SQ).append(COMMA).append(SP)
+                .append(QU).append(RP);
+        args.add(value);
+    }
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/SQLLexemes.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/SQLLexemes.java
index 234783802a9..05d0071e82d 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/SQLLexemes.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/SQLLexemes.java
@@ -25,6 +25,14 @@ public class SQLLexemes
 
     public static final String LOWER = "lower";
 
+    public static final String TS_RANK = "ts_rank";
+
+    public static final String TSVECTOR_DOCUMENT = "tsvector_document";
+
+    public static final String TO_TSQUERY = "to_tsquery";
+
+    public static final String PLAINTO_TSQUERY = "plainto_tsquery";
+
     public static final String NUMERIC = "numeric";
 
     public static final String TIMESTAMPTZ = "timestamptz";
@@ -101,6 +109,12 @@ public class SQLLexemes
 
     public static final String ORDER_BY = "ORDER BY";
 
+    public static final String INTERSECT = "INTERSECT";
+
+    public static final String UNION = "UNION";
+
+    public static final String UNION_ALL = "UNION ALL";
+
     public static final String NL = "\n";
 
     public static final String COMMA = ",";
@@ -139,6 +153,8 @@ public class SQLLexemes
 
     public static final String DQ = "\"";
 
+    public static final String DOUBLE_AT = "@@";
+
     public static final String TILDA = "~";
 
     public static final String SELECT_UNNEST = LP + SELECT + SP + UNNEST + LP + QU + RP + RP;
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/GlobalSearchTextConditionTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/GlobalSearchTextConditionTranslator.java
deleted file mode 100644
index 5fde14c4bf1..00000000000
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/GlobalSearchTextConditionTranslator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition;
-
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractStringValue;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.global.search.GlobalSearchTextCriteria;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.CriteriaTranslator;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.JoinInformation;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.TranslatorUtils;
-import ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames;
-
-import java.util.List;
-import java.util.Map;
-
-import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.PSQLTypes.VARCHAR;
-import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.TS_VECTOR_COLUMN;
-
-public class GlobalSearchTextConditionTranslator implements IConditionTranslator<GlobalSearchTextCriteria>
-{
-    @Override
-    public Map<String, JoinInformation> getJoinInformationMap(final GlobalSearchTextCriteria criterion, final TableMapper tableMapper, final IAliasFactory aliasFactory)
-    {
-        return null;
-    }
-
-    @Override
-    public void translate(final GlobalSearchTextCriteria criterion, final TableMapper tableMapper, final List<Object> args, final StringBuilder sqlBuilder, final Map<String, JoinInformation> aliases, final Map<String, String> dataTypeByPropertyName)
-    {
-        switch (criterion.getFieldType())
-        {
-            case ANY_FIELD:
-            {
-                final String criterionFieldName = criterion.getFieldName();
-                final AbstractStringValue value = criterion.getFieldValue();
-                normalizeValue(value, TS_VECTOR_COLUMN);
-
-                TranslatorUtils.translateStringComparison(CriteriaTranslator.MAIN_TABLE_ALIAS, TS_VECTOR_COLUMN, value, VARCHAR, sqlBuilder, args);
-                break;
-            }
-
-            case ATTRIBUTE:
-            case PROPERTY:
-            case ANY_PROPERTY:
-            {
-                throw new IllegalArgumentException();
-            }
-        }
-    }
-
-    private static void normalizeValue(final AbstractStringValue value, final String columnName)
-    {
-        if (columnName.equals(ColumnNames.CODE_COLUMN) && value.getValue().startsWith("/"))
-        {
-            value.setValue(value.getValue().substring(1));
-        }
-    }
-
-}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/utils/TranslatorUtils.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/utils/TranslatorUtils.java
index 11ea5715956..22fb48667a4 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/utils/TranslatorUtils.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/utils/TranslatorUtils.java
@@ -146,17 +146,25 @@ public class TranslatorUtils
                 case PERCENT:
                     // Fall through.
                 case BACKSLASH:
+                {
                     sb.append(BACKSLASH).append(ch);
                     break;
+                }
                 case ASTERISK:
+                {
                     sb.append(PERCENT);
                     break;
+                }
                 case QU:
+                {
                     sb.append(UNDERSCORE);
                     break;
+                }
                 default:
+                {
                     sb.append(ch);
                     break;
+                }
             }
         });
         return sb.toString();
diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml
index 9ef6109373f..a19b266df54 100644
--- a/openbis/source/java/genericApplicationContext.xml
+++ b/openbis/source/java/genericApplicationContext.xml
@@ -203,7 +203,7 @@
 		<constructor-arg ref="sql-executor"/>
 	</bean>
 
-	<bean id="identity-translator" class="ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IdentityTranslator">
+	<bean id="identity-translator" class="ch.ethz.sis.openbis.generic.server.asapi.v3.search.hibernate.IdentityMapper">
 	</bean>
 
 	<bean id="sample-search-manager" class="ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.SampleSearchManager" lazy-init="true">
@@ -370,7 +370,6 @@
 	<bean id="global-search-manager" class="ch.ethz.sis.openbis.generic.server.asapi.v3.search.planner.GlobalSearchManager" lazy-init="true">
 		<constructor-arg ref="information-provider-dao"/>
 		<constructor-arg ref="postgres-search-dao"/>
-		<constructor-arg ref="identity-translator"/>
 	</bean>
 
 	<!-- // Common -->
-- 
GitLab