From 65a296bcd3010ded925b1b4724e7f9c4aad47f27 Mon Sep 17 00:00:00 2001
From: Viktor Kovtun <viktor.kovtun@id.ethz.ch>
Date: Thu, 15 Oct 2020 15:57:35 +0200
Subject: [PATCH] SSDM-10317 Added search by material support to full text
 search.

---
 .../search/planner/GlobalSearchManager.java   |  6 +++
 .../GlobalSearchCriteriaTranslator.java       | 43 ++++++++++++++++---
 .../systemtest/asapi/v3/GlobalSearchTest.java | 26 ++++++++++-
 3 files changed, 67 insertions(+), 8 deletions(-)

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 11110cd7c9d..5d6ed435e47 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
@@ -310,6 +310,12 @@ public class GlobalSearchManager implements IGlobalSearchManager
             addPropertyMatch(cvCodeMatch, fieldsMap, matches);
         }
 
+        final String materialMatch = (String) fieldsMap.get(MATERIAL_MATCH_ALIAS);
+        if (materialMatch != null)
+        {
+            addPropertyMatch(materialMatch, fieldsMap, matches);
+        }
+
         final String sampleMatch = (String) fieldsMap.get(SAMPLE_MATCH_ALIAS);
         if (sampleMatch != null)
         {
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
index ca9c4d046a8..929eb3e8fdd 100644
--- 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
@@ -48,6 +48,8 @@ public class GlobalSearchCriteriaTranslator
 
     public static final String SAMPLE_IDENTIFIER_MATCH_ALIAS = "sample_identifier_match";
 
+    public static final String MATERIAL_MATCH_ALIAS = "material_match";
+
     public static final String SAMPLE_MATCH_ALIAS = "sample_match";
 
     public static final String ENTITY_TYPES_CODE_ALIAS = "enty_code";
@@ -88,6 +90,8 @@ public class GlobalSearchCriteriaTranslator
 
     private static final String SAMPLES_TABLE_ALIAS = "samp";
 
+    private static final String MATERIALS_TABLE_ALIAS = "mat";
+
     private static final String SPACE_TABLE_ALIAS = "space";
 
     private static final String PROJECT_TABLE_ALIAS = "proj";
@@ -257,6 +261,8 @@ public class GlobalSearchCriteriaTranslator
                 sqlBuilder.append(SP).append(SAMPLE_IDENTIFIER_MATCH_ALIAS).append(COMMA).append(NL);
             }
 
+            sqlBuilder.append(NULL).append(SP).append(MATERIAL_MATCH_ALIAS).append(COMMA).append(NL);
+
             if (tableMapper == SAMPLE || tableMapper == EXPERIMENT || tableMapper == DATA_SET)
             {
                 sqlBuilder.append(NULL).append(SP).append(SAMPLE_MATCH_ALIAS).append(COMMA).append(NL);
@@ -306,6 +312,9 @@ public class GlobalSearchCriteriaTranslator
                 sqlBuilder.append(NULL).append(SP).append(SAMPLE_IDENTIFIER_MATCH_ALIAS).append(COMMA).append(NL);
             }
 
+            buildMaterialMatch(sqlBuilder, criterionValues, args);
+            sqlBuilder.append(COMMA).append(NL);
+
             if (tableMapper == SAMPLE || tableMapper == EXPERIMENT || tableMapper == DATA_SET)
             {
                 buildSampleMatch(sqlBuilder, criterionValues, args);
@@ -362,20 +371,29 @@ public class GlobalSearchCriteriaTranslator
             final List<Object> args)
     {
         sqlBuilder.append(CASE).append(NL);
-        appendWhenThen(sqlBuilder, PERM_ID_COLUMN, values, args);
-        appendWhenThen(sqlBuilder, CODE_COLUMN, values, args);
-        appendWhenThen(sqlBuilder, SAMPLE_IDENTIFIER_COLUMN, values, args);
+        appendWhenThen(sqlBuilder, SAMPLES_TABLE_ALIAS, PERM_ID_COLUMN, values, args);
+        appendWhenThen(sqlBuilder, SAMPLES_TABLE_ALIAS, CODE_COLUMN, values, args);
+        appendWhenThen(sqlBuilder, SAMPLES_TABLE_ALIAS, SAMPLE_IDENTIFIER_COLUMN, values, args);
         sqlBuilder.append('\t').append(ELSE).append(SP).append(NULL).append(NL);
         sqlBuilder.append(END).append(SP).append(SAMPLE_MATCH_ALIAS);
     }
 
-    private static void appendWhenThen(final StringBuilder sqlBuilder, final String column, final String[] values,
+    private static void buildMaterialMatch(final StringBuilder sqlBuilder, final String[] values,
             final List<Object> args)
+    {
+        sqlBuilder.append(CASE).append(NL);
+        appendWhenThen(sqlBuilder, MATERIALS_TABLE_ALIAS, CODE_COLUMN, values, args);
+        sqlBuilder.append('\t').append(ELSE).append(SP).append(NULL).append(NL);
+        sqlBuilder.append(END).append(SP).append(MATERIAL_MATCH_ALIAS);
+    }
+
+    private static void appendWhenThen(final StringBuilder sqlBuilder, final String tableAlias, final String column,
+            final String[] values, final List<Object> args)
     {
         sqlBuilder.append('\t').append(WHEN).append(SP).append(LOWER).append(LP)
-                .append(SAMPLES_TABLE_ALIAS).append(PERIOD).append(column).append(RP).append(SP).append(IN).append(SP)
-                .append(SELECT_UNNEST)
-                .append(THEN).append(SP).append(SAMPLES_TABLE_ALIAS).append(PERIOD).append(column).append(NL);
+                .append(tableAlias).append(PERIOD).append(column).append(RP).append(SP).append(IN).append(SP)
+                .append(SELECT_UNNEST).append(SP)
+                .append(THEN).append(SP).append(tableAlias).append(PERIOD).append(column).append(NL);
         args.add(values);
     }
 
@@ -604,6 +622,11 @@ public class GlobalSearchCriteriaTranslator
                     .append(VOCABULARY_TERM_COLUMN).append(SP).append(EQ).append(SP).append(CONTROLLED_VOCABULARY_TERMS_TABLE_ALIAS).append(PERIOD)
                     .append(ID_COLUMN).append(NL);
 
+            sqlBuilder.append(LEFT_JOIN).append(SP).append(MATERIAL.getEntitiesTable()).append(SP)
+                    .append(MATERIALS_TABLE_ALIAS).append(SP).append(ON).append(SP).append(PROPERTIES_TABLE_ALIAS)
+                    .append(PERIOD).append(MATERIAL_PROP_COLUMN).append(SP).append(EQ).append(SP)
+                    .append(MATERIALS_TABLE_ALIAS).append(PERIOD).append(ID_COLUMN).append(NL);
+
             if (tableMapper == TableMapper.SAMPLE || tableMapper == TableMapper.EXPERIMENT
                     || tableMapper == TableMapper.DATA_SET)
             {
@@ -691,6 +714,12 @@ public class GlobalSearchCriteriaTranslator
                 .append(DOUBLE_AT).append(SP);
         buildTsQueryPart(sqlBuilder, stringValue, args);
 
+        sqlBuilder.append(SP).append(OR).append(SP);
+
+        sqlBuilder.append(MATERIALS_TABLE_ALIAS).append(PERIOD).append(TS_VECTOR_COLUMN).append(SP)
+                .append(DOUBLE_AT).append(SP).append(QU).append(DOUBLE_COLON).append(TSQUERY);
+        args.add(toTsQueryText(stringValue));
+
         if (tableMapper == TableMapper.SAMPLE || tableMapper == TableMapper.EXPERIMENT
                 || tableMapper == TableMapper.DATA_SET)
         {
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GlobalSearchTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GlobalSearchTest.java
index 213706a84ad..3c23fb623e3 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GlobalSearchTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GlobalSearchTest.java
@@ -1153,7 +1153,31 @@ public class GlobalSearchTest extends AbstractTest
         }
     }
 
-    public List<GlobalSearchObject> filterSearchResults(final List<GlobalSearchObject> results,
+    @Test
+    public void testSearchMatchingMaterialProperty()
+    {
+        final GlobalSearchCriteria criteria = new GlobalSearchCriteria();
+        criteria.withText().thatContains("BACTERIUM-Y");
+
+        final GlobalSearchObjectFetchOptions fo = new GlobalSearchObjectFetchOptions();
+        fo.sortBy().objectPermId().asc();
+        fo.withMatch();
+
+        final SearchResult<GlobalSearchObject> result = search(TEST_USER, criteria, fo);
+        final List<GlobalSearchObject> objects = result.getObjects();
+
+        assertEquals(result.getTotalCount(), 4);
+        assertEquals(objects.size(), 4);
+
+        assertSample(objects.get(0), "200902091250077-1026", "/CISD/CP-TEST-2", "Property 'bacterium': BACTERIUM-Y");
+        assertSample(objects.get(1), "200902091250077-1051", "/CISD/PLATE_WELLSEARCH:WELL-A01",
+                "Property 'bacterium': BACTERIUM-Y");
+        assertExperiment(objects.get(2), "201108050937246-1031", "/CISD/DEFAULT/EXP-Y",
+                "Property 'any_material': BACTERIUM-Y");
+        assertMaterial(objects.get(3), "BACTERIUM-Y", "BACTERIUM", "Identifier: BACTERIUM-Y (BACTERIUM)");
+    }
+
+    private List<GlobalSearchObject> filterSearchResults(final List<GlobalSearchObject> results,
             final boolean withDataset, final boolean withSample, final boolean withExperiment)
     {
         return results.stream().filter(globalSearchObject ->
-- 
GitLab