From 2183d3d65389cd0c0c8fb000eedc2dd8f07729d1 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Mon, 21 Mar 2011 14:09:42 +0000
Subject: [PATCH] [LMS-2148] search for container

SVN: 20423
---
 ...riaToDetailedSearchCriteriaTranslator.java | 18 +++--
 .../business/DetailedSearchManager.java       | 23 ++++---
 .../search/detailed/IndexFieldNameHelper.java | 15 ++--
 .../shared/api/v1/dto/SearchSubCriteria.java  | 10 +++
 .../DetailedSearchAssociationCriteria.java    |  6 +-
 .../basic/dto/DetailedSearchSubCriteria.java  |  7 +-
 .../basic/dto/SearchableEntityKind.java       | 55 +++++++++++++++
 .../openbis/generic/shared/dto/SamplePE.java  | 15 ++++
 .../dto/hibernate/SearchFieldConstants.java   |  4 ++
 .../api/v1/GeneralInformationServiceTest.java | 50 +++++++++++++-
 ...oDetailedSearchCriteriaTranslatorTest.java | 69 +++++++++++++++++++
 .../dataaccess/db/HibernateSearchDAOTest.java |  3 +-
 .../api/v1/GeneralInformationServiceTest.java |  4 +-
 13 files changed, 246 insertions(+), 33 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SearchableEntityKind.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java
index 7bd5e98cd0b..351c347d764 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java
@@ -32,7 +32,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchSubCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleAttributeSearchFieldKind;
@@ -51,13 +50,15 @@ class SearchCriteriaToDetailedSearchCriteriaTranslator
     private final static String INVALID_SEARCH_ATTRIBUTE_TEMPLATE =
             "%s is not a valid search attribute for %s";
 
-    private static Map<SearchableEntityKind, IMatchClauseAttributeTranslator> translators =
+    static Map<SearchableEntityKind, IMatchClauseAttributeTranslator> translators =
             new HashMap<SearchableEntityKind, IMatchClauseAttributeTranslator>();
 
     static
     {
-        translators.put(SearchableEntityKind.SAMPLE, new SampleAttributeTranslator());
         translators.put(SearchableEntityKind.EXPERIMENT, new ExperimentAttributeTranslator());
+        translators.put(SearchableEntityKind.SAMPLE, new SampleAttributeTranslator());
+        translators.put(SearchableEntityKind.SAMPLE_PARENT, new SampleAttributeTranslator());
+        translators.put(SearchableEntityKind.SAMPLE_CONTAINER, new SampleAttributeTranslator());
     }
 
     private static IMatchClauseAttributeTranslator translatorFor(SearchableEntityKind entityKind)
@@ -72,14 +73,19 @@ class SearchCriteriaToDetailedSearchCriteriaTranslator
                 attribute, entityKind));
     }
 
-    private static EntityKind translateEntityKind(SearchableEntityKind entityKind)
+    private static ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind translateEntityKind(
+            SearchableEntityKind entityKind)
     {
         switch (entityKind)
         {
             case SAMPLE:
-                return EntityKind.SAMPLE;
+                return ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.SAMPLE;
             case EXPERIMENT:
-                return EntityKind.EXPERIMENT;
+                return ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.EXPERIMENT;
+            case SAMPLE_CONTAINER:
+                return ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.SAMPLE_CONTAINER;
+            case SAMPLE_PARENT:
+                return ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.SAMPLE_PARENT;
         }
         return null; // can't happen
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DetailedSearchManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DetailedSearchManager.java
index 7889984dd9e..f2bca9d4b3a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DetailedSearchManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DetailedSearchManager.java
@@ -115,16 +115,17 @@ public class DetailedSearchManager
         parentCriteria.setCriteria(new ArrayList<DetailedSearchCriterion>());
         for (DetailedSearchSubCriteria subCriteria : allSubCriterias)
         {
-            if (subCriteria.getTargetEntityKind() == EntityKind.SAMPLE)
+            switch (subCriteria.getTargetEntityKind())
             {
-                // merge all parent sub criteria into one
-                parentCriteria.getCriteria().addAll(subCriteria.getCriteria().getCriteria());
-                parentCriteria.setConnection(subCriteria.getCriteria().getConnection());
-                parentCriteria.setUseWildcardSearchMode(subCriteria.getCriteria()
-                        .isUseWildcardSearchMode());
-            } else
-            {
-                otherSubCriterias.add(subCriteria);
+                case SAMPLE_PARENT:
+                    // merge all parent sub criteria into one
+                    parentCriteria.getCriteria().addAll(subCriteria.getCriteria().getCriteria());
+                    parentCriteria.setConnection(subCriteria.getCriteria().getConnection());
+                    parentCriteria.setUseWildcardSearchMode(subCriteria.getCriteria()
+                            .isUseWildcardSearchMode());
+                    break;
+                default:
+                    otherSubCriterias.add(subCriteria);
             }
         }
     }
@@ -151,8 +152,8 @@ public class DetailedSearchManager
         // for now we don't support sub criteria of sub criteria
         List<DetailedSearchAssociationCriteria> associations = Collections.emptyList();
         final Collection<Long> associatedIds =
-                searchDAO.searchForEntityIds(subCriteria.getCriteria(),
-                        DtoConverters.convertEntityKind(subCriteria.getTargetEntityKind()),
+                searchDAO.searchForEntityIds(subCriteria.getCriteria(), DtoConverters
+                        .convertEntityKind(subCriteria.getTargetEntityKind().getEntityKind()),
                         associations);
 
         return new DetailedSearchAssociationCriteria(subCriteria.getTargetEntityKind(),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/IndexFieldNameHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/IndexFieldNameHelper.java
index d0f0407bd64..3f61c69d3b3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/IndexFieldNameHelper.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/IndexFieldNameHelper.java
@@ -24,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants;
 
 /**
@@ -35,7 +36,8 @@ class IndexFieldNameHelper
 {
     // associations
 
-    static String getAssociationIndexField(EntityKind entityKind, EntityKind associationKind)
+    static String getAssociationIndexField(EntityKind entityKind,
+            SearchableEntityKind associationKind)
     {
         switch (associationKind)
         {
@@ -51,16 +53,21 @@ class IndexFieldNameHelper
                     return SearchFieldConstants.SAMPLE_ID;
                 }
                 throw createAssociationNotHandledException(entityKind, associationKind);
-            case MATERIAL:
+            case SAMPLE_CONTAINER:
+                if (entityKind == EntityKind.SAMPLE)
+                {
+                    return SearchFieldConstants.SAMPLE_ID;
+                }
                 throw createAssociationNotHandledException(entityKind, associationKind);
-            case DATA_SET:
+            case SAMPLE_PARENT:
+                // sample parent is a many-to-many connection - it is not handled by lucene index
                 throw createAssociationNotHandledException(entityKind, associationKind);
         }
         return null; // shouldn't happen
     }
 
     private static RuntimeException createAssociationNotHandledException(EntityKind entityKind,
-            EntityKind associationKind)
+            SearchableEntityKind associationKind)
     {
         return InternalErr.error("Associations between " + entityKind + " and " + associationKind
                 + " are not supported");
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchSubCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchSubCriteria.java
index fef1b2ca87b..ab2d31f0216 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchSubCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchSubCriteria.java
@@ -22,6 +22,16 @@ public class SearchSubCriteria implements Serializable
 
     private final SearchableEntityKind targetEntityKind;
 
+    public static SearchSubCriteria createSampleParentCriteria(SearchCriteria criteria)
+    {
+        return new SearchSubCriteria(SearchableEntityKind.SAMPLE_PARENT, criteria);
+    }
+
+    public static SearchSubCriteria createSampleContainerCriteria(SearchCriteria criteria)
+    {
+        return new SearchSubCriteria(SearchableEntityKind.SAMPLE_CONTAINER, criteria);
+    }
+
     public static SearchSubCriteria createSampleCriteria(SearchCriteria criteria)
     {
         return new SearchSubCriteria(SearchableEntityKind.SAMPLE, criteria);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchAssociationCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchAssociationCriteria.java
index 8ad789e4927..14346eebca1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchAssociationCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchAssociationCriteria.java
@@ -29,11 +29,11 @@ public class DetailedSearchAssociationCriteria implements ISerializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
-    private EntityKind entityKind;
+    private SearchableEntityKind entityKind;
 
     private Collection<Long> ids;
 
-    public DetailedSearchAssociationCriteria(EntityKind entityKind, Collection<Long> ids)
+    public DetailedSearchAssociationCriteria(SearchableEntityKind entityKind, Collection<Long> ids)
     {
         this.entityKind = entityKind;
         this.ids = ids;
@@ -44,7 +44,7 @@ public class DetailedSearchAssociationCriteria implements ISerializable
         return ids;
     }
 
-    public EntityKind getEntityKind()
+    public SearchableEntityKind getEntityKind()
     {
         return entityKind;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchSubCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchSubCriteria.java
index c1f0901795e..d0af539356b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchSubCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchSubCriteria.java
@@ -29,9 +29,10 @@ public class DetailedSearchSubCriteria implements ISerializable
 
     private DetailedSearchCriteria criteria;
 
-    private EntityKind targetEntityKind;
+    private SearchableEntityKind targetEntityKind;
 
-    public DetailedSearchSubCriteria(EntityKind targetEntityKind, DetailedSearchCriteria criteria)
+    public DetailedSearchSubCriteria(SearchableEntityKind targetEntityKind,
+            DetailedSearchCriteria criteria)
     {
         this.targetEntityKind = targetEntityKind;
         this.criteria = criteria;
@@ -42,7 +43,7 @@ public class DetailedSearchSubCriteria implements ISerializable
         return criteria;
     }
 
-    public EntityKind getTargetEntityKind()
+    public SearchableEntityKind getTargetEntityKind()
     {
         return targetEntityKind;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SearchableEntityKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SearchableEntityKind.java
new file mode 100644
index 00000000000..d6b17762af5
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SearchableEntityKind.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable;
+
+/**
+ * The <i>GWT</i> counterpart to
+ * ch.systemsx.cisd.openbis.generic.shared.api.v1.SearchableEntityKind.
+ * 
+ * @author Piotr Buczek
+ */
+public enum SearchableEntityKind implements ISerializable // AssociatedEntityKind
+{
+    SAMPLE("Sample", EntityKind.SAMPLE), EXPERIMENT("Experiment", EntityKind.EXPERIMENT),
+    // sample subcriteria
+    SAMPLE_CONTAINER("Container", EntityKind.SAMPLE), SAMPLE_PARENT("Parent", EntityKind.SAMPLE); // SAMPLE_CHILD
+
+    // MATERIAL("Material"), EXPERIMENT("Experiment"), SAMPLE("Sample"), DATA_SET("Data Set");
+
+    private final String description;
+
+    private final EntityKind entityKind;
+
+    private SearchableEntityKind(final String description, final EntityKind entityKind)
+    {
+        this.description = description;
+        this.entityKind = entityKind;
+    }
+
+    public final String getDescription()
+    {
+        return description;
+    }
+
+    public final EntityKind getEntityKind()
+    {
+        return entityKind;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java
index 4b3ba8ebb3f..7a3fe63546d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java
@@ -375,6 +375,21 @@ public class SamplePE extends AttachmentHolderPE implements IIdAndCodeHolder, Co
         return container;
     }
 
+    // used only by Hibernate Search
+    @SuppressWarnings("unused")
+    @Transient
+    @Field(index = Index.UN_TOKENIZED, store = Store.YES, name = SearchFieldConstants.CONTAINER_ID)
+    private Long getContainerId()
+    {
+        Long result = null;
+        if (getExperimentInternal() != null)
+        {
+            result = HibernateUtils.getId(getExperimentInternal());
+            assert result != null;
+        }
+        return result;
+    }
+
     public void setContainer(final SamplePE container)
     {
         this.container = container;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/hibernate/SearchFieldConstants.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/hibernate/SearchFieldConstants.java
index 96d4ca08b1e..017394e5b3b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/hibernate/SearchFieldConstants.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/hibernate/SearchFieldConstants.java
@@ -36,6 +36,8 @@ public final class SearchFieldConstants
 
     public static final String PREFIX_SAMPLE = "sample" + SEPARATOR;
 
+    public static final String PREFIX_CONTAINER = "container" + SEPARATOR;
+
     public static final String PREFIX_ENTITY_TYPE = "type" + SEPARATOR;
 
     public static final String PREFIX_FILE_FORMAT_TYPE = "file format type" + SEPARATOR;
@@ -61,6 +63,8 @@ public final class SearchFieldConstants
 
     public static final String SAMPLE_ID = PREFIX_SAMPLE + ID;
 
+    public static final String CONTAINER_ID = PREFIX_CONTAINER + ID;
+
     public static final String DELETED = "deleted";
 
     public static final String PERSON_LAST_NAME = "Last Name";
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java
index 30f638ea36d..a7375d49a12 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java
@@ -257,13 +257,38 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase
         assertEquals("ATTRIBUTE CODE: a code AND "
                 + "PROPERTY MY_PROPERTY2: a property value (with wildcards)",
                 detailedSearchCriteriaMatcher.recordedObject().toString());
-        // check experiment subcriteria
-        assertEquals("[SAMPLE: ATTRIBUTE CODE: parent code AND "
+        // check parent subcriteria
+        assertEquals("[SAMPLE_PARENT: ATTRIBUTE CODE: parent code AND "
                 + "PROPERTY PARENT_PROPERTY: parent property value (with wildcards)]",
                 detailedSearchSubCriteriaMatcher.recordedObject().toString());
         context.assertIsSatisfied();
     }
 
+    @Test
+    public void testSearchForSamplesWithContainer()
+    {
+        prepareGetSession();
+        final RecordingMatcher<DetailedSearchCriteria> detailedSearchCriteriaMatcher =
+                RecordingMatcher.create();
+        final RecordingMatcher<List<DetailedSearchSubCriteria>> detailedSearchSubCriteriaMatcher =
+                RecordingMatcher.create();
+        prepareSearchForSamples(detailedSearchCriteriaMatcher, detailedSearchSubCriteriaMatcher);
+        List<Sample> result =
+                service.searchForSamples(SESSION_TOKEN,
+                        createSearchCriteriaForSampleWithContainer());
+        assertEquals(1, result.size());
+        Sample resultSample = result.get(0);
+        assertEquals("/space/code", resultSample.getIdentifier());
+        assertEquals("ATTRIBUTE CODE: a code AND "
+                + "PROPERTY MY_PROPERTY2: a property value (with wildcards)",
+                detailedSearchCriteriaMatcher.recordedObject().toString());
+        // check container subcriteria
+        assertEquals("[SAMPLE_CONTAINER: ATTRIBUTE CODE: container code AND "
+                + "PROPERTY CONTAINER_PROPERTY: container property value (with wildcards)]",
+                detailedSearchSubCriteriaMatcher.recordedObject().toString());
+        context.assertIsSatisfied();
+    }
+
     private void prepareSearchForSamples(
             final RecordingMatcher<DetailedSearchCriteria> detailedSearchCriteriaMatcher,
             final RecordingMatcher<List<DetailedSearchSubCriteria>> detailedSearchSubCriteriaMatcher)
@@ -473,6 +498,16 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase
         return sc;
     }
 
+    private SearchCriteria createSearchCriteriaForSampleContainer()
+    {
+        SearchCriteria sc = new SearchCriteria();
+        sc.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "container code"));
+        sc.addMatchClause(MatchClause.createPropertyMatch("CONTAINER_PROPERTY",
+                "container property value"));
+        return sc;
+    }
+
     private SearchCriteria createSearchCriteriaForExperiment()
     {
         SearchCriteria sc = new SearchCriteria();
@@ -495,7 +530,16 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase
     {
         SearchCriteria mainCriteria = createSearchCriteriaForSample();
         SearchCriteria parentCriteria = createSearchCriteriaForSampleParent();
-        mainCriteria.addSubCriteria(SearchSubCriteria.createSampleCriteria(parentCriteria));
+        mainCriteria.addSubCriteria(SearchSubCriteria.createSampleParentCriteria(parentCriteria));
+        return mainCriteria;
+    }
+
+    private SearchCriteria createSearchCriteriaForSampleWithContainer()
+    {
+        SearchCriteria mainCriteria = createSearchCriteriaForSample();
+        SearchCriteria containerCriteria = createSearchCriteriaForSampleContainer();
+        mainCriteria.addSubCriteria(SearchSubCriteria
+                .createSampleContainerCriteria(containerCriteria));
         return mainCriteria;
     }
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslatorTest.java
index 70a80b71f69..699d3985f79 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslatorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslatorTest.java
@@ -19,18 +19,32 @@ package ch.systemsx.cisd.openbis.generic.server.api.v1;
 import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.openbis.generic.server.api.v1.SearchCriteriaToDetailedSearchCriteriaTranslator.IMatchClauseAttributeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClause;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClauseAttribute;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.SearchOperator;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchSubCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchableEntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchSubCriteria;
 
 /**
  * @author Chandrasekhar Ramakrishnan
  */
 public class SearchCriteriaToDetailedSearchCriteriaTranslatorTest extends AssertJUnit
 {
+    @Test
+    public void testTranslatorsInitialization()
+    {
+        for (SearchableEntityKind entityKind : SearchableEntityKind.values())
+        {
+            IMatchClauseAttributeTranslator translator =
+                    SearchCriteriaToDetailedSearchCriteriaTranslator.translators.get(entityKind);
+            assertNotNull("No translator defined for " + entityKind, translator);
+        }
+    }
+
     @Test
     public void testBasicMatchAllCriteriaTranslator()
     {
@@ -129,6 +143,61 @@ public class SearchCriteriaToDetailedSearchCriteriaTranslatorTest extends Assert
         }
     }
 
+    private static String EXPECTED_BASIC_QUERY_SUFFIX = "ATTRIBUTE CODE: a code AND "
+            + "PROPERTY MY_PROPERTY: a property value " + "(with wildcards)";
+
+    private void testConvertToDetailedSearchSubCriteria(
+            ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind expectedEntityKind,
+            SearchSubCriteria subCriteria)
+    {
+        DetailedSearchSubCriteria detailedSearchSubCriteria =
+                SearchCriteriaToDetailedSearchCriteriaTranslator
+                        .convertToDetailedSearchSubCriteria(subCriteria);
+        assertNotNull(detailedSearchSubCriteria);
+        assertEquals(expectedEntityKind + ": " + EXPECTED_BASIC_QUERY_SUFFIX,
+                detailedSearchSubCriteria.toString());
+    }
+
+    @Test
+    public void testBasicSampleSubCriteriaTranslator()
+    {
+        SearchCriteria criteria = createBasicSearchCriteria();
+        SearchSubCriteria subCriteria = SearchSubCriteria.createSampleCriteria(criteria);
+        testConvertToDetailedSearchSubCriteria(
+                ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.SAMPLE,
+                subCriteria);
+    }
+
+    @Test
+    public void testBasicSampleParentSubCriteriaTranslator()
+    {
+        SearchCriteria criteria = createBasicSearchCriteria();
+        SearchSubCriteria subCriteria = SearchSubCriteria.createSampleParentCriteria(criteria);
+        testConvertToDetailedSearchSubCriteria(
+                ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.SAMPLE_PARENT,
+                subCriteria);
+    }
+
+    @Test
+    public void testBasicSampleContainerSubCriteriaTranslator()
+    {
+        SearchCriteria criteria = createBasicSearchCriteria();
+        SearchSubCriteria subCriteria = SearchSubCriteria.createSampleContainerCriteria(criteria);
+        testConvertToDetailedSearchSubCriteria(
+                ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.SAMPLE_CONTAINER,
+                subCriteria);
+    }
+
+    @Test
+    public void testBasicExperimentSubCriteriaTranslator()
+    {
+        SearchCriteria criteria = createBasicSearchCriteria();
+        SearchSubCriteria subCriteria = SearchSubCriteria.createExperimentCriteria(criteria);
+        testConvertToDetailedSearchSubCriteria(
+                ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind.EXPERIMENT,
+                subCriteria);
+    }
+
     private SearchCriteria createBasicSearchCriteria()
     {
         SearchCriteria sc = new SearchCriteria();
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 bfc71d97868..c093b373fdd 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
@@ -48,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchableEntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
@@ -361,7 +362,7 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
         DetailedSearchCriterion criterion = createSimpleFieldCriterion();
         DetailedSearchCriteria criteria = createAndDatasetQuery(criterion);
         DetailedSearchAssociationCriteria association =
-                new DetailedSearchAssociationCriteria(EntityKind.EXPERIMENT,
+                new DetailedSearchAssociationCriteria(SearchableEntityKind.EXPERIMENT,
                         Collections.singleton(new Long(2L)));
         // compared to testSearchForDataSetsSimpleField() DSLoc.LOC3 should be filtered
         // because of different experiment
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
index bd91ac98b39..d27cfd3f9a0 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
@@ -165,7 +165,7 @@ public class GeneralInformationServiceTest extends SystemTestCase
         sc.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE, "*"));
         SearchCriteria pc = new SearchCriteria();
         pc.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE, "MP002-1"));
-        sc.addSubCriteria(SearchSubCriteria.createSampleCriteria(pc));
+        sc.addSubCriteria(SearchSubCriteria.createSampleParentCriteria(pc));
         List<Sample> result = generalInformationService.searchForSamples(sessionToken, sc);
         assertEquals(2, result.size());
     }
@@ -187,7 +187,7 @@ public class GeneralInformationServiceTest extends SystemTestCase
         // Add parent criteria limiting results to only 2
         SearchCriteria pc = new SearchCriteria();
         pc.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE, "DP1-A"));
-        sc.addSubCriteria(SearchSubCriteria.createSampleCriteria(pc));
+        sc.addSubCriteria(SearchSubCriteria.createSampleParentCriteria(pc));
         List<Sample> result3 = generalInformationService.searchForSamples(sessionToken, sc);
         assertEquals(2, result3.size());
     }
-- 
GitLab