From e9331c4ae5820c00c6b1ec47c9f4a93b9347fe2e Mon Sep 17 00:00:00 2001
From: anttil <anttil>
Date: Fri, 29 Jan 2016 12:35:12 +0000
Subject: [PATCH] SSDM-3078: Global search should have only one row per entity,
 and only one column for the match

SVN: 35594
---
 .../application/MatchingEntitiesPanel.java    |  18 +-
 .../web/client/application/SearchWidget.java  |   2 +-
 .../dto/MatchingEntitiesPanelColumnIDs.java   |  10 +-
 .../resultset/MatchingEntitiesProvider.java   |  15 +-
 .../openbis/generic/server/CommonServer.java  | 177 +++++++-----------
 .../dataaccess/db/HibernateSearchDAO.java     | 163 +++++++++++-----
 .../shared/basic/dto/MatchingEntity.java      |  46 +++--
 .../dto/ExperimentGlobalSearchBridge.java     |   2 +-
 .../shared/dto/GlobalSearchBridge.java        |  17 +-
 .../shared/dto/SampleGlobalSearchBridge.java  |   3 +-
 .../openbis/generic/shared/util/IColumn.java  |   5 +
 .../shared/util/TypedTableModelBuilder.java   |  15 +-
 .../cisd/openbis/public/common-dictionary.js  |   4 +-
 .../dataaccess/db/HibernateSearchDAOTest.java |   8 +-
 14 files changed, 273 insertions(+), 212 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
index 1dc81bfc053..3caa574e185 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
@@ -18,7 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application;
 
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.ENTITY_TYPE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.IDENTIFIER;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.MATCHING_FIELD;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.MATCH;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.REGISTRATOR;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
@@ -189,6 +189,7 @@ public final class MatchingEntitiesPanel extends TypedTableGrid<MatchingEntity>
                 super.createColumnsDefinition();
         schema.setGridCellRendererFor(REGISTRATOR, PersonRenderer.REGISTRATOR_RENDERER);
         schema.setGridCellRendererFor(IDENTIFIER, createInternalLinkCellRenderer());
+        schema.setGridCellRendererFor(MATCH, createMultilineStringCellRenderer());
         return schema;
     }
 
@@ -221,19 +222,18 @@ public final class MatchingEntitiesPanel extends TypedTableGrid<MatchingEntity>
     @Override
     protected List<String> getColumnIdsOfFilters()
     {
-        return Arrays.asList(ENTITY_TYPE, IDENTIFIER, MATCHING_FIELD);
+        return Arrays.asList(ENTITY_TYPE, IDENTIFIER, MATCH);
     }
 
     @Override
     public DatabaseModificationKind[] getRelevantModifications()
     {
-        return new DatabaseModificationKind[]
-            { createOrDelete(ObjectKind.MATERIAL), edit(ObjectKind.MATERIAL),
-                    createOrDelete(ObjectKind.SAMPLE), edit(ObjectKind.SAMPLE),
-                    createOrDelete(ObjectKind.EXPERIMENT), edit(ObjectKind.EXPERIMENT),
-                    createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
-                    edit(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
-                    createOrDelete(ObjectKind.VOCABULARY_TERM), edit(ObjectKind.VOCABULARY_TERM) };
+        return new DatabaseModificationKind[] { createOrDelete(ObjectKind.MATERIAL), edit(ObjectKind.MATERIAL),
+                createOrDelete(ObjectKind.SAMPLE), edit(ObjectKind.SAMPLE),
+                createOrDelete(ObjectKind.EXPERIMENT), edit(ObjectKind.EXPERIMENT),
+                createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
+                edit(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
+                createOrDelete(ObjectKind.VOCABULARY_TERM), edit(ObjectKind.VOCABULARY_TERM) };
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java
index 31ddd6c5c1d..d7edba1a04c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java
@@ -198,7 +198,7 @@ public final class SearchWidget extends LayoutContainer
         boolean onlyWildcard = true;
         for (final char c : queryText.toCharArray())
         {
-            if (c != '*' && c != '?')
+            if (c != '*' && c != '?' && c != '|') // '|||' is a delimiter in field global_search in index
             {
                 onlyWildcard = false;
                 break;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/MatchingEntitiesPanelColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/MatchingEntitiesPanelColumnIDs.java
index e3354f0e4a2..f5b5278be6a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/MatchingEntitiesPanelColumnIDs.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/MatchingEntitiesPanelColumnIDs.java
@@ -26,9 +26,15 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.MatchingEn
 public class MatchingEntitiesPanelColumnIDs
 {
     public static final String ENTITY_KIND = "ENTITY_KIND";
+
     public static final String ENTITY_TYPE = "ENTITY_TYPE";
+
     public static final String IDENTIFIER = "IDENTIFIER";
+
     public static final String REGISTRATOR = "REGISTRATOR";
-    public static final String MATCHING_FIELD = "MATCHING_FIELD";
-    public static final String MATCHING_TEXT = "MATCHING_TEXT";
+
+    public static final String MATCH = "MATCH";
+
+    public static final String RANK = "RANK";
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/MatchingEntitiesProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/MatchingEntitiesProvider.java
index d802dad3198..2e59f5df2d7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/MatchingEntitiesProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/MatchingEntitiesProvider.java
@@ -19,13 +19,14 @@ package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.ENTITY_KIND;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.ENTITY_TYPE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.IDENTIFIER;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.MATCHING_FIELD;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.MATCHING_TEXT;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.MATCH;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.RANK;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntitiesPanelColumnIDs.REGISTRATOR;
 
 import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
@@ -69,8 +70,9 @@ public class MatchingEntitiesProvider implements ITableModelProvider<MatchingEnt
         builder.addColumn(ENTITY_TYPE);
         builder.addColumn(IDENTIFIER).withDefaultWidth(140);
         builder.addColumn(REGISTRATOR);
-        builder.addColumn(MATCHING_FIELD).withDefaultWidth(140);
-        builder.addColumn(MATCHING_TEXT).withDefaultWidth(200);
+        builder.addColumn(MATCH).withDefaultWidth(200).withDataType(DataTypeCode.MULTILINE_VARCHAR);
+        builder.addColumn(RANK);
+        long rank = 1;
         for (MatchingEntity matchingEntity : entities)
         {
             builder.addRow(matchingEntity);
@@ -78,8 +80,9 @@ public class MatchingEntitiesProvider implements ITableModelProvider<MatchingEnt
             builder.column(ENTITY_TYPE).addString(matchingEntity.getEntityType().getCode());
             builder.column(IDENTIFIER).addString(matchingEntity.getIdentifier());
             builder.column(REGISTRATOR).addPerson(matchingEntity.getRegistrator());
-            builder.column(MATCHING_FIELD).addString(matchingEntity.getFieldDescription());
-            builder.column(MATCHING_TEXT).addString(matchingEntity.getTextFragment());
+            builder.column(MATCH).addMultilineValue(matchingEntity.getMatch());
+            builder.column(RANK).addInteger(rank);
+            rank++;
         }
         return builder.getModel();
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 4eddb96b3fd..15a389b0e4d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -249,7 +249,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 import ch.systemsx.cisd.openbis.generic.shared.util.RelationshipUtils;
 
-public final class CommonServer extends AbstractCommonServer<ICommonServerForInternalUse> implements
+public final class CommonServer extends AbstractCommonServer<ICommonServerForInternalUse>implements
         ICommonServerForInternalUse
 {
     private final LastModificationState lastModificationState;
@@ -401,7 +401,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Capability("UPDATE_SPACE")
     public void updateSpace(final String sessionToken,
             @AuthorizationGuard(guardClass = SpaceUpdatesPredicate.class)
-            final ISpaceUpdates updates)
+    final ISpaceUpdates updates)
     {
         assert sessionToken != null : "Unspecified session token";
         assert updates != null : "Unspecified updates";
@@ -431,8 +431,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_ADMIN)
     public void registerSpaceRole(String sessionToken, RoleCode roleCode,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            SpaceIdentifier spaceIdentifier, Grantee grantee)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) SpaceIdentifier spaceIdentifier, Grantee grantee)
     {
         final Session session = getSession(sessionToken);
 
@@ -467,8 +466,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_ADMIN)
     public void deleteSpaceRole(String sessionToken, RoleCode roleCode,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            SpaceIdentifier spaceIdentifier, Grantee grantee)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) SpaceIdentifier spaceIdentifier, Grantee grantee)
     {
         final Session session = getSession(sessionToken);
 
@@ -619,7 +617,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @ReturnValueFilter(validatorClass = SampleValidator.class)
     public List<Sample> listSamples(final String sessionToken,
             @AuthorizationGuard(guardClass = ListSampleCriteriaPredicate.class)
-            final ListSampleCriteria criteria)
+    final ListSampleCriteria criteria)
     {
         final Session session = getSession(sessionToken);
         final ISampleLister sampleLister = businessObjectFactory.createSampleLister(session);
@@ -660,7 +658,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @ReturnValueFilter(validatorClass = SampleValidator.class)
     public List<Sample> listSamplesOnBehalfOfUser(final String sessionToken,
             @AuthorizationGuard(guardClass = ListSampleCriteriaPredicate.class)
-            final ListSampleCriteria criteria, String userId)
+    final ListSampleCriteria criteria, String userId)
     {
         final Session session = getSession(sessionToken);
 
@@ -703,7 +701,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @ReturnValueFilter(validatorClass = ExternalDataValidator.class)
     public List<AbstractExternalData> listSampleExternalData(final String sessionToken,
             @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            final TechId sampleId, final boolean showOnlyDirectlyConnected)
+    final TechId sampleId, final boolean showOnlyDirectlyConnected)
     {
         final Session session = getSession(sessionToken);
         final IDatasetLister datasetLister = createDatasetLister(session);
@@ -718,7 +716,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @ReturnValueFilter(validatorClass = ExternalDataValidator.class)
     public List<AbstractExternalData> listExperimentExternalData(final String sessionToken,
             @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            final TechId experimentId, boolean showOnlyDirectlyConnected)
+    final TechId experimentId, boolean showOnlyDirectlyConnected)
     {
         final Session session = getSession(sessionToken);
         final IDatasetLister datasetLister = createDatasetLister(session);
@@ -762,7 +760,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @ReturnValueFilter(validatorClass = ExternalDataValidator.class)
     public List<AbstractExternalData> listDataSetRelationships(final String sessionToken,
             @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class)
-            final TechId datasetId, final DataSetRelationshipRole role)
+    final TechId datasetId, final DataSetRelationshipRole role)
     {
         final Session session = getSession(sessionToken);
         final IDatasetLister datasetLister = createDatasetLister(session);
@@ -910,6 +908,14 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
                             useWildcardSearchMode, list.size(), maxSize);
             list.addAll(entities);
         }
+        Collections.sort(list, new Comparator<MatchingEntity>()
+            {
+                @Override
+                public int compare(MatchingEntity o1, MatchingEntity o2)
+                {
+                    return new Double(o2.getScore()).compareTo(o1.getScore());
+                }
+            });
         return list;
     }
 
@@ -954,8 +960,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Experiment> listExperiments(final String sessionToken,
             ExperimentType experimentType,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            ProjectIdentifier projectIdentifier)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier)
     {
         List<ProjectIdentifier> projectIdentifiers = projectIdentifier != null ? Collections.singletonList(projectIdentifier) : null;
         return listExperiments(sessionToken, experimentType, null, projectIdentifiers, false, false);
@@ -965,8 +970,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Experiment> listExperiments(final String sessionToken,
             ExperimentType experimentType,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            List<ProjectIdentifier> projectIdentifiers)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) List<ProjectIdentifier> projectIdentifiers)
     {
         return listExperiments(sessionToken, experimentType, null, projectIdentifiers, false, false);
     }
@@ -975,8 +979,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Experiment> listExperimentsHavingSamples(final String sessionToken,
             ExperimentType experimentType,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            List<ProjectIdentifier> projectIdentifiers)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) List<ProjectIdentifier> projectIdentifiers)
     {
         return listExperiments(sessionToken, experimentType, null, projectIdentifiers, true, false);
     }
@@ -985,8 +988,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Experiment> listExperimentsHavingDataSets(final String sessionToken,
             ExperimentType experimentType,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            List<ProjectIdentifier> projectIdentifiers)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) List<ProjectIdentifier> projectIdentifiers)
     {
         return listExperiments(sessionToken, experimentType, null, projectIdentifiers, false, true);
     }
@@ -995,8 +997,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Experiment> listExperiments(final String sessionToken,
             ExperimentType experimentType,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            SpaceIdentifier spaceIdentifier)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) SpaceIdentifier spaceIdentifier)
     {
         return listExperiments(sessionToken, experimentType, spaceIdentifier, null, false, false);
     }
@@ -1004,8 +1005,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Experiment> listExperiments(final String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            List<ExperimentIdentifier> experimentIdentifiers)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) List<ExperimentIdentifier> experimentIdentifiers)
     {
         Session session = getSession(sessionToken);
         IExperimentTable experimentTable = businessObjectFactory.createExperimentTable(session);
@@ -1575,8 +1575,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("REGISTER_PROJECT")
     public void registerProject(String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            ProjectIdentifier projectIdentifier, String description, String leaderId,
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier, String description, String leaderId,
             Collection<NewAttachment> attachments)
     {
         final Session session = getSession(sessionToken);
@@ -1675,8 +1674,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AbstractExternalData getDataSetInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class)
-            TechId datasetId)
+            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class) TechId datasetId)
     {
         final Session session = getSession(sessionToken);
         final IDataBO datasetBO = businessObjectFactory.createDataBO(session);
@@ -1698,8 +1696,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("WRITE_DATASET")
     public DataSetUpdateResult updateDataSet(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetUpdatesPredicate.class)
-            DataSetUpdatesDTO updates)
+            @AuthorizationGuard(guardClass = DataSetUpdatesPredicate.class) DataSetUpdatesDTO updates)
     {
         final Session session = getSession(sessionToken);
         final IDataBO dataSetBO = businessObjectFactory.createDataBO(session);
@@ -2038,8 +2035,8 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_DATASET")
     public void deleteDataSets(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> dataSetCodes, String reason, DeletionType type, boolean isTrashEnabled)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> dataSetCodes, String reason, DeletionType type,
+            boolean isTrashEnabled)
     {
         deleteDataSetsCommon(sessionToken, dataSetCodes, reason, type, false, isTrashEnabled);
     }
@@ -2048,8 +2045,8 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.INSTANCE_DISABLED)
     @Capability("FORCE_DELETE_DATASET")
     public void deleteDataSetsForced(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> dataSetCodes, String reason, DeletionType type, boolean isTrashEnabled)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> dataSetCodes, String reason, DeletionType type,
+            boolean isTrashEnabled)
     {
         deleteDataSetsCommon(sessionToken, dataSetCodes, reason, type, true, isTrashEnabled);
     }
@@ -2100,8 +2097,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_SAMPLE")
     public void deleteSamples(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdCollectionPredicate.class)
-            List<TechId> sampleIds, String reason, DeletionType deletionType)
+            @AuthorizationGuard(guardClass = SampleTechIdCollectionPredicate.class) List<TechId> sampleIds, String reason, DeletionType deletionType)
     {
         Session session = getSession(sessionToken);
         switch (deletionType)
@@ -2125,8 +2121,8 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_EXPERIMENT")
     public void deleteExperiments(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdCollectionPredicate.class)
-            List<TechId> experimentIds, String reason, DeletionType deletionType)
+            @AuthorizationGuard(guardClass = ExperimentTechIdCollectionPredicate.class) List<TechId> experimentIds, String reason,
+            DeletionType deletionType)
     {
         Session session = getSession(sessionToken);
         IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
@@ -2176,8 +2172,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_PROJECT")
     public void deleteProjects(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectTechIdCollectionPredicate.class)
-            List<TechId> projectIds, String reason)
+            @AuthorizationGuard(guardClass = ProjectTechIdCollectionPredicate.class) List<TechId> projectIds, String reason)
     {
         Session session = getSession(sessionToken);
         IProjectBO projectBO = businessObjectFactory.createProjectBO(session);
@@ -2191,8 +2186,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_ADMIN)
     @Capability("DELETE_SPACE")
     public void deleteSpaces(String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceTechIdCollectionPredicate.class)
-            List<TechId> spaceIds, String reason)
+            @AuthorizationGuard(guardClass = SpaceTechIdCollectionPredicate.class) List<TechId> spaceIds, String reason)
     {
         Session session = getSession(sessionToken);
         ISpaceBO spaceBO = businessObjectFactory.createSpaceBO(session);
@@ -2239,8 +2233,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_EXPERIMENT_ATTACHMENT")
     public void deleteExperimentAttachments(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            TechId experimentId, List<String> fileNames, String reason)
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId, List<String> fileNames, String reason)
     {
         Session session = getSession(sessionToken);
         IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
@@ -2279,8 +2272,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_SAMPLE_ATTACHMENT")
     public void deleteSampleAttachments(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            TechId sampleId, List<String> fileNames, String reason)
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) TechId sampleId, List<String> fileNames, String reason)
     {
         Session session = getSession(sessionToken);
         ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
@@ -2292,8 +2284,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_PROJECT_ATTACHMENT")
     public void deleteProjectAttachments(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class)
-            TechId projectId, List<String> fileNames, String reason)
+            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId, List<String> fileNames, String reason)
     {
         Session session = getSession(sessionToken);
         IProjectBO projectBO = businessObjectFactory.createProjectBO(session);
@@ -2311,8 +2302,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Attachment> listExperimentAttachments(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            TechId experimentId)
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId)
     {
         Session session = getSession(sessionToken);
         IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
@@ -2325,8 +2315,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Attachment> listSampleAttachments(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            TechId sampleId)
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) TechId sampleId)
     {
         Session session = getSession(sessionToken);
         ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
@@ -2338,8 +2327,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<Attachment> listProjectAttachments(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class)
-            TechId projectId)
+            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId)
     {
         Session session = getSession(sessionToken);
         IProjectBO projectBO = businessObjectFactory.createProjectBO(session);
@@ -2406,7 +2394,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public SampleParentWithDerived getSampleInfo(final String sessionToken,
             @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            final TechId sampleId) throws UserFailureException
+    final TechId sampleId) throws UserFailureException
     {
         assert sessionToken != null : "Unspecified session token.";
         assert sampleId != null : "Unspecified sample techId.";
@@ -2422,15 +2410,15 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
                         session.tryGetPerson(), sample);
         return SampleTranslator.translate(getSampleTypeSlaveServerPlugin(sample.getSampleType())
                 .getSampleInfo(session, sample), session.getBaseIndexURL(), MetaprojectTranslator
-                .translate(metaprojectPEs), managedPropertyEvaluatorFactory);
+                        .translate(metaprojectPEs),
+                managedPropertyEvaluatorFactory);
     }
 
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @Capability("WRITE_SAMPLE")
     public SampleUpdateResult updateSample(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleUpdatesPredicate.class)
-            SampleUpdatesDTO updates)
+            @AuthorizationGuard(guardClass = SampleUpdatesPredicate.class) SampleUpdatesDTO updates)
     {
         final Session session = getSession(sessionToken);
         final ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
@@ -2448,8 +2436,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public Experiment getExperimentInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            ExperimentIdentifier identifier)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ExperimentIdentifier identifier)
     {
         final Session session = getSession(sessionToken);
         final IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
@@ -2476,8 +2463,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public Experiment getExperimentInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            TechId experimentId)
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId)
     {
         final Session session = getSession(sessionToken);
         final IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
@@ -2500,8 +2486,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
     public ExperimentUpdateResult updateExperiment(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentUpdatesPredicate.class)
-            ExperimentUpdatesDTO updates)
+            @AuthorizationGuard(guardClass = ExperimentUpdatesPredicate.class) ExperimentUpdatesDTO updates)
     {
         final Session session = getSession(sessionToken);
         final IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
@@ -2517,8 +2502,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public Project getProjectInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class)
-            TechId projectId)
+            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId)
     {
         final Session session = getSession(sessionToken);
         final IProjectBO bo = businessObjectFactory.createProjectBO(session);
@@ -2531,8 +2515,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public Project getProjectInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class)
-            ProjectIdentifier projectIdentifier)
+            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier)
     {
         final Session session = getSession(sessionToken);
         final IProjectBO bo = businessObjectFactory.createProjectBO(session);
@@ -2668,8 +2651,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("WRITE_PROJECT")
     public int updateProject(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectUpdatesPredicate.class)
-            ProjectUpdatesDTO updates)
+            @AuthorizationGuard(guardClass = ProjectUpdatesPredicate.class) ProjectUpdatesDTO updates)
     {
         final Session session = getSession(sessionToken);
         final IProjectBO bo = businessObjectFactory.createProjectBO(session);
@@ -2780,7 +2762,8 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
                                 "[%s]\n%s%s\n",
                                 entityType.getCode(),
                                 firstSection ? "# Comments must be located after the type declaration ('[TYPE]').\n"
-                                        : "", section);
+                                        : "",
+                                section);
             }
             sb.append(section);
             firstSection = false;
@@ -3051,8 +3034,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public TableModel createReportFromDatasets(String sessionToken,
             DatastoreServiceDescription serviceDescription,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes)
     {
         Session session = getSession(sessionToken);
         IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
@@ -3063,8 +3045,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public TableModel createReportFromDatasets(String sessionToken, String serviceKey,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes)
     {
         Session session = getSession(sessionToken);
         IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
@@ -3086,8 +3067,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     public void processDatasets(String sessionToken,
             DatastoreServiceDescription serviceDescription,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes)
     {
         Session session = getSession(sessionToken);
         IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
@@ -3099,8 +3079,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("ARCHIVE_DATASET")
     public int archiveDatasets(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes, boolean removeFromDataStore)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes, boolean removeFromDataStore)
     {
         return super.archiveDatasets(sessionToken, datasetCodes, removeFromDataStore);
     }
@@ -3109,8 +3088,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @Capability("UNARCHIVE_DATASET")
     public int unarchiveDatasets(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes)
     {
         return super.unarchiveDatasets(sessionToken, datasetCodes);
     }
@@ -3349,8 +3327,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_FILTER")
     public void deleteFilters(String sessionToken,
-            @AuthorizationGuard(guardClass = DeleteGridCustomFilterPredicate.class)
-            List<TechId> filterIds)
+            @AuthorizationGuard(guardClass = DeleteGridCustomFilterPredicate.class) List<TechId> filterIds)
     {
         IGridCustomFilterOrColumnBO bo = createGridCustomFilterBO(sessionToken);
         deleteFiltersOrColumns(filterIds, bo);
@@ -3360,8 +3337,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("WRITE_FILTER")
     public void updateFilter(String sessionToken,
-            @AuthorizationGuard(guardClass = UpdateGridCustomFilterPredicate.class)
-            IExpressionUpdates updates)
+            @AuthorizationGuard(guardClass = UpdateGridCustomFilterPredicate.class) IExpressionUpdates updates)
     {
         assert updates != null : "Unspecified updates";
         createGridCustomFilterBO(sessionToken).update(updates);
@@ -3382,8 +3358,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("DELETE_CUSTOM_COLUMN")
     public void deleteGridCustomColumns(String sessionToken,
-            @AuthorizationGuard(guardClass = DeleteGridCustomColumnPredicate.class)
-            List<TechId> columnIds)
+            @AuthorizationGuard(guardClass = DeleteGridCustomColumnPredicate.class) List<TechId> columnIds)
     {
         IGridCustomFilterOrColumnBO bo = createGridCustomColumnBO(sessionToken);
         deleteFiltersOrColumns(columnIds, bo);
@@ -3393,8 +3368,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @Capability("WRITE_CUSTOM_COLUMN")
     public void updateGridCustomColumn(String sessionToken,
-            @AuthorizationGuard(guardClass = UpdateGridCustomColumnPredicate.class)
-            IExpressionUpdates updates)
+            @AuthorizationGuard(guardClass = UpdateGridCustomColumnPredicate.class) IExpressionUpdates updates)
     {
         assert updates != null : "Unspecified updates";
         createGridCustomColumnBO(sessionToken).update(updates);
@@ -3435,8 +3409,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_ADMIN)
     public int lockDatasets(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes)
     {
         Session session = getSession(sessionToken);
         IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
@@ -3447,8 +3420,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_ADMIN)
     public int unlockDatasets(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class)
-            List<String> datasetCodes)
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes)
     {
         Session session = getSession(sessionToken);
         IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
@@ -3460,8 +3432,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public LinkModel retrieveLinkFromDataSet(String sessionToken,
             DatastoreServiceDescription serviceDescription,
-            @AuthorizationGuard(guardClass = DataSetCodePredicate.class)
-            String dataSetCode)
+            @AuthorizationGuard(guardClass = DataSetCodePredicate.class) String dataSetCode)
     {
         Session session = getSession(sessionToken);
         IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
@@ -3566,8 +3537,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public IEntityInformationHolderWithPermId getEntityInformationHolder(String sessionToken,
-            @AuthorizationGuard(guardClass = BasicEntityDescriptionPredicate.class)
-            BasicEntityDescription info)
+            @AuthorizationGuard(guardClass = BasicEntityDescriptionPredicate.class) BasicEntityDescription info)
     {
         Session session = getSession(sessionToken);
         IEntityInformationWithPropertiesHolder entity = getEntity(info, session);
@@ -3784,8 +3754,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @Capability("WRITE_DATASET_PROPERTIES")
     public void updateDataSetProperties(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class)
-            TechId entityId, List<PropertyUpdates> modifiedProperties)
+            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class) TechId entityId, List<PropertyUpdates> modifiedProperties)
     {
         checkSession(sessionToken);
         AbstractExternalData dataSet = getDataSetInfo(sessionToken, entityId);
@@ -3823,8 +3792,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @Capability("WRITE_EXPERIMENT_PROPERTIES")
     public void updateExperimentProperties(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            TechId entityId, List<PropertyUpdates> modifiedProperties)
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId entityId, List<PropertyUpdates> modifiedProperties)
     {
         checkSession(sessionToken);
         Experiment experiment = getExperimentInfo(sessionToken, entityId);
@@ -3849,8 +3817,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @Capability("WRITE_SAMPLE_PROPERTIES")
     public void updateSampleProperties(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            TechId entityId, List<PropertyUpdates> modifiedProperties)
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) TechId entityId, List<PropertyUpdates> modifiedProperties)
     {
         checkSession(sessionToken);
         Map<String, String> properties = createPropertiesMap(modifiedProperties);
@@ -3915,7 +3882,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Capability("RESTORE")
     public void revertDeletions(final String sessionToken,
             @AuthorizationGuard(guardClass = RevertDeletionPredicate.class)
-            final List<TechId> deletionIds)
+    final List<TechId> deletionIds)
     {
         final Session session = getSession(sessionToken);
 
@@ -3969,7 +3936,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Capability("PURGE")
     public void deletePermanently(final String sessionToken,
             @AuthorizationGuard(guardClass = DeletionTechIdCollectionPredicate.class)
-            final List<TechId> deletionIds)
+    final List<TechId> deletionIds)
     {
         deletePermanentlyCommon(sessionToken, deletionIds, false);
     }
@@ -3979,7 +3946,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @Capability("FORCE_PURGE")
     public void deletePermanentlyForced(final String sessionToken,
             @AuthorizationGuard(guardClass = DeletionTechIdCollectionPredicate.class)
-            final List<TechId> deletionIds)
+    final List<TechId> deletionIds)
     {
         deletePermanentlyCommon(sessionToken, deletionIds, true);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAO.java
index 62db41c5eaa..ee2cc96e765 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAO.java
@@ -26,6 +26,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
@@ -338,10 +340,13 @@ final class HibernateSearchDAO extends HibernateDaoSupport implements IHibernate
 
                     String[] fields = headerField.stringValue().split(splitString);
                     String[] content = dataField.stringValue().split(splitString);
-                    String[] metaprojects = metaprojectField.stringValue().split(" ");
+                    String[] metaprojects = new String[0];
 
-                    String matchingField = "unknown";
-                    String matchingText = "";
+                    String mpfs = metaprojectField.stringValue();
+                    if (mpfs.trim().length() > 0)
+                    {
+                        metaprojects = metaprojectField.stringValue().split(" ");
+                    }
 
                     List<String> query = new ArrayList<>();
                     if (useWildcardSearchMode)
@@ -361,62 +366,144 @@ final class HibernateSearchDAO extends HibernateDaoSupport implements IHibernate
                         }
                     }
 
-                    List<MatchingEntity> result = new ArrayList<>();
+                    Map<String, String> matchingFields = new HashMap<>();
+                    double score = 0.0;
 
                     for (int i = 0; i < content.length; i++)
                     {
                         for (String q : query)
                         {
+                            double currentScore = score;
+
                             if (useWildcardSearchMode)
                             {
-                                if (content[i].toLowerCase().matches("(?s).*" + q.toLowerCase().replace("*", ".*").replace("?", ".?") + ".*"))
+                                Pattern pattern = Pattern.compile("(?s)" + q.toLowerCase().replace("*", ".*").replace("?", ".?"));
+                                Matcher matcher = pattern.matcher(content[i].toLowerCase());
+
+                                while (matcher.find())
                                 {
-                                    matchingField = (fields.length == content.length) ? fields[i] : "Unknown";
-                                    matchingText = content[i];
-                                    MatchingEntity me = createMatchingEntity(((Document) tuple[1]), matchingText);
-                                    me.setFieldDescription(matchingField);
-                                    result.add(me);
+                                    int start = matcher.start();
+                                    int end = matcher.end();
+                                    score += getScore(content[i].toLowerCase(), start, end, fields[i], useWildcardSearchMode);
                                 }
                             } else
                             {
-                                if (content[i].toLowerCase().contains(q.toLowerCase()))
+                                String rest = content[i].toLowerCase();
+                                while (rest.length() > 0)
                                 {
-                                    matchingField = (fields.length == content.length) ? fields[i] : "Unknown";
-                                    matchingText = content[i];
-                                    MatchingEntity me = createMatchingEntity(((Document) tuple[1]), matchingText);
-                                    me.setFieldDescription(matchingField);
-                                    result.add(me);
+                                    int start = rest.indexOf(q.toLowerCase());
+                                    if (start == -1)
+                                    {
+                                        rest = "";
+                                    } else
+                                    {
+                                        int end = start + q.length();
+                                        rest = rest.substring(end);
+                                        score += getScore(content[i].toLowerCase(), start, end, fields[i], useWildcardSearchMode);
+                                    }
                                 }
                             }
+
+                            if (score > currentScore)
+                            {
+                                matchingFields.put(fields[i], content[i]);
+                            }
                         }
                     }
 
+                    Set<String> matchingMetaprojects = new HashSet<>();
                     for (int i = 0; i < metaprojects.length; i++)
                     {
+                        String mp = metaprojects[i].substring(1);
+                        String user = mp.substring(0, mp.indexOf("/"));
+                        if (!user.equals(userId))
+                        {
+                            continue;
+                        }
+
                         String value = metaprojects[i].substring(metaprojects[i].lastIndexOf("/") + 1);
                         for (String q : query)
                         {
                             if (useWildcardSearchMode)
                             {
-                                if (value.toLowerCase().matches(".*" + q.toLowerCase().replace("*", ".*").replace("?", ".?") + ".*"))
+                                Pattern pattern = Pattern.compile(q.toLowerCase().replace("*", ".*").replace("?", ".?"));
+                                Matcher matcher = pattern.matcher(value.toLowerCase());
+
+                                while (matcher.find())
                                 {
-                                    MatchingEntity me = createMatchingEntity(((Document) tuple[1]), value);
-                                    me.setFieldDescription("Tag");
-                                    result.add(me);
+                                    matchingMetaprojects.add(value);
+                                    int start = matcher.start();
+                                    int end = matcher.end();
+                                    score += getScore(value, start, end, "Tag", useWildcardSearchMode) * 5;
                                 }
                             } else
                             {
-                                if (value.toLowerCase().contains(q.toLowerCase()))
+                                String rest = value.toLowerCase();
+                                while (rest.length() > 0)
                                 {
-                                    MatchingEntity me = createMatchingEntity(((Document) tuple[1]), value);
-                                    me.setFieldDescription("Tag");
-                                    result.add(me);
+                                    int start = rest.indexOf(q.toLowerCase());
+                                    if (start == -1)
+                                    {
+                                        rest = "";
+                                    } else
+                                    {
+                                        matchingMetaprojects.add(value);
+                                        int end = start + q.length();
+                                        rest = rest.substring(end);
+                                        score += getScore(value, start, end, "Tag", useWildcardSearchMode) * 5;
+                                    }
                                 }
                             }
                         }
                     }
 
-                    return result;
+                    if (matchingMetaprojects.size() > 0)
+                    {
+                        List<String> mps = new ArrayList<>(matchingMetaprojects);
+                        Collections.sort(mps);
+                        matchingFields.put("Tags", StringUtils.join(mps, ","));
+                    }
+
+                    if (matchingFields.containsKey("Code") ||
+                            matchingFields.containsKey("Project code") ||
+                            matchingFields.containsKey("Space code"))
+                    {
+                        matchingFields.remove("Identifier");
+                    }
+
+                    List<String> keys = new ArrayList<String>(matchingFields.keySet());
+                    Collections.sort(keys);
+
+                    String text = "";
+                    for (String key : keys)
+                    {
+                        text = text + key + ": " + matchingFields.get(key) + "\n";
+                    }
+
+                    return createMatchingEntity((Document) tuple[1], text, score);
+                }
+
+                private double getScore(String text, int start, int end, String field, boolean wildcard)
+                {
+                    boolean fullmatch = (start == 0 || !StringUtils.isAlphanumeric(text.substring(start - 1, start))) &&
+                            (end == text.length() || !StringUtils.isAlphanumeric(text.substring(end, end + 1))) &&
+                            !wildcard; // full/partial matching not relevant for wildcard mode
+                    if (field.equals("Perm ID") || field.equals("Identifier") || field.equals("Code"))
+                    {
+                        if (fullmatch)
+                        {
+                            return 200;
+                        } else
+                        {
+                            return 100;
+                        }
+                    } else if (fullmatch)
+                    {
+                        return 10;
+                    } else
+                    {
+                        return 1;
+                    }
                 }
 
                 @Override
@@ -430,13 +517,13 @@ final class HibernateSearchDAO extends HibernateDaoSupport implements IHibernate
                     return result;
                 }
 
-                private MatchingEntity createMatchingEntity(final Document doc, final String matchingText)
+                private MatchingEntity createMatchingEntity(final Document doc, final String matchingText, double score)
                 {
                     final MatchingEntity result = new MatchingEntity();
 
                     // search properties
-                    result.setFieldDescription(fieldName);
-                    result.setTextFragment(matchingText);
+                    result.setMatch(matchingText);
+                    result.setScore(score);
 
                     // IIdentifiable properties
                     // NOTE: for contained sample this code is full code with container code part
@@ -512,29 +599,11 @@ final class HibernateSearchDAO extends HibernateDaoSupport implements IHibernate
             });
 
         List<?> list = hibernateQuery.list();
-        final List<List<MatchingEntity>> nestedResult = AbstractDAO.cast(list);
-        List<MatchingEntity> result = new ArrayList<>();
-        for (List<MatchingEntity> entities : nestedResult)
-        {
-            result.addAll(entities);
-        }
+        List<MatchingEntity> result = AbstractDAO.cast(list);
 
         return filterNulls(result);
     }
 
-    // we need this for higlighter when wildcards are used
-    private static Query rewriteQuery(IndexReader indexReader, Query query)
-    {
-        try
-        {
-            return query.rewrite(indexReader);
-        } catch (IOException ex)
-        {
-            logSearchHighlightingError(ex);
-            return query;
-        }
-    }
-
     // detailed search
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MatchingEntity.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MatchingEntity.java
index 2b44c60693a..034ec9e9d23 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MatchingEntity.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MatchingEntity.java
@@ -22,8 +22,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWit
 import ch.systemsx.cisd.openbis.generic.shared.basic.IRegistratorHolder;
 
 /**
- * An entity that matches the <i>Hibernate Search</i> query and which has been returned by the
- * server.
+ * An entity that matches the <i>Hibernate Search</i> query and which has been returned by the server.
  * 
  * @author Christian Ribeaud
  */
@@ -48,9 +47,9 @@ public final class MatchingEntity implements Serializable, IEntityInformationHol
 
     private Space spaceOrNull;
 
-    private String fieldDescription;
+    private String match;
 
-    private String textFragment;
+    private double score;
 
     @Override
     public final EntityKind getEntityKind()
@@ -95,26 +94,6 @@ public final class MatchingEntity implements Serializable, IEntityInformationHol
         this.spaceOrNull = spaceOrNull;
     }
 
-    public String getFieldDescription()
-    {
-        return fieldDescription;
-    }
-
-    public void setFieldDescription(String fieldDescription)
-    {
-        this.fieldDescription = fieldDescription;
-    }
-
-    public String getTextFragment()
-    {
-        return textFragment;
-    }
-
-    public void setTextFragment(String textFragment)
-    {
-        this.textFragment = textFragment;
-    }
-
     public final String getIdentifier()
     {
         return identifier;
@@ -207,4 +186,23 @@ public final class MatchingEntity implements Serializable, IEntityInformationHol
         return getIdentifier();
     }
 
+    public String getMatch()
+    {
+        return match;
+    }
+
+    public void setMatch(String match)
+    {
+        this.match = match;
+    }
+
+    public double getScore()
+    {
+        return score;
+    }
+
+    public void setScore(double score)
+    {
+        this.score = score;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentGlobalSearchBridge.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentGlobalSearchBridge.java
index 69cc8e5496d..71c51d7534e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentGlobalSearchBridge.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentGlobalSearchBridge.java
@@ -11,8 +11,8 @@ public class ExperimentGlobalSearchBridge extends GlobalSearchBridge<ExperimentP
         Map<String, String> values = new HashMap<>();
 
         values.put("Perm ID", experiment.getPermId());
-        values.put("Identifier", experiment.getIdentifier());
         values.put("Code", experiment.getCode());
+        values.put("Identifier", experiment.getIdentifier());
         values.put("Registration date", dateFormat.format(experiment.getRegistrationDate()));
         values.put("Modification date", dateFormat.format(experiment.getModificationDate()));
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GlobalSearchBridge.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GlobalSearchBridge.java
index 21421169db8..c6a8db15181 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GlobalSearchBridge.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GlobalSearchBridge.java
@@ -73,11 +73,9 @@ public abstract class GlobalSearchBridge<T extends IEntityWithMetaprojects> impl
         if (person != null)
         {
             values.put("User id of " + role, person.getUserId());
-            values.put("First name of " + role, person.getFirstName());
-            values.put("Last name of " + role, person.getLastName());
+            values.put("Name of " + role, person.getLastName() + ", " + person.getFirstName());
             values.put("Email of " + role, person.getEmail());
         }
-
     }
 
     @Override
@@ -93,8 +91,17 @@ public abstract class GlobalSearchBridge<T extends IEntityWithMetaprojects> impl
             List<String> values = new ArrayList<>();
             for (Map.Entry<String, String> entry : data.entrySet())
             {
+                if (entry.getValue() == null)
+                {
+                    continue;
+                }
                 keys.add(entry.getKey());
-                values.add(entry.getValue());
+                String val = entry.getValue();
+                while (val.indexOf(" ||| ") != -1)
+                {
+                    val = val.replace(" ||| ", " \\|\\|\\| ");
+                }
+                values.add(val);
             }
 
             String indexedValue = StringUtils.joinList(values, " ||| ");
@@ -144,7 +151,7 @@ public abstract class GlobalSearchBridge<T extends IEntityWithMetaprojects> impl
 
         } catch (Exception e)
         {
-            e.printStackTrace(); // WHAT SHOULD BE DONE HERE?!
+            e.printStackTrace();
         }
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleGlobalSearchBridge.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleGlobalSearchBridge.java
index 46cb585f051..a811c7669b0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleGlobalSearchBridge.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleGlobalSearchBridge.java
@@ -11,11 +11,10 @@ public class SampleGlobalSearchBridge extends GlobalSearchBridge<SamplePE>
         Map<String, String> values = new HashMap<>();
 
         values.put("Perm ID", sample.getPermId());
-        values.put("Identifier", sample.getIdentifier());
         values.put("Code", sample.getCode());
+        values.put("Identifier", sample.getIdentifier());
         values.put("Registration date", dateFormat.format(sample.getRegistrationDate()));
         values.put("Modification date", dateFormat.format(sample.getModificationDate()));
-
         values.put("Sample type", sample.getSampleType().getCode());
 
         if (sample.getExperiment() != null)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java
index d2f6966d3d4..8c7f5f8eed5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java
@@ -84,6 +84,11 @@ public interface IColumn
      */
     public void addString(String valueOrNull);
 
+    /**
+     * Adds a multiline string value to the column.
+     */
+    public void addMultilineValue(String valueOrNull);
+
     /**
      * Adds an integer value to the column.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java
index 111d2391d8d..db1d64f6cdc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java
@@ -423,6 +423,15 @@ public class TypedTableModelBuilder<T extends Serializable>
             addValue(value);
         }
 
+        @Override
+        public void addMultilineValue(String valueOrNull)
+        {
+            setDataType(DataTypeCode.MULTILINE_VARCHAR);
+            StringTableCell value =
+                    valueOrNull == null ? EMPTY_CELL : new StringTableCell(valueOrNull);
+            addValue(value);
+        }
+
         @Override
         public void addInteger(Long valueOrNull)
         {
@@ -580,8 +589,7 @@ public class TypedTableModelBuilder<T extends Serializable>
     /**
      * Adds a column with specified id.
      * 
-     * @return an {@link IColumnMetaData} instance which allows to set title, default width, and/or
-     *         data type.
+     * @return an {@link IColumnMetaData} instance which allows to set title, default width, and/or data type.
      * @throws IllegalArgumentException if a column with specified is has already been added.
      */
     public IColumnMetaData addColumn(String id)
@@ -595,8 +603,7 @@ public class TypedTableModelBuilder<T extends Serializable>
     }
 
     /**
-     * Adds a row with optional row object. This method has to be called before adding values to
-     * columns.
+     * Adds a row with optional row object. This method has to be called before adding values to columns.
      */
     public void addRow(T objectOrNull)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index b1ab502d902..b3c36d0d9b0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -278,8 +278,8 @@ var common = {
   no_match: "No results found for '{0}'.<br><br><br>Note, that you are {1} using wildcard search mode. Try to turn it {2} in your user settings.",
   entity_type: "Entity Type",
   entity_kind: "Entity Kind",
-  matching_text: "Matching Text",
-  matching_field: "Matching Field",
+  match: "Match",
+  rank: "Rank",
   too_generic: "Query string '{0}' is too generic.",
   show_related_datasets: "Show Related Data Sets",
   show_related_datasets_message: "Select between showing Data Sets related to selected ({0}) entities or to all entities from the table and click on OK button.",
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAOTest.java
index 3ddf7b0343c..2ca6abbebe2 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/HibernateSearchDAOTest.java
@@ -132,9 +132,9 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
         {
             assertEquals(lastName, matchingEntity.getRegistrator().getFirstName());
 
-            String fieldDescription = matchingEntity.getFieldDescription();
-            if (fieldDescription.contains("First name of registrator") == false
-                    && fieldDescription.contains("First name of modifier") == false)
+            String fieldDescription = matchingEntity.getMatch();
+            if (fieldDescription.contains("Name of registrator") == false
+                    && fieldDescription.contains("Name of modifier") == false)
             {
                 fail("Field description '" + fieldDescription + "' neither contains 'First name of registrator' " +
                         "nor 'First name of modifier'.");
@@ -162,7 +162,7 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
         for (MatchingEntity matchingEntity : hits)
         {
             AssertionUtil.assertContainsInsensitive(querySubstring, matchingEntity.getCode());
-            assertEquals("code", matchingEntity.getFieldDescription());
+            assertEquals("Code", matchingEntity.getMatch().substring(0, matchingEntity.getMatch().indexOf(":")));
         }
     }
 
-- 
GitLab