From 8f888a2699fee3da014c4ef2fc585e52c9985c67 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Wed, 6 Apr 2016 06:35:40 +0000
Subject: [PATCH] SSDM-3401: searchDataSetTypes introduced, implemented and
 tested. Bug in PropertyAssignmentTranslator. Refactoring: Introducing
 AbstractSearchEntityTypeExecutor as super class of Search*TypeExecutor.

SVN: 36089
---
 .../server/asapi/v3/ApplicationServerApi.java | 17 ++++
 .../asapi/v3/ApplicationServerApiLogger.java  | 10 +++
 .../dataset/ISearchDataSetTypeExecutor.java   | 31 +++++++
 .../dataset/SearchDataSetTypeExecutor.java    | 37 +++++++++
 .../AbstractSearchEntityTypeExecutor.java     | 64 +++++++++++++++
 .../SearchExperimentTypeExecutor.java         | 33 +-------
 .../ISearchDataSetTypeMethodExecutor.java     | 31 +++++++
 .../SearchDataSetTypeSqlMethodExecutor.java   | 59 ++++++++++++++
 .../sample/SearchSampleTypeExecutor.java      | 31 +------
 .../PropertyAssignmentTranslator.java         | 16 +++-
 .../asapi/v3/SearchDataSetTypeTest.java       | 80 +++++++++++++++++++
 .../asapi/v3/SearchExperimentTypeTest.java    |  2 +-
 .../asapi/v3/IApplicationServerApi.java       |  4 +
 13 files changed, 354 insertions(+), 61 deletions(-)
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/ISearchDataSetTypeExecutor.java
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/SearchDataSetTypeExecutor.java
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/entity/AbstractSearchEntityTypeExecutor.java
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/ISearchDataSetTypeMethodExecutor.java
 create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/SearchDataSetTypeSqlMethodExecutor.java
 create mode 100644 openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchDataSetTypeTest.java

diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
index 76631187bea..4a49d72c106 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
@@ -26,9 +26,11 @@ import org.springframework.transaction.annotation.Transactional;
 import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.create.DataSetCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.delete.DataSetDeletionOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.IDataSetId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria;
@@ -128,6 +130,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.IMapVocabular
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.IRevertDeletionMethodExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.ISearchCustomASServiceMethodExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.ISearchDataSetMethodExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.ISearchDataSetTypeMethodExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.ISearchDeletionMethodExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.ISearchExperimentMethodExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.method.ISearchExperimentTypeMethodExecutor;
@@ -257,6 +260,9 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
     @Autowired
     private ISearchDataSetMethodExecutor searchDataSetExecutor;
 
+    @Autowired
+    private ISearchDataSetTypeMethodExecutor searchDataSetTypeExecutor;
+    
     @Autowired
     private ISearchMaterialMethodExecutor searchMaterialExecutor;
 
@@ -569,6 +575,8 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
     }
 
     @Override
+    @Transactional(readOnly = true)
+    @RolesAllowed({ RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
     public SearchResult<ExperimentType> searchExperimentTypes(String sessionToken, EntityTypeSearchCriteria searchCriteria,
             ExperimentTypeFetchOptions fetchOptions)
     {
@@ -600,6 +608,15 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
         return searchDataSetExecutor.search(sessionToken, searchCriteria, fetchOptions);
     }
 
+    @Override
+    @Transactional(readOnly = true)
+    @RolesAllowed({ RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
+    public SearchResult<DataSetType> searchDataSetTypes(String sessionToken, EntityTypeSearchCriteria searchCriteria,
+            DataSetTypeFetchOptions fetchOptions)
+    {
+        return searchDataSetTypeExecutor.search(sessionToken, searchCriteria, fetchOptions);
+    }
+
     @Override
     @Transactional(readOnly = true)
     @RolesAllowed({ RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java
index c1c037a5709..14bf5478759 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java
@@ -22,9 +22,11 @@ import java.util.Map;
 import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.create.DataSetCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.delete.DataSetDeletionOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.IDataSetId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria;
@@ -339,6 +341,14 @@ public class ApplicationServerApiLogger extends AbstractServerLogger implements
         return null;
     }
 
+    @Override
+    public SearchResult<DataSetType> searchDataSetTypes(String sessionToken, EntityTypeSearchCriteria searchCriteria,
+            DataSetTypeFetchOptions fetchOptions)
+    {
+        logAccess(sessionToken, "search-data-set-types", "SEARCH_CRITERIA:\n%s\nFETCH_OPTIONS:\n%s\n", searchCriteria, fetchOptions);
+        return null;
+    }
+
     @Override
     public SearchResult<Material> searchMaterials(String sessionToken, MaterialSearchCriteria searchCriteria, MaterialFetchOptions fetchOptions)
     {
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/ISearchDataSetTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/ISearchDataSetTypeExecutor.java
new file mode 100644
index 00000000000..b4f1c23b3e5
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/ISearchDataSetTypeExecutor.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 ETH Zuerich, SIS
+ *
+ * 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.ethz.sis.openbis.generic.server.asapi.v3.executor.dataset;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.ISearchObjectExecutor;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public interface ISearchDataSetTypeExecutor extends ISearchObjectExecutor<EntityTypeSearchCriteria, DataSetTypePE>
+{
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/SearchDataSetTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/SearchDataSetTypeExecutor.java
new file mode 100644
index 00000000000..c22c3e287d2
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/dataset/SearchDataSetTypeExecutor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 ETH Zuerich, SIS
+ *
+ * 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.ethz.sis.openbis.generic.server.asapi.v3.executor.dataset;
+
+import org.springframework.stereotype.Component;
+
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.AbstractSearchEntityTypeExecutor;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+@Component
+public class SearchDataSetTypeExecutor extends AbstractSearchEntityTypeExecutor<DataSetTypePE> implements ISearchDataSetTypeExecutor
+{
+    public SearchDataSetTypeExecutor()
+    {
+        super(EntityKind.DATA_SET);
+    }
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/entity/AbstractSearchEntityTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/entity/AbstractSearchEntityTypeExecutor.java
new file mode 100644
index 00000000000..67fe390d44e
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/entity/AbstractSearchEntityTypeExecutor.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 ETH Zuerich, SIS
+ *
+ * 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.ethz.sis.openbis.generic.server.asapi.v3.executor.entity;
+
+import java.util.List;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.CodeSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.PermIdSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.AbstractSearchObjectManuallyExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.CodeMatcher;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.Matcher;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public abstract class AbstractSearchEntityTypeExecutor<ENTITY_TYPE_PE extends EntityTypePE>
+        extends AbstractSearchObjectManuallyExecutor<EntityTypeSearchCriteria, ENTITY_TYPE_PE>
+{
+    private final EntityKind entityKind;
+
+    protected AbstractSearchEntityTypeExecutor(EntityKind entityKind)
+    {
+        this.entityKind = entityKind;
+    }
+    
+    @Override
+    protected List<ENTITY_TYPE_PE> listAll()
+    {
+        return daoFactory.getEntityTypeDAO(entityKind).listEntityTypes();
+    }
+
+    @Override
+    protected Matcher<ENTITY_TYPE_PE> getMatcher(ISearchCriteria criteria)
+    {
+        if (criteria instanceof PermIdSearchCriteria || criteria instanceof CodeSearchCriteria)
+        {
+            return new CodeMatcher<ENTITY_TYPE_PE>();
+        } else
+        {
+            throw new IllegalArgumentException("Unknown search criteria: " + criteria.getClass());
+        }
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/SearchExperimentTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/SearchExperimentTypeExecutor.java
index 6a136017281..74d330cc0cf 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/SearchExperimentTypeExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/SearchExperimentTypeExecutor.java
@@ -16,17 +16,9 @@
 
 package ch.ethz.sis.openbis.generic.server.asapi.v3.executor.experiment;
 
-import java.util.List;
-
 import org.springframework.stereotype.Component;
 
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.CodeSearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.PermIdSearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.AbstractSearchObjectManuallyExecutor;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.CodeMatcher;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.Matcher;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.AbstractSearchEntityTypeExecutor;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
@@ -36,27 +28,10 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
  * @author Franz-Josef Elmer
  */
 @Component
-public class SearchExperimentTypeExecutor extends AbstractSearchObjectManuallyExecutor<EntityTypeSearchCriteria, ExperimentTypePE> 
-        implements ISearchExperimentTypeExecutor
+public class SearchExperimentTypeExecutor extends AbstractSearchEntityTypeExecutor<ExperimentTypePE> implements ISearchExperimentTypeExecutor
 {
-
-    @Override
-    protected List<ExperimentTypePE> listAll()
+    public SearchExperimentTypeExecutor()
     {
-        return daoFactory.getEntityTypeDAO(EntityKind.EXPERIMENT).listEntityTypes();
+        super(EntityKind.EXPERIMENT);
     }
-
-    @Override
-    protected Matcher<ExperimentTypePE> getMatcher(ISearchCriteria criteria)
-    {
-        if (criteria instanceof PermIdSearchCriteria || criteria instanceof CodeSearchCriteria)
-        {
-            return new CodeMatcher<ExperimentTypePE>();
-        } else
-        {
-            throw new IllegalArgumentException("Unknown search criteria: " + criteria.getClass());
-        }
-    }
-
-
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/ISearchDataSetTypeMethodExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/ISearchDataSetTypeMethodExecutor.java
new file mode 100644
index 00000000000..17d4c98f595
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/ISearchDataSetTypeMethodExecutor.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 ETH Zuerich, SIS
+ *
+ * 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.ethz.sis.openbis.generic.server.asapi.v3.executor.method;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public interface ISearchDataSetTypeMethodExecutor extends ISearchMethodExecutor<DataSetType, EntityTypeSearchCriteria, DataSetTypeFetchOptions>
+{
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/SearchDataSetTypeSqlMethodExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/SearchDataSetTypeSqlMethodExecutor.java
new file mode 100644
index 00000000000..05700b0a7db
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/method/SearchDataSetTypeSqlMethodExecutor.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 ETH Zuerich, SIS
+ *
+ * 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.ethz.sis.openbis.generic.server.asapi.v3.executor.method;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.IOperationContext;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.dataset.ISearchDataSetTypeExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.ITranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.entity.dataset.IDataSetTypeTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
+
+/**
+ *
+ * @author Franz-Josef Elmer
+ */
+@Component
+public class SearchDataSetTypeSqlMethodExecutor extends AbstractIdSearchMethodExecutor<DataSetType, DataSetTypePE, EntityTypeSearchCriteria, DataSetTypeFetchOptions> 
+        implements ISearchDataSetTypeMethodExecutor
+{
+    @Autowired
+    private ISearchDataSetTypeExecutor searchExecutor;
+    
+    @Autowired
+    private IDataSetTypeTranslator translator;
+    
+    @Override
+    protected List<DataSetTypePE> searchPEs(IOperationContext context, EntityTypeSearchCriteria criteria)
+    {
+        return searchExecutor.search(context, criteria);
+    }
+
+    @Override
+    protected ITranslator<Long, DataSetType, DataSetTypeFetchOptions> getTranslator()
+    {
+        return translator;
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/sample/SearchSampleTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/sample/SearchSampleTypeExecutor.java
index 32ab6f3d51d..96e861a5406 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/sample/SearchSampleTypeExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/sample/SearchSampleTypeExecutor.java
@@ -16,17 +16,9 @@
 
 package ch.ethz.sis.openbis.generic.server.asapi.v3.executor.sample;
 
-import java.util.List;
-
 import org.springframework.stereotype.Component;
 
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.CodeSearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ISearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.PermIdSearchCriteria;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.AbstractSearchObjectManuallyExecutor;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.CodeMatcher;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.Matcher;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.AbstractSearchEntityTypeExecutor;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
@@ -36,25 +28,10 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
  * @author Franz-Josef Elmer
  */
 @Component
-public class SearchSampleTypeExecutor extends AbstractSearchObjectManuallyExecutor<EntityTypeSearchCriteria, SampleTypePE> 
-        implements ISearchSampleTypeExecutor
+public class SearchSampleTypeExecutor extends AbstractSearchEntityTypeExecutor<SampleTypePE> implements ISearchSampleTypeExecutor
 {
-
-    @Override
-    protected List<SampleTypePE> listAll()
-    {
-        return daoFactory.getEntityTypeDAO(EntityKind.SAMPLE).listEntityTypes();
-    }
-
-    @Override
-    protected Matcher<SampleTypePE> getMatcher(ISearchCriteria criteria)
+    public SearchSampleTypeExecutor()
     {
-        if (criteria instanceof PermIdSearchCriteria || criteria instanceof CodeSearchCriteria)
-        {
-            return new CodeMatcher<SampleTypePE>();
-        } else
-        {
-            throw new IllegalArgumentException("Unknown search criteria: " + criteria.getClass());
-        }
+        super(EntityKind.SAMPLE);
     }
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/entity/property/PropertyAssignmentTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/entity/property/PropertyAssignmentTranslator.java
index 0f3dbdc19c2..b42b3dcbf6b 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/entity/property/PropertyAssignmentTranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/entity/property/PropertyAssignmentTranslator.java
@@ -41,13 +41,19 @@ public abstract class PropertyAssignmentTranslator extends ObjectToManyRelationT
     protected Map<Long, PropertyAssignment> getAssignments(Collection<PropertyAssignmentRecord> assignmentRecords)
     {
         Map<Long, PropertyAssignment> assignments = new HashMap<>();
-        Map<Long, PropertyAssignment> assignmentsByPropertyTypeId = new HashMap<>();
+        Map<Long, List<PropertyAssignment>> assignmentsByPropertyTypeId = new HashMap<>();
         for (PropertyAssignmentRecord assignmentRecord : assignmentRecords)
         {
             PropertyAssignment assignment = new PropertyAssignment();
             assignment.setMandatory(assignmentRecord.is_mandatory);
             assignments.put(assignmentRecord.id, assignment);
-            assignmentsByPropertyTypeId.put(assignmentRecord.prty_id, assignment);
+            List<PropertyAssignment> list = assignmentsByPropertyTypeId.get(assignmentRecord.prty_id);
+            if (list == null)
+            {
+                list = new ArrayList<>();
+                assignmentsByPropertyTypeId.put(assignmentRecord.prty_id, list);
+            }
+            list.add(assignment);
         }
         PropertyTypeQuery query = QueryTool.getManagedQuery(PropertyTypeQuery.class);
         List<PropertyTypeRecord> propertyTypeRecords = query.getPropertyTypes(new LongOpenHashSet(assignmentsByPropertyTypeId.keySet()));
@@ -60,8 +66,10 @@ public abstract class PropertyAssignmentTranslator extends ObjectToManyRelationT
             propertyType.setDescription(propertyTypeRecord.description);
             propertyType.setDataTypeCode(DataTypeCode.valueOf(propertyTypeRecord.dataSetTypeCode));
             propertyType.setInternalNameSpace(propertyTypeRecord.is_internal_namespace);
-            PropertyAssignment assignment = assignmentsByPropertyTypeId.get(propertyTypeId);
-            assignment.setPropertyType(propertyType);
+            for (PropertyAssignment assignment : assignmentsByPropertyTypeId.get(propertyTypeId))
+            {
+                assignment.setPropertyType(propertyType);
+            }
         }
         return assignments;
     }
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchDataSetTypeTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchDataSetTypeTest.java
new file mode 100644
index 00000000000..c2506ae6158
--- /dev/null
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchDataSetTypeTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 ETH Zuerich, SIS
+ *
+ * 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.ethz.sis.openbis.systemtest.asapi.v3;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.search.EntityTypeSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.sort.CodeComparator;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class SearchDataSetTypeTest extends AbstractTest
+{
+    @Test
+    public void testSearchWithCodeThatStartsWithD()
+    {
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        EntityTypeSearchCriteria searchCriteria = new EntityTypeSearchCriteria();
+        searchCriteria.withCode().thatStartsWith("D");
+        DataSetTypeFetchOptions fetchOptions = new DataSetTypeFetchOptions();
+        
+        SearchResult<DataSetType> searchResult = v3api.searchDataSetTypes(sessionToken, searchCriteria, fetchOptions);
+        
+        List<DataSetType> types = searchResult.getObjects();
+        List<String> codes = extractCodes(types);
+        Collections.sort(codes);
+        assertEquals(codes.toString(), "[DELETION_TEST, DELETION_TEST_CONTAINER]");
+        assertEquals(types.get(0).getFetchOptions().hasPropertyAssignments(), false);
+        v3api.logout(sessionToken);
+    }
+
+    @Test
+    public void testSearchWithPropertyAssignmentSortByCodeDesc()
+    {
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        EntityTypeSearchCriteria searchCriteria = new EntityTypeSearchCriteria();
+        searchCriteria.withCode().thatStartsWith("D");
+        DataSetTypeFetchOptions fetchOptions = new DataSetTypeFetchOptions();
+        fetchOptions.withPropertyAssignments().sortBy().code().desc();
+        
+        SearchResult<DataSetType> searchResult = v3api.searchDataSetTypes(sessionToken, searchCriteria, fetchOptions);
+        
+        List<DataSetType> types = searchResult.getObjects();
+        Collections.sort(types, new CodeComparator<DataSetType>());
+        List<String> codes = extractCodes(types);
+        assertEquals(codes.toString(), "[DELETION_TEST, DELETION_TEST_CONTAINER]");
+        assertEquals(types.get(0).getFetchOptions().hasPropertyAssignments(), true);
+        List<PropertyAssignment> propertyAssignments = types.get(0).getPropertyAssignments();
+        System.err.println(propertyAssignments.get(0).getPropertyType());
+        assertOrder(propertyAssignments, "ORGANISM", "DESCRIPTION", "BACTERIUM");
+        v3api.logout(sessionToken);
+    }
+    
+}
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchExperimentTypeTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchExperimentTypeTest.java
index 0f06e281e08..3583b4ba575 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchExperimentTypeTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchExperimentTypeTest.java
@@ -56,7 +56,7 @@ public class SearchExperimentTypeTest extends AbstractTest
     }
 
     @Test
-    public void testSearchWithPropertyAssignmentSortByLabelDesc()
+    public void testSearchWithPropertyAssignmentSortByCodeDesc()
     {
         String sessionToken = v3api.login(TEST_USER, PASSWORD);
         EntityTypeSearchCriteria searchCriteria = new EntityTypeSearchCriteria();
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java
index 164dce1c2a7..d89d93b6499 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java
@@ -21,9 +21,11 @@ import java.util.Map;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.create.DataSetCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.delete.DataSetDeletionOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.IDataSetId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria;
@@ -184,6 +186,8 @@ public interface IApplicationServerApi extends IRpcService
     
     public SearchResult<DataSet> searchDataSets(String sessionToken, DataSetSearchCriteria searchCriteria, DataSetFetchOptions fetchOptions);
 
+    public SearchResult<DataSetType> searchDataSetTypes(String sessionToken, EntityTypeSearchCriteria searchCriteria, DataSetTypeFetchOptions fetchOptions);
+    
     public SearchResult<Material> searchMaterials(String sessionToken, MaterialSearchCriteria searchCriteria, MaterialFetchOptions fetchOptions);
 
     public SearchResult<VocabularyTerm> searchVocabularyTerms(String sessionToken, VocabularyTermSearchCriteria searchCriteria,
-- 
GitLab