From 26e552ee4b1ad73d042b9fc928a8ea3aa46c2861 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Mon, 31 Aug 2009 14:18:09 +0000
Subject: [PATCH] [LMS-1121] refactorization: extracted common code from Data
 Set search - to be used for other entities

SVN: 12329
---
 .../web/client/ICommonClientService.java      |   6 +-
 .../web/client/ICommonClientServiceAsync.java |   6 +-
 ...ava => DetailedSearchFieldComboModel.java} |   9 +-
 .../ui/data/DataSetSearchHitGrid.java         |  18 +-
 .../DetailedSearchCriteriaWidget.java}        |  48 ++---
 .../DetailedSearchCriterionWidget.java}       |  47 +++--
 .../DetailedSearchFieldsSelectionWidget.java} | 176 ++++++++++-------
 .../DetailedSearchToolbar.java}               |  19 +-
 .../DetailedSearchWindow.java}                |  26 ++-
 .../ui/search/IDetailedSearchHitGrid.java     |  35 ++++
 .../ui/search/MatchCriteriaRadio.java         |  94 +++++++++
 .../web/server/CommonClientService.java       |   4 +-
 ...ListDataSetSearchOriginalDataProvider.java |   6 +-
 .../openbis/generic/server/CommonServer.java  |   4 +-
 .../generic/server/CommonServerLogger.java    |   4 +-
 .../dataaccess/IHibernateSearchDAO.java       |   4 +-
 .../dataaccess/db/HibernateSearchDAO.java     |  11 +-
 .../db/search/LuceneQueryBuilder.java         | 146 +-------------
 .../search/detailed/DetailedQueryBuilder.java | 186 ++++++++++++++++++
 .../search/detailed/IndexFieldNameHelper.java |  83 ++++++++
 .../openbis/generic/shared/ICommonServer.java |   4 +-
 .../dto/DataSetAttributeSearchFieldKind.java  |  51 +++++
 .../shared/basic/dto/DataSetSearchField.java  | 112 -----------
 .../basic/dto/DataSetSearchFieldKind.java     |  83 --------
 ...teria.java => DetailedSearchCriteria.java} |  15 +-
 ...rion.java => DetailedSearchCriterion.java} |  13 +-
 .../shared/basic/dto/DetailedSearchField.java | 128 ++++++++++++
 .../basic/dto/DetailedSearchFieldKind.java    |  47 +++++
 .../basic/dto/IAttributeSearchFieldKind.java  |  27 +++
 .../client/application/DataSetSearchTest.java |   8 +-
 .../{data => search}/FillSearchCriteria.java  |  51 ++---
 .../dataaccess/db/HibernateSearchDAOTest.java |  65 +++---
 .../shared/ICommonServer.java.expected        |   4 +-
 33 files changed, 965 insertions(+), 575 deletions(-)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/{DataSetSearchFieldComboModel.java => DetailedSearchFieldComboModel.java} (74%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{data/CriteriaWidget.java => search/DetailedSearchCriteriaWidget.java} (67%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{data/CriterionWidget.java => search/DetailedSearchCriterionWidget.java} (73%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{data/DataSetSearchFieldsSelectionWidget.java => search/DetailedSearchFieldsSelectionWidget.java} (50%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{data/DataSetSearchToolbar.java => search/DetailedSearchToolbar.java} (73%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{data/DataSetSearchWindow.java => search/DetailedSearchWindow.java} (75%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/IDetailedSearchHitGrid.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/MatchCriteriaRadio.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/DetailedQueryBuilder.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/IndexFieldNameHelper.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetAttributeSearchFieldKind.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchField.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchFieldKind.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/{DataSetSearchCriteria.java => DetailedSearchCriteria.java} (78%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/{DataSetSearchCriterion.java => DetailedSearchCriterion.java} (80%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchField.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchFieldKind.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IAttributeSearchFieldKind.java
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{data => search}/FillSearchCriteria.java (60%)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index 9f9c7ab22f9..4350d6e3504 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -43,7 +43,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AttachmentHolderKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
@@ -75,6 +74,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleSetCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -472,9 +472,9 @@ public interface ICommonClientService extends IClientService
             throws UserFailureException;
 
     /**
-     * Returns {@link ExternalData} fulfilling given {@link DataSetSearchCriteria}.
+     * Returns {@link ExternalData} fulfilling given {@link DetailedSearchCriteria}.
      */
-    public ResultSetWithEntityTypes<ExternalData> searchForDataSets(DataSetSearchCriteria criteria,
+    public ResultSetWithEntityTypes<ExternalData> searchForDataSets(DetailedSearchCriteria criteria,
             final IResultSetConfig<String, ExternalData> resultSetConfig)
             throws UserFailureException;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index 92023da3cdb..16f0b274a72 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -45,7 +45,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AttachmentHolderKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
@@ -77,6 +76,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleSetCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -397,9 +397,9 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
             final AsyncCallback<Void> projectRegistrationCallback);
 
     /**
-     * @see ICommonClientService#searchForDataSets(DataSetSearchCriteria, IResultSetConfig)
+     * @see ICommonClientService#searchForDataSets(DetailedSearchCriteria, IResultSetConfig)
      */
-    public void searchForDataSets(DataSetSearchCriteria criteria,
+    public void searchForDataSets(DetailedSearchCriteria criteria,
             final IResultSetConfig<String, ExternalData> resultSetConfig,
             final AsyncCallback<ResultSetWithEntityTypes<ExternalData>> callback);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/DataSetSearchFieldComboModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/DetailedSearchFieldComboModel.java
similarity index 74%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/DataSetSearchFieldComboModel.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/DetailedSearchFieldComboModel.java
index f2de744cd68..cc1fa015a37 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/DataSetSearchFieldComboModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/DetailedSearchFieldComboModel.java
@@ -18,19 +18,20 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.model;
 
 import com.extjs.gxt.ui.client.data.BaseModelData;
 
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchField;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField;
 
-public class DataSetSearchFieldComboModel extends BaseModelData
+/** Model of combo box used in detailed entity search. */
+public class DetailedSearchFieldComboModel extends BaseModelData
 {
     private static final long serialVersionUID = 1L;
 
-    public DataSetSearchFieldComboModel(String code, DataSetSearchField field)
+    public DetailedSearchFieldComboModel(String code, DetailedSearchField field)
     {
         set(ModelDataPropertyNames.CODE, code);
         set(ModelDataPropertyNames.OBJECT, field);
     }
 
-    public DataSetSearchField getField()
+    public DetailedSearchField getField()
     {
         return get(ModelDataPropertyNames.OBJECT);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java
index ef3154f6e3a..ad7749d78f9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java
@@ -27,18 +27,22 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewConte
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplayTypeIDGenerator;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search.IDetailedSearchHitGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search.DetailedSearchToolbar;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search.DetailedSearchWindow;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 
 /**
  * Grid with data set search results.
  * 
  * @author Izabela Adamczyk
  */
-public class DataSetSearchHitGrid extends AbstractExternalDataGrid
+public class DataSetSearchHitGrid extends AbstractExternalDataGrid implements IDetailedSearchHitGrid
 {
 
     // browser consists of the grid and the paging toolbar
@@ -51,15 +55,15 @@ public class DataSetSearchHitGrid extends AbstractExternalDataGrid
             final IViewContext<ICommonClientServiceAsync> viewContext)
     {
         DataSetSearchHitGrid grid = new DataSetSearchHitGrid(viewContext);
-        final DataSetSearchWindow searchWindow = new DataSetSearchWindow(viewContext);
-        final DataSetSearchToolbar toolbar =
-                new DataSetSearchToolbar(grid, viewContext.getMessage(Dict.BUTTON_CHANGE_QUERY),
+        final DetailedSearchWindow searchWindow = new DetailedSearchWindow(viewContext, EntityKind.DATA_SET);
+        final DetailedSearchToolbar toolbar =
+                new DetailedSearchToolbar(grid, viewContext.getMessage(Dict.BUTTON_CHANGE_QUERY),
                         searchWindow);
         searchWindow.setUpdateListener(toolbar);
         return grid.asDisposableWithToolbar(toolbar);
     }
 
-    private DataSetSearchCriteria chosenSearchCriteria;
+    private DetailedSearchCriteria chosenSearchCriteria;
 
     private DataSetSearchHitGrid(final IViewContext<ICommonClientServiceAsync> viewContext)
     {
@@ -74,7 +78,7 @@ public class DataSetSearchHitGrid extends AbstractExternalDataGrid
         viewContext.getService().searchForDataSets(chosenSearchCriteria, resultSetConfig, callback);
     }
 
-    public void refresh(DataSetSearchCriteria newCriteria, List<PropertyType> propertyTypes)
+    public void refresh(DetailedSearchCriteria newCriteria, List<PropertyType> propertyTypes)
     {
         chosenSearchCriteria = newCriteria;
         if (criteria != null)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/CriteriaWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java
similarity index 67%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/CriteriaWidget.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java
index a0954b30db5..371779a085f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/CriteriaWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -24,32 +24,35 @@ import com.extjs.gxt.ui.client.widget.VerticalPanel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriterion;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion;
 
 /**
- * Widget for {@link DataSetSearchCriteria} management.
+ * Widget for {@link DetailedSearchCriteria} management.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
-public class CriteriaWidget extends VerticalPanel
+public class DetailedSearchCriteriaWidget extends VerticalPanel
 {
 
     public static final String FIRST_ID_SUFFIX = "_first";
 
-    private final List<CriterionWidget> criteriaWidgets;
+    private final List<DetailedSearchCriterionWidget> criteriaWidgets;
 
     private final MatchCriteriaRadio matchRadios;
 
-    public CriteriaWidget(IViewContext<ICommonClientServiceAsync> viewContext)
+    public DetailedSearchCriteriaWidget(IViewContext<ICommonClientServiceAsync> viewContext,
+            EntityKind entityKind)
     {
         setLayoutOnChange(true);
-        criteriaWidgets = new ArrayList<CriterionWidget>();
+        criteriaWidgets = new ArrayList<DetailedSearchCriterionWidget>();
         add(matchRadios =
                 new MatchCriteriaRadio(viewContext.getMessage(Dict.MATCH_ALL), viewContext
                         .getMessage(Dict.MATCH_ANY)));
-        addCriterion(new CriterionWidget(viewContext, this, FIRST_ID_SUFFIX));
+        addCriterion(new DetailedSearchCriterionWidget(viewContext, this, FIRST_ID_SUFFIX, entityKind));
     }
 
     private void enableRemovalIfOneExists(final boolean enable)
@@ -61,9 +64,9 @@ public class CriteriaWidget extends VerticalPanel
     }
 
     /**
-     * Adds given {@link CriterionWidget} to the panel.
+     * Adds given {@link DetailedSearchCriterionWidget} to the panel.
      */
-    void addCriterion(CriterionWidget criterion)
+    void addCriterion(DetailedSearchCriterionWidget criterion)
     {
         enableRemovalIfOneExists(true);
         criteriaWidgets.add(criterion);
@@ -73,10 +76,11 @@ public class CriteriaWidget extends VerticalPanel
     }
 
     /**
-     * Removes given {@link CriterionWidget} from the panel, unless it is the only one that left. In
-     * this case the state of chosen {@link CriterionWidget} is set to initial value (reset).
+     * Removes given {@link DetailedSearchCriterionWidget} from the panel, unless it is the only one that
+     * left. In this case the state of chosen {@link DetailedSearchCriterionWidget} is set to initial value
+     * (reset).
      */
-    void removeCriterion(CriterionWidget w)
+    void removeCriterion(DetailedSearchCriterionWidget w)
     {
         if (criteriaWidgets.size() > 1)
         {
@@ -98,13 +102,13 @@ public class CriteriaWidget extends VerticalPanel
      * @return <b>search criteria</b> extracted from criteria widgets and "match" radio buttons<br>
      *         <b>null</b> if no criteria were selected
      */
-    public DataSetSearchCriteria tryGetCriteria()
+    public DetailedSearchCriteria tryGetCriteria()
     {
 
-        List<DataSetSearchCriterion> criteria = new ArrayList<DataSetSearchCriterion>();
-        for (CriterionWidget cw : criteriaWidgets)
+        List<DetailedSearchCriterion> criteria = new ArrayList<DetailedSearchCriterion>();
+        for (DetailedSearchCriterionWidget cw : criteriaWidgets)
         {
-            DataSetSearchCriterion value = cw.tryGetValue();
+            DetailedSearchCriterion value = cw.tryGetValue();
             if (value != null)
             {
                 criteria.add(value);
@@ -112,7 +116,7 @@ public class CriteriaWidget extends VerticalPanel
         }
         if (criteria.size() > 0)
         {
-            final DataSetSearchCriteria result = new DataSetSearchCriteria();
+            final DetailedSearchCriteria result = new DetailedSearchCriteria();
             result.setConnection(matchRadios.getSelected());
             result.setCriteria(criteria);
             return result;
@@ -128,7 +132,7 @@ public class CriteriaWidget extends VerticalPanel
         sb.append(matchRadios.getSelectedLabel());
         sb.append(": ");
         boolean first = true;
-        for (CriterionWidget cw : criteriaWidgets)
+        for (DetailedSearchCriterionWidget cw : criteriaWidgets)
         {
             String desc = cw.tryGetDescription();
             if (desc != null)
@@ -153,8 +157,8 @@ public class CriteriaWidget extends VerticalPanel
     public void reset()
     {
         matchRadios.reset();
-        List<CriterionWidget> list = new ArrayList<CriterionWidget>(criteriaWidgets);
-        for (CriterionWidget cw : list)
+        List<DetailedSearchCriterionWidget> list = new ArrayList<DetailedSearchCriterionWidget>(criteriaWidgets);
+        for (DetailedSearchCriterionWidget cw : list)
         {
             removeCriterion(cw);
         }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/CriterionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java
similarity index 73%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/CriterionWidget.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java
index 919dbd5108c..f9a5a83f831 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/CriterionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search;
 
 import java.util.List;
 
@@ -31,16 +31,18 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriterion;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchField;
+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.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 
 /**
- * Allows to specify one criterion.
+ * Allows to specify one detailed search criterion.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
-public class CriterionWidget extends HorizontalPanel
+public class DetailedSearchCriterionWidget extends HorizontalPanel
 {
 
     private static final String PREFIX = "data_set_search_criterion";
@@ -53,9 +55,9 @@ public class CriterionWidget extends HorizontalPanel
 
     public static final String ADD_BUTTON_ID_PREFIX = ID + "_add";
 
-    private final CriteriaWidget parent;
+    private final DetailedSearchCriteriaWidget parent;
 
-    private final DataSetSearchFieldsSelectionWidget nameField;
+    private final DetailedSearchFieldsSelectionWidget nameField;
 
     private final String idSuffix;
 
@@ -65,14 +67,15 @@ public class CriterionWidget extends HorizontalPanel
 
     private int generatedChildren;
 
-    public CriterionWidget(IViewContext<ICommonClientServiceAsync> viewContext,
-            CriteriaWidget parent, String idSuffix)
+    public DetailedSearchCriterionWidget(IViewContext<ICommonClientServiceAsync> viewContext,
+            DetailedSearchCriteriaWidget parent, String idSuffix, EntityKind entityKind)
     {
-        this(parent, idSuffix, new DataSetSearchFieldsSelectionWidget(viewContext, idSuffix));
+        this(parent, idSuffix, new DetailedSearchFieldsSelectionWidget(viewContext, idSuffix,
+                entityKind));
     }
 
-    private CriterionWidget(final CriteriaWidget parent, String idSuffix,
-            DataSetSearchFieldsSelectionWidget nameField)
+    private DetailedSearchCriterionWidget(final DetailedSearchCriteriaWidget parent,
+            String idSuffix, DetailedSearchFieldsSelectionWidget nameField)
     {
         generatedChildren = 0;
         this.parent = parent;
@@ -134,13 +137,15 @@ public class CriterionWidget extends HorizontalPanel
     }
 
     /**
-     * Adds a new {@link CriterionWidget} coping data from given the <em>name field</em>.
+     * Adds a new {@link DetailedSearchCriterionWidget} coping data from given the
+     * <em>name field</em>.
      */
     private void createNew()
     {
-        CriterionWidget newCriterion =
-                new CriterionWidget(parent, getChildId(), new DataSetSearchFieldsSelectionWidget(
-                        nameField, getChildId()));
+        DetailedSearchCriterionWidget newCriterion =
+                new DetailedSearchCriterionWidget(parent, getChildId(),
+                        new DetailedSearchFieldsSelectionWidget(nameField, getChildId(), nameField
+                                .getEntityKind()));
         parent.addCriterion(newCriterion);
         generatedChildren++;
     }
@@ -160,17 +165,17 @@ public class CriterionWidget extends HorizontalPanel
     }
 
     /**
-     * Returns {@link DataSetSearchCriterion} for selected <em>name</em> and <em>value</em>. If
+     * Returns {@link DetailedSearchCriterion} for selected <em>name</em> and <em>value</em>. If
      * either <em>name</em> or <em>value</em> is not specified, returns null.
      */
-    public DataSetSearchCriterion tryGetValue()
+    public DetailedSearchCriterion tryGetValue()
     {
 
         final String selectedValue = valueField.getValue();
-        final DataSetSearchField selectedFieldName = nameField.tryGetSelectedField();
+        final DetailedSearchField selectedFieldName = nameField.tryGetSelectedField();
         if (selectedFieldName != null && StringUtils.isBlank(selectedValue) == false)
         {
-            return new DataSetSearchCriterion(selectedFieldName, selectedValue);
+            return new DetailedSearchCriterion(selectedFieldName, selectedValue);
         }
         return null;
 
@@ -178,7 +183,7 @@ public class CriterionWidget extends HorizontalPanel
 
     public String tryGetDescription()
     {
-        DataSetSearchCriterion criterion = tryGetValue();
+        DetailedSearchCriterion criterion = tryGetValue();
         String name = nameField.tryGetSelectedCode();
         if (criterion == null || name == null)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java
similarity index 50%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java
index 22953a295e9..37230bc0113 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -27,7 +27,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.DataSetSearchFieldComboModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.DetailedSearchFieldComboModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.PropertyTypeRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.entity.PropertyTypesFilterUtil;
@@ -35,24 +35,28 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchField;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+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.IAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
- * {@link ComboBox} containing list of search fields loaded from the server (property types) and
+ * {@link ComboBox} containing list of detailed search fields loaded from the server (property types) and
  * static ones.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
 // TODO 2009-02-13, Tomasz Pylak: fetching of property types is done every time a new widget is
 // created, although all of them are identical. It should be done outside of this class and passed
 // to it.
-public final class DataSetSearchFieldsSelectionWidget extends
-        DropDownList<DataSetSearchFieldComboModel, PropertyType>
+// TODO 2009-08-31, Piotr Buczek: write code for remaining entity kinds
+public final class DetailedSearchFieldsSelectionWidget extends
+        DropDownList<DetailedSearchFieldComboModel, PropertyType>
 {
     private static final int WIDTH = 200;
 
@@ -64,20 +68,29 @@ public final class DataSetSearchFieldsSelectionWidget extends
 
     private final IViewContext<ICommonClientServiceAsync> viewContext;
 
+    private final EntityKind entityKind;
+
     private boolean dataLoaded;
 
     private List<PropertyType> propertyTypes;
 
-    public DataSetSearchFieldsSelectionWidget(
-            final IViewContext<ICommonClientServiceAsync> viewContext, final String idSuffix)
+    public DetailedSearchFieldsSelectionWidget(
+            final IViewContext<ICommonClientServiceAsync> viewContext, final String idSuffix,
+            final EntityKind entityKind)
     {
         super(viewContext, SUFFIX + idSuffix, Dict.PROPERTY_TYPE, ModelDataPropertyNames.CODE,
                 CHOOSE_SUFFIX, EMPTY_RESULT_SUFFIX);
         this.viewContext = viewContext;
+        this.entityKind = entityKind;
         dataLoaded = false;
         setAllowBlank(true);
     }
 
+    public EntityKind getEntityKind()
+    {
+        return entityKind;
+    }
+
     @Override
     /*
      * * Always returns null.
@@ -88,12 +101,12 @@ public final class DataSetSearchFieldsSelectionWidget extends
     }
 
     /**
-     * Returns {@link DataSetSearchField} connected with selected option, or null - if nothing
+     * Returns {@link DetailedSearchField} connected with selected option, or null - if nothing
      * selected.
      */
-    public DataSetSearchField tryGetSelectedField()
+    public DetailedSearchField tryGetSelectedField()
     {
-        return (DataSetSearchField) GWTUtils.tryGetSingleSelected(this);
+        return (DetailedSearchField) GWTUtils.tryGetSingleSelected(this);
     }
 
     /**
@@ -110,11 +123,11 @@ public final class DataSetSearchFieldsSelectionWidget extends
         return propertyTypes;
     }
 
-    public DataSetSearchFieldsSelectionWidget(DataSetSearchFieldsSelectionWidget source,
-            final String idSuffix)
+    public DetailedSearchFieldsSelectionWidget(DetailedSearchFieldsSelectionWidget source,
+            final String idSuffix, final EntityKind entityKind)
     {
-        this(source.viewContext, idSuffix);
-        ListStore<DataSetSearchFieldComboModel> sourceStore = source.getStore();
+        this(source.viewContext, idSuffix, entityKind);
+        ListStore<DetailedSearchFieldComboModel> sourceStore = source.getStore();
         sourceStore.clearFilters();
         this.setValue(findAnyFieldItem(sourceStore.getModels()));
         setWidth(WIDTH);
@@ -135,9 +148,9 @@ public final class DataSetSearchFieldsSelectionWidget extends
         {
             propertyTypes = result.getList();
 
-            final ListStore<DataSetSearchFieldComboModel> propertyTypeStore = getStore();
+            final ListStore<DetailedSearchFieldComboModel> propertyTypeStore = getStore();
             propertyTypeStore.removeAll();
-            List<DataSetSearchFieldComboModel> items = convertItems(propertyTypes);
+            List<DetailedSearchFieldComboModel> items = convertItems(propertyTypes);
             propertyTypeStore.add(items);
             if (propertyTypeStore.getCount() > 0)
             {
@@ -154,18 +167,18 @@ public final class DataSetSearchFieldsSelectionWidget extends
         }
     }
 
-    private static DataSetSearchFieldComboModel findAnyFieldItem(
-            List<DataSetSearchFieldComboModel> items)
+    private static DetailedSearchFieldComboModel findAnyFieldItem(
+            List<DetailedSearchFieldComboModel> items)
     {
-        return findFieldItem(items, DataSetSearchFieldKind.ANY_FIELD);
+        return findFieldItem(items, DetailedSearchFieldKind.ANY_FIELD);
     }
 
-    private static DataSetSearchFieldComboModel findFieldItem(
-            List<DataSetSearchFieldComboModel> items, DataSetSearchFieldKind fieldKind)
+    private static DetailedSearchFieldComboModel findFieldItem(
+            List<DetailedSearchFieldComboModel> items, DetailedSearchFieldKind fieldKind)
     {
-        for (DataSetSearchFieldComboModel item : items)
+        for (DetailedSearchFieldComboModel item : items)
         {
-            DataSetSearchField field = item.getField();
+            DetailedSearchField field = item.getField();
             if (field.getKind() == fieldKind)
             {
                 return item;
@@ -176,85 +189,114 @@ public final class DataSetSearchFieldsSelectionWidget extends
     }
 
     @Override
-    protected List<DataSetSearchFieldComboModel> convertItems(List<PropertyType> types)
+    protected List<DetailedSearchFieldComboModel> convertItems(List<PropertyType> types)
     {
-        final List<DataSetSearchFieldComboModel> result =
-                new ArrayList<DataSetSearchFieldComboModel>();
-        for (DataSetSearchFieldKind field : DataSetSearchFieldKind.getSimpleFields())
+        final List<DetailedSearchFieldComboModel> result =
+                new ArrayList<DetailedSearchFieldComboModel>();
+        for (IAttributeSearchFieldKind attributeFieldKind : getAttributeFieldKinds())
         {
-            DataSetSearchField simpleField = DataSetSearchField.createSimpleField(field);
-            addFieldComboModel(result, simpleField);
+            DetailedSearchField attributeField =
+                    DetailedSearchField.createAttributeField(attributeFieldKind);
+            addAttributeFieldComboModel(result, attributeField, attributeFieldKind);
         }
         Collections.sort(types);
 
-        List<String> allDataSetProps = addDataSetPropertyTypes(result, types);
+        List<String> allEntityPropertyCodes = addEntityPropertyTypes(result, types);
 
-        DataSetSearchField anyDataSetProperty =
-                DataSetSearchField.createAnyDataSetProperty(allDataSetProps);
-        addFieldComboModel(result, anyDataSetProperty);
+        DetailedSearchField anyPropertyField =
+                DetailedSearchField.createAnyPropertyField(allEntityPropertyCodes);
+        addComplexFieldComboModel(result, anyPropertyField);
 
-        DataSetSearchField anyField = DataSetSearchField.createAnyField(allDataSetProps);
-        addFieldComboModel(result, anyField);
+        DetailedSearchField anyField = DetailedSearchField.createAnyField(allEntityPropertyCodes);
+        addComplexFieldComboModel(result, anyField);
 
         return result;
     }
 
-    private void addFieldComboModel(List<DataSetSearchFieldComboModel> result,
-            DataSetSearchField field)
+    private IAttributeSearchFieldKind[] getAttributeFieldKinds()
     {
-        result.add(createComboModel(field));
+        switch (entityKind)
+        {
+            case DATA_SET:
+                return DataSetAttributeSearchFieldKind.values();
+            default:
+                throw new IllegalArgumentException("not yet implemented");
+        }
     }
 
-    private static DataSetSearchFieldComboModel createComboModel(DataSetSearchField simpleField)
+    private void addComplexFieldComboModel(List<DetailedSearchFieldComboModel> result,
+            DetailedSearchField field)
     {
-        return new DataSetSearchFieldComboModel(getDisplayName(simpleField.getKind()), simpleField);
+        assert field.getKind() != DetailedSearchFieldKind.ATTRIBUTE : "attribute field not allowed";
+        result.add(createComplexFieldComboModel(field));
     }
 
-    private static List<String> addDataSetPropertyTypes(
-            final List<DataSetSearchFieldComboModel> result, List<PropertyType> propertyTypes)
+    private void addAttributeFieldComboModel(List<DetailedSearchFieldComboModel> result,
+            DetailedSearchField attributeField, IAttributeSearchFieldKind attributeFieldKind)
+    {
+        assert attributeField.getKind() == DetailedSearchFieldKind.ATTRIBUTE : "attribute field required";
+        result.add(createAttributeFieldComboModel(attributeField, attributeFieldKind));
+    }
+
+    private static DetailedSearchFieldComboModel createComplexFieldComboModel(
+            DetailedSearchField complexField)
+    {
+        assert complexField.getKind() != DetailedSearchFieldKind.ATTRIBUTE : "attribute field not allowed";
+        return new DetailedSearchFieldComboModel(getDisplayName(complexField), complexField);
+    }
+
+    private static DetailedSearchFieldComboModel createAttributeFieldComboModel(
+            DetailedSearchField attributeField, IAttributeSearchFieldKind attributeFieldKind)
+    {
+        assert attributeField.getKind() == DetailedSearchFieldKind.ATTRIBUTE : "attribute field required";
+        return new DetailedSearchFieldComboModel(getDisplayName(attributeFieldKind), attributeField);
+    }
+
+    private List<String> addEntityPropertyTypes(final List<DetailedSearchFieldComboModel> result,
+            List<PropertyType> allPropertyTypes)
     {
         List<PropertyType> relevantPropertyTypes =
-                PropertyTypesFilterUtil.filterDataSetPropertyTypes(propertyTypes);
-        return addPropertyTypes(result, relevantPropertyTypes, EntityKind.DATA_SET);
+                PropertyTypesFilterUtil.filterPropertyTypesForEntityKind(allPropertyTypes,
+                        entityKind);
+        return addPropertyTypes(result, relevantPropertyTypes);
     }
 
     // returns codes of added properties
-    private static List<String> addPropertyTypes(final List<DataSetSearchFieldComboModel> result,
-            List<PropertyType> types, EntityKind kind)
+    private static List<String> addPropertyTypes(final List<DetailedSearchFieldComboModel> result,
+            List<PropertyType> types)
     {
-        List<String> allProps = new ArrayList<String>();
+        final List<String> allProps = new ArrayList<String>();
         for (final PropertyType st : types)
         {
-            String code = st.getCode();
-            allProps.add(code);
-            DataSetSearchField field;
-            switch (kind)
-            {
-                case DATA_SET:
-                    field = DataSetSearchField.createDataSetProperty(code);
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unsupported entity kind.");
-            }
-            DataSetSearchFieldComboModel comboModel = createPropertyComboModel(st, field, types);
+            final String propertyCode = st.getCode();
+            allProps.add(propertyCode);
+            final DetailedSearchField field = DetailedSearchField.createPropertyField(propertyCode);
+            final DetailedSearchFieldComboModel comboModel =
+                    createPropertyComboModel(st, field, types);
             result.add(comboModel);
         }
         return allProps;
     }
 
-    private static DataSetSearchFieldComboModel createPropertyComboModel(
-            final PropertyType propertyType, DataSetSearchField searchField,
+    private static DetailedSearchFieldComboModel createPropertyComboModel(
+            final PropertyType propertyType, DetailedSearchField searchField,
             List<PropertyType> types)
     {
-        String prefix = getDisplayName(searchField.getKind());
+        String prefix = getDisplayName(searchField);
         String property = PropertyTypeRenderer.getDisplayName(propertyType, types);
         String code = prefix + " \'" + property + "\'";
-        return new DataSetSearchFieldComboModel(code, searchField);
+        return new DetailedSearchFieldComboModel(code, searchField);
+    }
+
+    private static String getDisplayName(DetailedSearchField complexField)
+    {
+        assert complexField.getKind() != DetailedSearchFieldKind.ATTRIBUTE : "attribute field not allowed";
+        return complexField.getKind().getDescription();
     }
 
-    private static String getDisplayName(DataSetSearchFieldKind field)
+    private static String getDisplayName(IAttributeSearchFieldKind attributefieldKind)
     {
-        return field.description();
+        return attributefieldKind.getDescription();
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java
similarity index 73%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchToolbar.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java
index 6da5beb74bb..923981b794f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java
@@ -1,4 +1,4 @@
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search;
 
 import java.util.List;
 
@@ -12,23 +12,24 @@ import com.google.gwt.user.client.Element;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 
 /**
- * Contains a button opening {@link DataSetSearchWindow}.
+ * Contains a button opening {@link DetailedSearchWindow}.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
-class DataSetSearchToolbar extends ToolBar
+public class DetailedSearchToolbar extends ToolBar
 {
     private LabelToolItem description;
 
-    private final DataSetSearchHitGrid grid;
+    private final IDetailedSearchHitGrid grid;
 
-    private final DataSetSearchWindow searchWindow;
+    private final DetailedSearchWindow searchWindow;
 
-    public DataSetSearchToolbar(final DataSetSearchHitGrid grid, String buttonName,
-            final DataSetSearchWindow searchWindow)
+    public DetailedSearchToolbar(final IDetailedSearchHitGrid grid, String buttonName,
+            final DetailedSearchWindow searchWindow)
     {
         this.grid = grid;
         this.searchWindow = searchWindow;
@@ -44,7 +45,7 @@ class DataSetSearchToolbar extends ToolBar
             }));
     }
 
-    public void updateSearchResults(DataSetSearchCriteria searchCriteria, String searchDescription,
+    public void updateSearchResults(DetailedSearchCriteria searchCriteria, String searchDescription,
             List<PropertyType> availablePropertyTypes)
     {
         grid.refresh(searchCriteria, availablePropertyTypes);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchWindow.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java
similarity index 75%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchWindow.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java
index 8b9a3de702f..99afd1ed4fa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchWindow.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java
@@ -1,4 +1,4 @@
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search;
 
 import java.util.List;
 
@@ -14,15 +14,18 @@ import com.extjs.gxt.ui.client.widget.layout.FitLayout;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetSearchHitGrid;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 
 /**
- * Shows {@link CriteriaWidget}, allowing to specify search criteria.
+ * Shows {@link DetailedSearchCriteriaWidget}, allowing to specify detailed search criteria.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
-public class DataSetSearchWindow extends Dialog
+public class DetailedSearchWindow extends Dialog
 {
     public static final String SEARCH_BUTTON_ID = DataSetSearchHitGrid.BROWSER_ID + "search_button";
 
@@ -32,18 +35,20 @@ public class DataSetSearchWindow extends Dialog
 
     private static final int WIDTH = 550;
 
-    private CriteriaWidget criteriaWidget;
+    private DetailedSearchCriteriaWidget criteriaWidget;
 
-    private DataSetSearchToolbar updateListener;
+    private DetailedSearchToolbar updateListener;
 
-    public DataSetSearchWindow(final IViewContext<ICommonClientServiceAsync> viewContext)
+    public DetailedSearchWindow(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final EntityKind entityKind)
     {
         setSize(WIDTH, HEIGHT);
         setModal(true);
         setScrollMode(Scroll.AUTOY);
         setLayout(new FitLayout());
         setResizable(false);
-        add(criteriaWidget = new CriteriaWidget(viewContext), new FitData(MARGIN));
+        add(criteriaWidget = new DetailedSearchCriteriaWidget(viewContext, entityKind),
+                new FitData(MARGIN));
         final ButtonBar bar = new ButtonBar();
         bar.add(new Button(viewContext.getMessage(Dict.BUTTON_CANCEL),
                 new SelectionListener<ButtonEvent>()
@@ -72,7 +77,8 @@ public class DataSetSearchWindow extends Dialog
                                 {
                                     List<PropertyType> availablePropertyTypes =
                                             criteriaWidget.getAvailablePropertyTypes();
-                                    DataSetSearchCriteria criteria = criteriaWidget.tryGetCriteria();
+                                    DetailedSearchCriteria criteria =
+                                            criteriaWidget.tryGetCriteria();
                                     String criteriaDescription =
                                             criteriaWidget.getCriteriaDescription();
                                     updateListener.updateSearchResults(criteria,
@@ -87,7 +93,7 @@ public class DataSetSearchWindow extends Dialog
         setButtons("");
     }
 
-    public void setUpdateListener(DataSetSearchToolbar toolbar)
+    public void setUpdateListener(DetailedSearchToolbar toolbar)
     {
         this.updateListener = toolbar;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/IDetailedSearchHitGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/IDetailedSearchHitGrid.java
new file mode 100644
index 00000000000..b333e7273c7
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/IDetailedSearchHitGrid.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009 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.client.web.client.application.ui.search;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
+
+/**
+ * Interface for grids that show results of detailed entity search.
+ * 
+ * @author Piotr Buczek
+ */
+public interface IDetailedSearchHitGrid
+{
+
+    /** refreshes grid with new criteria and properties */
+    void refresh(DetailedSearchCriteria newCriteria, List<PropertyType> propertyTypes);
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/MatchCriteriaRadio.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/MatchCriteriaRadio.java
new file mode 100644
index 00000000000..55527fc73a2
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/MatchCriteriaRadio.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009 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.client.web.client.application.ui.search;
+
+import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
+import com.extjs.gxt.ui.client.Style.VerticalAlignment;
+import com.extjs.gxt.ui.client.widget.HorizontalPanel;
+import com.extjs.gxt.ui.client.widget.form.Radio;
+import com.extjs.gxt.ui.client.widget.form.RadioGroup;
+import com.extjs.gxt.ui.client.widget.layout.TableData;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
+
+/**
+ * Widget which enables to select {@link SearchCriteriaConnection} type.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class MatchCriteriaRadio extends HorizontalPanel
+{
+    private static final String PREFIX = "match_criteria_radio";
+
+    private static final String ID = GenericConstants.ID_PREFIX + PREFIX;
+
+    public static final String OR_RADIO_ID = ID + "_or";
+
+    public static final String AND_RADIO_ID = ID + "_and";
+
+    private final Radio orRadio;
+
+    private final Radio andRadio;
+
+    public MatchCriteriaRadio(String matchAll, String matchAny)
+    {
+        RadioGroup group = new RadioGroup();
+        andRadio = new Radio();
+        andRadio.setId(AND_RADIO_ID);
+        andRadio.setBoxLabel(matchAll);
+
+        orRadio = new Radio();
+        orRadio.setId(OR_RADIO_ID);
+        orRadio.setBoxLabel(matchAny);
+
+        group.add(andRadio);
+        group.add(orRadio);
+
+        reset();
+        final TableData radioData =
+                new TableData(HorizontalAlignment.CENTER, VerticalAlignment.MIDDLE);
+        radioData.setPadding(5);
+        add(group, radioData);
+    }
+
+    public void reset()
+    {
+        orRadio.setValue(true);
+    }
+
+    String getSelectedLabel()
+    {
+        return isAndSelected() ? andRadio.getBoxLabel() : orRadio.getBoxLabel();
+    }
+
+    SearchCriteriaConnection getSelected()
+    {
+        if (isAndSelected())
+        {
+            return SearchCriteriaConnection.MATCH_ALL;
+        } else
+        {
+            return SearchCriteriaConnection.MATCH_ANY;
+        }
+    }
+
+    private boolean isAndSelected()
+    {
+        return andRadio.getValue() != null && andRadio.getValue().booleanValue() == true;
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index 40a7dd146d2..adf06ac10cd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -80,7 +80,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AttachmentHolderKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelatedEntities;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
@@ -117,6 +116,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleSetCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -501,7 +501,7 @@ public final class CommonClientService extends AbstractClientService implements
                 commonServer, sessionToken, listCriteria.getCriteria()));
     }
 
-    public ResultSetWithEntityTypes<ExternalData> searchForDataSets(DataSetSearchCriteria criteria,
+    public ResultSetWithEntityTypes<ExternalData> searchForDataSets(DetailedSearchCriteria criteria,
             final IResultSetConfig<String, ExternalData> resultSetConfig)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/ListDataSetSearchOriginalDataProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/ListDataSetSearchOriginalDataProvider.java
index 60c794ddd9b..147f23ea85a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/ListDataSetSearchOriginalDataProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/ListDataSetSearchOriginalDataProvider.java
@@ -4,8 +4,8 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IOriginalDataProvider;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 
 /**
  * A {@link IOriginalDataProvider} implementation for search data sets.
@@ -16,10 +16,10 @@ final class ListDataSetSearchOriginalDataProvider extends
         AbstractOriginalDataProvider<ExternalData>
 {
 
-    private final DataSetSearchCriteria criteria;
+    private final DetailedSearchCriteria criteria;
 
     ListDataSetSearchOriginalDataProvider(final ICommonServer commonServer,
-            final String sessionToken, final DataSetSearchCriteria criteria)
+            final String sessionToken, final DetailedSearchCriteria criteria)
     {
         super(commonServer, sessionToken);
         this.criteria = criteria;
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 d50322bbdae..2334698a79d 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
@@ -75,7 +75,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelatedEntities;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
@@ -108,6 +107,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -740,7 +740,7 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
 
     }
 
-    public List<ExternalData> searchForDataSets(String sessionToken, DataSetSearchCriteria criteria)
+    public List<ExternalData> searchForDataSets(String sessionToken, DetailedSearchCriteria criteria)
     {
         final Session session = getSessionManager().getSession(sessionToken);
         try
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index 674c48ba445..5ea77d822c9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -33,7 +33,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelatedEntities;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
@@ -64,6 +63,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -382,7 +382,7 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 projectIdentifier, attachments.size());
     }
 
-    public List<ExternalData> searchForDataSets(String sessionToken, DataSetSearchCriteria criteria)
+    public List<ExternalData> searchForDataSets(String sessionToken, DetailedSearchCriteria criteria)
     {
         logAccess(sessionToken, "search_for_datasets");
         return null;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IHibernateSearchDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IHibernateSearchDAO.java
index 7f3d832c408..c712ad76eb8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IHibernateSearchDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IHibernateSearchDAO.java
@@ -21,8 +21,8 @@ import java.util.List;
 import org.springframework.dao.DataAccessException;
 
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.HibernateSearchDataProvider;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 
@@ -44,5 +44,5 @@ public interface IHibernateSearchDAO
             throws DataAccessException;
 
     /** search for datasets using the specified criteria */
-    public List<ExternalDataPE> searchForDataSets(DataSetSearchCriteria criteria);
+    public List<ExternalDataPE> searchForDataSets(DetailedSearchCriteria criteria);
 }
\ No newline at end of file
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 14a7861c7eb..c0defd53010 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
@@ -61,10 +61,11 @@ import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.LuceneQueryBuilder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BasicEntityType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants;
@@ -399,7 +400,7 @@ final class HibernateSearchDAO extends HibernateDaoSupport implements IHibernate
         }
     }
 
-    public List<ExternalDataPE> searchForDataSets(final DataSetSearchCriteria criteria)
+    public List<ExternalDataPE> searchForDataSets(final DetailedSearchCriteria criteria)
     {
         final List<ExternalDataPE> list =
                 AbstractDAO.cast((List<?>) getHibernateTemplate().execute(new HibernateCallback()
@@ -419,10 +420,10 @@ final class HibernateSearchDAO extends HibernateDaoSupport implements IHibernate
         return list;
     }
 
-    private List<ExternalDataPE> searchForDataSets(Session session,
-            DataSetSearchCriteria datasetSearchCriteria)
+    private List<ExternalDataPE> searchForDataSets(Session session, DetailedSearchCriteria searchCriteria)
     {
-        Query query = LuceneQueryBuilder.createQuery(datasetSearchCriteria);
+        Query query =
+                LuceneQueryBuilder.createDetailedSearchQuery(searchCriteria, EntityKind.DATA_SET);
         final FullTextSession fullTextSession = Search.getFullTextSession(session);
         final FullTextQuery hibernateQuery =
                 fullTextSession.createFullTextQuery(query, ExternalDataPE.class);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/LuceneQueryBuilder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/LuceneQueryBuilder.java
index 044d9c41d57..78e4086347e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/LuceneQueryBuilder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/LuceneQueryBuilder.java
@@ -16,13 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search;
 
-import static ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants.CODE;
-
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
-import org.apache.log4j.Logger;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.queryParser.ParseException;
 import org.apache.lucene.queryParser.QueryParser;
@@ -31,150 +26,21 @@ import org.apache.lucene.search.Query;
 import org.apache.lucene.search.BooleanClause.Occur;
 
 import ch.rinn.restrictions.Private;
-import ch.systemsx.cisd.common.exceptions.InternalErr;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.common.logging.LogCategory;
-import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriterion;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchField;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchFieldKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
-import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants;
-import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.detailed.DetailedQueryBuilder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 
 /**
  * @author Tomasz Pylak
  */
 public class LuceneQueryBuilder
 {
-    private final static Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, LuceneQueryBuilder.class);
-
     /** @throws UserFailureException when some search patterns are incorrect */
-    public static Query createQuery(DataSetSearchCriteria dataSetCriteria)
-            throws UserFailureException
-    {
-        List<DataSetSearchCriterion> criteria = dataSetCriteria.getCriteria();
-        Occur occureCondition = createOccureCondition(dataSetCriteria.getConnection());
-
-        Analyzer analyzer = createSearchAnalyzer();
-        BooleanQuery resultQuery = new BooleanQuery();
-        for (DataSetSearchCriterion criterion : criteria)
-        {
-            List<String> fieldNames = getIndexFieldNames(criterion.getField());
-            String searchPattern = LuceneQueryBuilder.adaptQuery(criterion.getValue());
-
-            Query luceneQuery = parseQuery(fieldNames, searchPattern, analyzer);
-            resultQuery.add(luceneQuery, occureCondition);
-        }
-        operationLog.debug("Lucene datasets query: " + resultQuery.toString());
-        return resultQuery;
-    }
-
-    private static Occur createOccureCondition(SearchCriteriaConnection connection)
-    {
-        switch (connection)
-        {
-            case MATCH_ALL:
-                return Occur.MUST;
-            case MATCH_ANY:
-                return Occur.SHOULD;
-            default:
-                throw InternalErr.error("unknown enum " + connection);
-        }
-    }
-
-    private static List<String> getIndexFieldNames(DataSetSearchField searchField)
-    {
-        DataSetSearchFieldKind fieldKind = searchField.getKind();
-        switch (fieldKind)
-        {
-            case ANY_DATA_SET_PROPERTY:
-                return getDataSetPropertyIndexFields(searchField);
-            case ANY_FIELD:
-                List<String> fields = new ArrayList<String>();
-                fields.addAll(getDataSetPropertyIndexFields(searchField));
-                fields.addAll(getAllIndexSimpleFieldNames());
-                return fields;
-            default:
-                return Arrays.asList(getSimpleFieldIndexName(searchField));
-        }
-    }
-
-    private static String getSimpleFieldIndexName(DataSetSearchField searchField)
-    {
-        String indexFieldName = tryGetIndexFieldName(searchField);
-        assert indexFieldName != null;
-        return indexFieldName;
-    }
-
-    private static List<String> getAllIndexSimpleFieldNames()
-    {
-        List<DataSetSearchFieldKind> simpleFieldKinds = DataSetSearchFieldKind.getSimpleFields();
-        List<String> fields = new ArrayList<String>();
-        for (DataSetSearchFieldKind simpleFieldKind : simpleFieldKinds)
-        {
-            DataSetSearchField simpleField = DataSetSearchField.createSimpleField(simpleFieldKind);
-            fields.add(getSimpleFieldIndexName(simpleField));
-        }
-        return fields;
-    }
-
-    private static List<String> getDataSetPropertyIndexFields(DataSetSearchField searchField)
-    {
-        return getPropertyIndexFields(searchField.getAllDataSetPropertyCodesOrNull(),
-                EntityKind.DATA_SET);
-    }
-
-    private static List<String> getPropertyIndexFields(List<String> allPropertyCodes,
-            EntityKind kind)
-    {
-        List<String> fields = new ArrayList<String>();
-        assert allPropertyCodes != null;
-        for (String propertyCode : allPropertyCodes)
-        {
-            DataSetSearchField searchField;
-            switch (kind)
-            {
-                case DATA_SET:
-                    searchField = DataSetSearchField.createDataSetProperty(propertyCode);
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unsupported entity kind");
-            }
-            String fieldIndex = tryGetIndexFieldName(searchField);
-            fields.add(fieldIndex);
-        }
-        return fields;
-    }
-
-    // returns the field name in the index for the specified dataset query field
-    private static String tryGetIndexFieldName(DataSetSearchField searchField)
-    {
-        DataSetSearchFieldKind fieldKind = searchField.getKind();
-        switch (fieldKind)
-        {
-            case DATA_SET_CODE:
-                return CODE;
-            case DATA_SET_TYPE:
-                return SearchFieldConstants.PREFIX_ENTITY_TYPE + CODE;
-            case DATA_SET_PROPERTY:
-                return getPropertyIndexField(searchField.getPropertyCode());
-            case FILE_TYPE:
-                return SearchFieldConstants.PREFIX_FILE_FORMAT_TYPE + CODE;
-            case ANY_DATA_SET_PROPERTY:
-            case ANY_FIELD:
-                return null;
-            default:
-                throw InternalErr.error("unknown enum " + fieldKind);
-        }
-    }
-
-    private static String getPropertyIndexField(String propertyCode)
+    public static Query createDetailedSearchQuery(DetailedSearchCriteria searchCriteria,
+            EntityKind entityKind)
     {
-        assert propertyCode != null : "property code is null";
-        return SearchFieldConstants.PREFIX_PROPERTIES + propertyCode;
+        return DetailedQueryBuilder.createQuery(searchCriteria, entityKind);
     }
 
     public static String adaptQuery(String userQuery)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/DetailedQueryBuilder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/DetailedQueryBuilder.java
new file mode 100644
index 00000000000..acd6eefa94b
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/DetailedQueryBuilder.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2009 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.server.dataaccess.db.search.detailed;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.BooleanClause.Occur;
+
+import ch.systemsx.cisd.common.exceptions.InternalErr;
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.LuceneQueryBuilder;
+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.DetailedSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
+
+/**
+ * Builder for detailed lucene queries for different entity kinds.
+ * 
+ * @author Piotr Buczek
+ */
+public class DetailedQueryBuilder
+{
+    private final static Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, DetailedQueryBuilder.class);
+
+    /** @throws UserFailureException when some search patterns are incorrect */
+    public static Query createQuery(DetailedSearchCriteria searchCriteria, EntityKind entityKind)
+            throws UserFailureException
+    {
+        final DetailedQueryBuilder builder = new DetailedQueryBuilder(entityKind);
+        final Query resultQuery = builder.createQuery(searchCriteria);
+        operationLog.debug("Lucene detailed query: " + resultQuery.toString());
+        return resultQuery;
+    }
+
+    //
+    // LuceneDetailedQueryBuilder
+    //
+
+    private final EntityKind entityKind;
+
+    private DetailedQueryBuilder(EntityKind entityKind)
+    {
+        this.entityKind = entityKind;
+    }
+
+    private Query createQuery(DetailedSearchCriteria searchCriteria)
+    {
+        List<DetailedSearchCriterion> criteria = searchCriteria.getCriteria();
+        Occur occureCondition = createOccureCondition(searchCriteria.getConnection());
+
+        Analyzer analyzer = LuceneQueryBuilder.createSearchAnalyzer();
+        BooleanQuery resultQuery = new BooleanQuery();
+        for (DetailedSearchCriterion criterion : criteria)
+        {
+            List<String> fieldNames = getIndexFieldNames(criterion.getField());
+            String searchPattern = LuceneQueryBuilder.adaptQuery(criterion.getValue());
+            Query luceneQuery = LuceneQueryBuilder.parseQuery(fieldNames, searchPattern, analyzer);
+            resultQuery.add(luceneQuery, occureCondition);
+        }
+        return resultQuery;
+    }
+
+    private Occur createOccureCondition(SearchCriteriaConnection connection)
+    {
+        switch (connection)
+        {
+            case MATCH_ALL:
+                return Occur.MUST;
+            case MATCH_ANY:
+                return Occur.SHOULD;
+            default:
+                throw InternalErr.error("unknown enum " + connection);
+        }
+    }
+
+    private List<String> getIndexFieldNames(DetailedSearchField searchField)
+    {
+        DetailedSearchFieldKind fieldKind = searchField.getKind();
+        switch (fieldKind)
+        {
+            case ANY_PROPERTY:
+                return getPropertyIndexFields(searchField);
+            case ANY_FIELD:
+                List<String> fields = new ArrayList<String>();
+                fields.addAll(getPropertyIndexFields(searchField));
+                fields.addAll(getAllAttributeIndexFieldNames());
+                return fields;
+            default:
+                return Arrays.asList(getSimpleFieldIndexName(searchField));
+        }
+    }
+
+    private final static EnumSet<DetailedSearchFieldKind> simpleFieldKinds =
+            EnumSet.of(DetailedSearchFieldKind.ATTRIBUTE, DetailedSearchFieldKind.PROPERTY);
+
+    private String getSimpleFieldIndexName(DetailedSearchField searchField)
+    {
+        assert simpleFieldKinds.contains(searchField.getKind()) : "simple field kind required";
+        String indexFieldName = tryGetIndexFieldName(searchField);
+        assert indexFieldName != null;
+        return indexFieldName;
+    }
+
+    private List<String> getAllAttributeIndexFieldNames()
+    {
+        List<String> indexFieldNames = new ArrayList<String>();
+        IAttributeSearchFieldKind[] attributeFieldKinds =
+                IndexFieldNameHelper.getAllAttributeFieldKinds(entityKind);
+        for (IAttributeSearchFieldKind attributeFieldKind : attributeFieldKinds)
+        {
+            DetailedSearchField attributeField =
+                    DetailedSearchField.createAttributeField(attributeFieldKind);
+            indexFieldNames.add(getSimpleFieldIndexName(attributeField));
+        }
+        return indexFieldNames;
+    }
+
+    private List<String> getPropertyIndexFields(DetailedSearchField searchField)
+    {
+        assert searchField.getKind() != DetailedSearchFieldKind.ATTRIBUTE : "attribute field kind not allowed";
+        return getPropertyIndexFieldNames(searchField.getAllEntityPropertyCodesOrNull());
+    }
+
+    private List<String> getPropertyIndexFieldNames(List<String> allPropertyCodes)
+    {
+        List<String> indexFieldNames = new ArrayList<String>();
+        assert allPropertyCodes != null;
+        for (String propertyCode : allPropertyCodes)
+        {
+            final DetailedSearchField searchField =
+                    DetailedSearchField.createPropertyField(propertyCode);
+            final String indexFieldName = tryGetIndexFieldName(searchField);
+            assert indexFieldName != null;
+            indexFieldNames.add(indexFieldName);
+        }
+        return indexFieldNames;
+    }
+
+    // returns the field name in the index for the specified query field
+    private String tryGetIndexFieldName(DetailedSearchField searchField)
+    {
+        DetailedSearchFieldKind fieldKind = searchField.getKind();
+        switch (fieldKind)
+        {
+            case ATTRIBUTE:
+                return IndexFieldNameHelper.getAttributeIndexField(entityKind, searchField
+                        .getAttributeCode());
+            case PROPERTY:
+                return IndexFieldNameHelper.getPropertyIndexField(searchField.getPropertyCode());
+            case ANY_PROPERTY:
+            case ANY_FIELD:
+                return null;
+            default:
+                throw InternalErr.error("unknown enum " + fieldKind);
+        }
+    }
+
+}
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
new file mode 100644
index 00000000000..ec3aea908f4
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/search/detailed/IndexFieldNameHelper.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2009 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.server.dataaccess.db.search.detailed;
+
+import static ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants.CODE;
+
+import ch.systemsx.cisd.common.exceptions.InternalErr;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants;
+
+/**
+ * Helper for getting index field names of attributes and properties for detailed entity search.<br>
+ * 
+ * @author Piotr Buczek
+ */
+// TODO 2009-08-31, Piotr Buczek: write code for remaining entity kinds
+class IndexFieldNameHelper
+{
+    // properties
+
+    static String getPropertyIndexField(String propertyCode)
+    {
+        assert propertyCode != null : "property code is null";
+        return SearchFieldConstants.PREFIX_PROPERTIES + propertyCode;
+    }
+
+    // attributes
+
+    static IAttributeSearchFieldKind[] getAllAttributeFieldKinds(EntityKind entityKind)
+    {
+        switch (entityKind)
+        {
+            case DATA_SET:
+                return DataSetAttributeSearchFieldKind.values();
+            default:
+                throw new IllegalArgumentException("not implemented yet");
+        }
+    }
+
+    static String getAttributeIndexField(EntityKind entityKind, String attributeCode)
+    {
+        switch (entityKind)
+        {
+            case DATA_SET:
+                return getDataSetAttributeIndexField(DataSetAttributeSearchFieldKind
+                        .valueOf(attributeCode));
+            default:
+                throw new IllegalArgumentException("not implemented yet");
+        }
+    }
+
+    private static String getDataSetAttributeIndexField(
+            DataSetAttributeSearchFieldKind attributeKind)
+    {
+        switch (attributeKind)
+        {
+            case DATA_SET_CODE:
+                return CODE;
+            case DATA_SET_TYPE:
+                return SearchFieldConstants.PREFIX_ENTITY_TYPE + CODE;
+            case FILE_TYPE:
+                return SearchFieldConstants.PREFIX_FILE_FORMAT_TYPE + CODE;
+            default:
+                throw InternalErr.error("unknown enum " + attributeKind);
+        }
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 449fb85df09..a48ef186592 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -46,7 +46,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelatedEntities;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
@@ -76,6 +75,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -473,7 +473,7 @@ public interface ICommonServer extends IServer
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.OBSERVER)
     @ReturnValueFilter(validatorClass = ExternalDataValidator.class)
-    public List<ExternalData> searchForDataSets(String sessionToken, DataSetSearchCriteria criteria);
+    public List<ExternalData> searchForDataSets(String sessionToken, DetailedSearchCriteria criteria);
 
     /**
      * Returns all data sets related to specified entities.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetAttributeSearchFieldKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetAttributeSearchFieldKind.java
new file mode 100644
index 00000000000..94d2c890d71
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetAttributeSearchFieldKind.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2009 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 com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Kinds of fields connected with data set attributes that can be used in detailed text queries.
+ * 
+ * @author Piotr Buczek
+ */
+public enum DataSetAttributeSearchFieldKind implements IsSerializable, IAttributeSearchFieldKind
+{
+    DATA_SET_CODE("Code"),
+
+    DATA_SET_TYPE("Data Set Type"),
+
+    FILE_TYPE("File Type");
+
+    private final String description;
+
+    private DataSetAttributeSearchFieldKind(String description)
+    {
+        this.description = description;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    public String getCode()
+    {
+        return name();
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchField.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchField.java
deleted file mode 100644
index a3cbed548c6..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchField.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2009 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 java.io.Serializable;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.IsSerializable;
-
-/**
- * Full specification of the field connected with the data set which can be used in text queries.
- * 
- * @author Tomasz Pylak
- */
-public class DataSetSearchField implements IsSerializable, Serializable
-{
-    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
-
-    private DataSetSearchFieldKind kind;
-
-    private String propertyCodeOrNull;
-
-    private List<String> allDataSetPropertyCodesOrNull;
-
-    public static DataSetSearchField createAnyField(List<String> allDataSetPropertyCodes)
-    {
-        return new DataSetSearchField(DataSetSearchFieldKind.ANY_FIELD, null,
-                allDataSetPropertyCodes);
-    }
-
-    public static DataSetSearchField createAnyDataSetProperty(List<String> allDataSetPropertyCodes)
-    {
-        return new DataSetSearchField(DataSetSearchFieldKind.ANY_DATA_SET_PROPERTY, null,
-                allDataSetPropertyCodes);
-    }
-
-    public static DataSetSearchField createDataSetProperty(String propertyCode)
-    {
-        return new DataSetSearchField(DataSetSearchFieldKind.DATA_SET_PROPERTY, propertyCode);
-    }
-
-    public static DataSetSearchField createSimpleField(DataSetSearchFieldKind fieldKind)
-    {
-        assert fieldKind.isComplex() == false : "only simple field can be created with this method";
-
-        return new DataSetSearchField(fieldKind, null);
-    }
-
-    // GWT only
-    private DataSetSearchField()
-    {
-        this(null, null);
-    }
-
-    private DataSetSearchField(DataSetSearchFieldKind kind, String propertyCodeOrNull)
-    {
-        this(kind, propertyCodeOrNull, null);
-    }
-
-    private DataSetSearchField(DataSetSearchFieldKind kind, String propertyCodeOrNull,
-            List<String> allDataSetPropertyCodesOrNull)
-    {
-        this.kind = kind;
-        this.propertyCodeOrNull = propertyCodeOrNull;
-        this.allDataSetPropertyCodesOrNull = allDataSetPropertyCodesOrNull;
-    }
-
-    public DataSetSearchFieldKind getKind()
-    {
-        return kind;
-    }
-
-    public String getPropertyCode()
-    {
-        assert kind == DataSetSearchFieldKind.DATA_SET_PROPERTY;
-        return propertyCodeOrNull;
-    }
-
-    public List<String> getAllDataSetPropertyCodesOrNull()
-    {
-        assert kind == DataSetSearchFieldKind.ANY_DATA_SET_PROPERTY
-                || kind == DataSetSearchFieldKind.ANY_FIELD;
-        return allDataSetPropertyCodesOrNull;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-        sb.append(getKind());
-        if (getKind().equals(DataSetSearchFieldKind.DATA_SET_PROPERTY))
-        {
-            sb.append(".");
-            sb.append(getPropertyCode());
-        }
-        return sb.toString();
-    }
-}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchFieldKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchFieldKind.java
deleted file mode 100644
index 0da169ca6ba..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchFieldKind.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2009 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 java.util.ArrayList;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.IsSerializable;
-
-/**
- * Kinds of fields connected with the data set which can be used in text queries.
- * 
- * @author Tomasz Pylak
- */
-public enum DataSetSearchFieldKind implements IsSerializable
-{
-    ANY_FIELD("Any Field", true),
-
-    ANY_DATA_SET_PROPERTY("Any Data Set Property", true),
-
-    DATA_SET_CODE("Code"),
-
-    DATA_SET_TYPE("Data Set Type"),
-
-    FILE_TYPE("File Type"),
-
-    DATA_SET_PROPERTY("Property", true);
-
-    private final String description;
-
-    // if field is complex, it needs some additional information to be interpreted (e.g.
-    // property code)
-    private final boolean isComplex;
-
-    private DataSetSearchFieldKind(String description)
-    {
-        this(description, false);
-    }
-
-    private DataSetSearchFieldKind(String description, boolean isComplex)
-    {
-        this.description = description;
-        this.isComplex = isComplex;
-    }
-
-    public String description()
-    {
-        return description;
-    }
-
-    public static List<DataSetSearchFieldKind> getSimpleFields()
-    {
-        List<DataSetSearchFieldKind> result = new ArrayList<DataSetSearchFieldKind>();
-        for (DataSetSearchFieldKind field : DataSetSearchFieldKind.values())
-        {
-            if (field.isComplex == false)
-            {
-                result.add(field);
-
-            }
-        }
-        return result;
-    }
-
-    boolean isComplex()
-    {
-        return isComplex;
-    }
-}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchCriteria.java
similarity index 78%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchCriteria.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchCriteria.java
index 90dd5339b87..79ebbc38d97 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchCriteria.java
@@ -22,28 +22,29 @@ import java.util.List;
 import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
- * Describes search criteria specific to data set search.
+ * Describes detailed search criteria specific to an entity.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
-public class DataSetSearchCriteria implements IsSerializable, Serializable
+public class DetailedSearchCriteria implements IsSerializable, Serializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
-    private List<DataSetSearchCriterion> criteria;
+    private List<DetailedSearchCriterion> criteria;
 
     private SearchCriteriaConnection connection;
 
-    public DataSetSearchCriteria()
+    public DetailedSearchCriteria()
     {
     }
 
-    public List<DataSetSearchCriterion> getCriteria()
+    public List<DetailedSearchCriterion> getCriteria()
     {
         return criteria;
     }
 
-    public void setCriteria(List<DataSetSearchCriterion> criteria)
+    public void setCriteria(List<DetailedSearchCriterion> criteria)
     {
         this.criteria = criteria;
     }
@@ -62,7 +63,7 @@ public class DataSetSearchCriteria implements IsSerializable, Serializable
     public String toString()
     {
         final StringBuilder sb = new StringBuilder();
-        for (final DataSetSearchCriterion element : getCriteria())
+        for (final DetailedSearchCriterion element : getCriteria())
         {
             if (sb.length() > 0)
             {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchCriterion.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchCriterion.java
similarity index 80%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchCriterion.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchCriterion.java
index df7e7c998e5..11090506787 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetSearchCriterion.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchCriterion.java
@@ -22,31 +22,32 @@ import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
-public class DataSetSearchCriterion implements IsSerializable, Serializable
+public class DetailedSearchCriterion implements IsSerializable, Serializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
-    private DataSetSearchField field;
+    private DetailedSearchField field;
 
     private String value;
 
-    public DataSetSearchCriterion()
+    public DetailedSearchCriterion()
     {
     }
 
-    public DataSetSearchCriterion(DataSetSearchField field, String value)
+    public DetailedSearchCriterion(DetailedSearchField field, String value)
     {
         this.field = field;
         this.value = value;
     }
 
-    public DataSetSearchField getField()
+    public DetailedSearchField getField()
     {
         return field;
     }
 
-    public void setField(DataSetSearchField field)
+    public void setField(DetailedSearchField field)
     {
         this.field = field;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchField.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchField.java
new file mode 100644
index 00000000000..09df9b4631a
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchField.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2009 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 java.io.Serializable;
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Full specification of the field connected with an entity which can be used in detailed text
+ * queries.
+ * 
+ * @author Tomasz Pylak
+ * @author Piotr Buczek
+ */
+public class DetailedSearchField implements IsSerializable, Serializable
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private DetailedSearchFieldKind kind;
+
+    private String codeOrNull; // simple field code / property code
+
+    private List<String> allEntityPropertyCodesOrNull;
+
+    public static DetailedSearchField createAnyField(List<String> allEntityPropertyCodes)
+    {
+        assert allEntityPropertyCodes != null : "property codes not set";
+        return new DetailedSearchField(DetailedSearchFieldKind.ANY_FIELD, null,
+                allEntityPropertyCodes);
+    }
+
+    public static DetailedSearchField createAnyPropertyField(List<String> allEntityPropertyCodes)
+    {
+        assert allEntityPropertyCodes != null : "property codes not set";
+        return new DetailedSearchField(DetailedSearchFieldKind.ANY_PROPERTY, null,
+                allEntityPropertyCodes);
+    }
+
+    public static DetailedSearchField createPropertyField(String propertyCode)
+    {
+        assert propertyCode != null : "property code not set";
+        return new DetailedSearchField(DetailedSearchFieldKind.PROPERTY, propertyCode);
+    }
+
+    public static DetailedSearchField createAttributeField(
+            IAttributeSearchFieldKind attributeFieldKind)
+    {
+        assert attributeFieldKind != null : "attribute not set";
+        return createAttributeField(attributeFieldKind.getCode());
+    }
+
+    private static DetailedSearchField createAttributeField(String code)
+    {
+        assert code != null : "code not set";
+        return new DetailedSearchField(DetailedSearchFieldKind.ATTRIBUTE, code);
+    }
+
+    // GWT only
+    private DetailedSearchField()
+    {
+        this(null, null);
+    }
+
+    private DetailedSearchField(DetailedSearchFieldKind kind, String codeOrNull)
+    {
+        this(kind, codeOrNull, null);
+    }
+
+    private DetailedSearchField(DetailedSearchFieldKind kind, String codeOrNull,
+            List<String> allEntityPropertyCodesOrNull)
+    {
+        this.kind = kind;
+        this.codeOrNull = codeOrNull;
+        this.allEntityPropertyCodesOrNull = allEntityPropertyCodesOrNull;
+    }
+
+    public DetailedSearchFieldKind getKind()
+    {
+        return kind;
+    }
+
+    public String getAttributeCode()
+    {
+        assert kind == DetailedSearchFieldKind.ATTRIBUTE;
+        return codeOrNull;
+    }
+
+    public String getPropertyCode()
+    {
+        assert kind == DetailedSearchFieldKind.PROPERTY;
+        return codeOrNull;
+    }
+
+    public List<String> getAllEntityPropertyCodesOrNull()
+    {
+        assert kind == DetailedSearchFieldKind.ANY_PROPERTY
+                || kind == DetailedSearchFieldKind.ANY_FIELD;
+        return allEntityPropertyCodesOrNull;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getKind());
+        if (codeOrNull != null)
+        {
+            sb.append(" " + codeOrNull);
+        }
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchFieldKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchFieldKind.java
new file mode 100644
index 00000000000..20f72b89d5a
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DetailedSearchFieldKind.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 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 com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * General kinds of fields that can be used in detailed text query for an entity.
+ * 
+ * @author Piotr Buczek
+ */
+public enum DetailedSearchFieldKind implements IsSerializable
+{
+    ANY_FIELD("Any Field"),
+
+    ANY_PROPERTY("Any Property"),
+
+    PROPERTY("Property"),
+
+    ATTRIBUTE("");
+
+    private final String description;
+
+    private DetailedSearchFieldKind(String description)
+    {
+        this.description = description;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IAttributeSearchFieldKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IAttributeSearchFieldKind.java
new file mode 100644
index 00000000000..526be5d27a3
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IAttributeSearchFieldKind.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 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;
+
+/**
+ * @author Piotr Buczek
+ */
+public interface IAttributeSearchFieldKind
+{
+    String getCode();
+
+    String getDescription();
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/DataSetSearchTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/DataSetSearchTest.java
index fe4b2513106..4440f6dacdb 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/DataSetSearchTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/DataSetSearchTest.java
@@ -20,11 +20,11 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.menu.TopMe
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.data.CommonExternalDataColDefKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetSearchHitGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetSearchRow;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.FillSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search.FillSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractGWTTestCase;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.CheckTableCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.Row;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetAttributeSearchFieldKind;
 
 /**
  * A {@link AbstractGWTTestCase} extension to test <i>Data Set Search</i>.
@@ -40,7 +40,7 @@ public class DataSetSearchTest extends AbstractGWTTestCase
     {
         loginAndGotoTab();
         FillSearchCriteria fillCriteriaCmd = new FillSearchCriteria();
-        fillCriteriaCmd.addDataSetPropertyCriterion("Comment", "no comment");
+        fillCriteriaCmd.addPropertyCriterion("Comment", "no comment");
         remoteConsole.prepare(fillCriteriaCmd);
 
         final CheckTableCommand checkResultTableCmd = createCheckSearchGridCmd();
@@ -59,7 +59,7 @@ public class DataSetSearchTest extends AbstractGWTTestCase
     {
         loginAndGotoTab();
         FillSearchCriteria fillCriteriaCmd = new FillSearchCriteria();
-        fillCriteriaCmd.addSimpleCriterion(DataSetSearchFieldKind.FILE_TYPE, "tiff");
+        fillCriteriaCmd.addAttributeCriterion(DataSetAttributeSearchFieldKind.FILE_TYPE, "tiff");
 
         remoteConsole.prepare(fillCriteriaCmd);
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/FillSearchCriteria.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/FillSearchCriteria.java
similarity index 60%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/FillSearchCriteria.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/FillSearchCriteria.java
index 99bbe615f9b..55d7e33a1b4 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/FillSearchCriteria.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/FillSearchCriteria.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -22,15 +22,19 @@ import java.util.List;
 import com.extjs.gxt.ui.client.widget.form.Radio;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.Criterion;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.MatchCriteriaRadio;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractDefaultTestCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.GWTTestUtil;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchFieldKind;
 
 /**
- * A {@link AbstractDefaultTestCommand} extension for filling {@link CriteriaWidget}.
+ * A {@link AbstractDefaultTestCommand} extension for filling {@link DetailedSearchCriteriaWidget}.
  * 
  * @author Izabela Adamczyk
+ * @author Piotr Buczek
  */
 public final class FillSearchCriteria extends AbstractDefaultTestCommand
 {
@@ -45,7 +49,7 @@ public final class FillSearchCriteria extends AbstractDefaultTestCommand
         criteria = new ArrayList<Criterion>();
         criteriaDefined = false;
         matchAll();
-        addCallbackClass(DataSetSearchFieldsSelectionWidget.ListPropertyTypesCallback.class);
+        addCallbackClass(DetailedSearchFieldsSelectionWidget.ListPropertyTypesCallback.class);
     }
 
     public FillSearchCriteria matchAll()
@@ -60,23 +64,21 @@ public final class FillSearchCriteria extends AbstractDefaultTestCommand
         return this;
     }
 
-    public FillSearchCriteria addSimpleCriterion(DataSetSearchFieldKind name, String value)
+    public FillSearchCriteria addAttributeCriterion(IAttributeSearchFieldKind attribute,
+            String value)
     {
-        return addCriterion(name, null, value);
+        return addCriterion(attribute.getDescription(), value);
     }
 
-    public FillSearchCriteria addDataSetPropertyCriterion(String name, String value)
+    public FillSearchCriteria addPropertyCriterion(String name, String value)
     {
-        return addCriterion(DataSetSearchFieldKind.DATA_SET_PROPERTY, name, value);
+        final String field = DetailedSearchFieldKind.PROPERTY.getDescription() + " '" + name + "'";
+        return addCriterion(field, value);
     }
 
-    private FillSearchCriteria addCriterion(DataSetSearchFieldKind fieldKind,
-            String propertyOrNull, String value)
+    private FillSearchCriteria addCriterion(String name, String value)
     {
-        final String field =
-                fieldKind.description()
-                        + (propertyOrNull == null ? "" : " '" + propertyOrNull + "'");
-        criteria.add(new Criterion(field, value));
+        criteria.add(new Criterion(name, value));
         criteriaDefined = true;
         return this;
     }
@@ -102,19 +104,20 @@ public final class FillSearchCriteria extends AbstractDefaultTestCommand
         }
         for (int i = 0; i < criteria.size(); i++)
         {
-            final DataSetSearchFieldsSelectionWidget selector =
-                    (DataSetSearchFieldsSelectionWidget) GWTTestUtil
-                            .getWidgetWithID(DataSetSearchFieldsSelectionWidget.ID
-                                    + DataSetSearchFieldsSelectionWidget.SUFFIX
-                                    + CriteriaWidget.FIRST_ID_SUFFIX + getSuffix(i));
+            final DetailedSearchFieldsSelectionWidget selector =
+                    (DetailedSearchFieldsSelectionWidget) GWTTestUtil
+                            .getWidgetWithID(DetailedSearchFieldsSelectionWidget.ID
+                                    + DetailedSearchFieldsSelectionWidget.SUFFIX
+                                    + DetailedSearchCriteriaWidget.FIRST_ID_SUFFIX + getSuffix(i));
             GWTUtils.setSelectedItem(selector, ModelDataPropertyNames.CODE, criteria.get(i)
                     .getName());
-            GWTTestUtil.setTextField(CriterionWidget.VALUE_FIELD_ID_PREFIX
-                    + CriteriaWidget.FIRST_ID_SUFFIX + getSuffix(i), criteria.get(i).getValue());
-            GWTTestUtil.clickButtonWithID(CriterionWidget.ADD_BUTTON_ID_PREFIX
-                    + CriteriaWidget.FIRST_ID_SUFFIX);
+            GWTTestUtil.setTextField(DetailedSearchCriterionWidget.VALUE_FIELD_ID_PREFIX
+                    + DetailedSearchCriteriaWidget.FIRST_ID_SUFFIX + getSuffix(i), criteria.get(i)
+                    .getValue());
+            GWTTestUtil.clickButtonWithID(DetailedSearchCriterionWidget.ADD_BUTTON_ID_PREFIX
+                    + DetailedSearchCriteriaWidget.FIRST_ID_SUFFIX);
         }
-        GWTTestUtil.clickButtonWithID(DataSetSearchWindow.SEARCH_BUTTON_ID);
+        GWTTestUtil.clickButtonWithID(DetailedSearchWindow.SEARCH_BUTTON_ID);
     }
 
     private final String getSuffix(int i)
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 39f4863ae76..d5005f3028c 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
@@ -45,12 +45,12 @@ import ch.systemsx.cisd.common.test.AssertionUtil;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.FullTextIndexerRunnable;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriterion;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchField;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
+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.dto.DataSetPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
@@ -205,28 +205,28 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
 
     // ----------------- test serach for datasets
 
-    private static DataSetSearchCriteria createOrDatasetQuery(DataSetSearchCriterion... criteria)
+    private static DetailedSearchCriteria createOrDatasetQuery(DetailedSearchCriterion... criteria)
     {
         return createDatasetQuery(SearchCriteriaConnection.MATCH_ANY, criteria);
     }
 
-    private static DataSetSearchCriteria createAndDatasetQuery(DataSetSearchCriterion... criteria)
+    private static DetailedSearchCriteria createAndDatasetQuery(DetailedSearchCriterion... criteria)
     {
         return createDatasetQuery(SearchCriteriaConnection.MATCH_ALL, criteria);
     }
 
-    private static DataSetSearchCriteria createDatasetQuery(SearchCriteriaConnection connection,
-            DataSetSearchCriterion[] criteria)
+    private static DetailedSearchCriteria createDatasetQuery(SearchCriteriaConnection connection,
+            DetailedSearchCriterion[] criteria)
     {
-        DataSetSearchCriteria result = new DataSetSearchCriteria();
+        DetailedSearchCriteria result = new DetailedSearchCriteria();
         result.setConnection(connection);
         result.setCriteria(Arrays.asList(criteria));
         return result;
     }
 
-    private static DataSetSearchCriterion mkCriterion(DataSetSearchField field, String value)
+    private static DetailedSearchCriterion mkCriterion(DetailedSearchField field, String value)
     {
-        return new DataSetSearchCriterion(field, value);
+        return new DetailedSearchCriterion(field, value);
     }
 
     private List<String> fetchPropertyTypeCodes()
@@ -240,7 +240,7 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
         return codes;
     }
 
-    private List<ExternalDataPE> searchForDatasets(DataSetSearchCriteria criteria)
+    private List<ExternalDataPE> searchForDatasets(DetailedSearchCriteria criteria)
     {
         final IHibernateSearchDAO hibernateSearchDAO = daoFactory.getHibernateSearchDAO();
         return hibernateSearchDAO.searchForDataSets(criteria);
@@ -248,8 +248,7 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
 
     // NOTE: such a check depends strongly on the test database content. Use it only when the better
     // way to check the results is much harder.
-    private void assertCorrectDatasetsFound(DataSetSearchCriteria criteria,
-            DSLoc... expectedLocations)
+    private void assertCorrectDatasetsFound(DetailedSearchCriteria criteria, DSLoc... expectedLocations)
     {
         List<ExternalDataPE> dataSets = searchForDatasets(criteria);
         AssertJUnit.assertEquals(expectedLocations.length, dataSets.size());
@@ -289,54 +288,54 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
         }
     }
 
-    private static DataSetSearchField createAnySearchField(List<String> propertyTypes)
+    private static DetailedSearchField createAnySearchField(List<String> propertyTypes)
     {
-        return DataSetSearchField.createAnyField(propertyTypes);
+        return DetailedSearchField.createAnyField(propertyTypes);
     }
 
-    private DataSetSearchCriterion createAnyFieldCriterion()
+    private DetailedSearchCriterion createAnyFieldCriterion()
     {
         List<String> propertyTypes = fetchPropertyTypeCodes();
         return mkCriterion(createAnySearchField(propertyTypes), "*3*");
     }
 
-    private DataSetSearchCriterion createSimpleFieldCriterion()
+    private DetailedSearchCriterion createSimpleFieldCriterion()
     {
-        return mkCriterion(DataSetSearchField.createSimpleField(DataSetSearchFieldKind.FILE_TYPE),
-                "TIFF");
+        return mkCriterion(DetailedSearchField
+                .createAttributeField(DataSetAttributeSearchFieldKind.FILE_TYPE), "TIFF");
     }
 
     @Test
     public final void testSearchForDataSetsAnyField()
     {
-        DataSetSearchCriterion criterion = createAnyFieldCriterion();
-        DataSetSearchCriteria criteria = createAndDatasetQuery(criterion);
+        DetailedSearchCriterion criterion = createAnyFieldCriterion();
+        DetailedSearchCriteria criteria = createAndDatasetQuery(criterion);
         assertCorrectDatasetsFound(criteria, DSLoc.LOC1, DSLoc.LOC2, DSLoc.LOC4, DSLoc.LOC5);
     }
 
     @Test
     public final void testSearchForDataSetsSimpleField()
     {
-        DataSetSearchCriterion criterion = createSimpleFieldCriterion();
-        DataSetSearchCriteria criteria = createAndDatasetQuery(criterion);
+        DetailedSearchCriterion criterion = createSimpleFieldCriterion();
+        DetailedSearchCriteria criteria = createAndDatasetQuery(criterion);
         assertCorrectDatasetsFound(criteria, DSLoc.LOC3, DSLoc.LOC4);
     }
 
     @Test
     public final void testSearchForDataSetsComplexAndQuery()
     {
-        DataSetSearchCriterion criterion1 = createAnyFieldCriterion();
-        DataSetSearchCriterion criterion2 = createSimpleFieldCriterion();
-        DataSetSearchCriteria criteria = createAndDatasetQuery(criterion1, criterion2);
+        DetailedSearchCriterion criterion1 = createAnyFieldCriterion();
+        DetailedSearchCriterion criterion2 = createSimpleFieldCriterion();
+        DetailedSearchCriteria criteria = createAndDatasetQuery(criterion1, criterion2);
         assertCorrectDatasetsFound(criteria, DSLoc.LOC4);
     }
 
     @Test
     public final void testSearchForDataSetsComplexOrQuery()
     {
-        DataSetSearchCriterion criterion1 = createAnyFieldCriterion();
-        DataSetSearchCriterion criterion2 = createSimpleFieldCriterion();
-        DataSetSearchCriteria criteria = createOrDatasetQuery(criterion1, criterion2);
+        DetailedSearchCriterion criterion1 = createAnyFieldCriterion();
+        DetailedSearchCriterion criterion2 = createSimpleFieldCriterion();
+        DetailedSearchCriteria criteria = createOrDatasetQuery(criterion1, criterion2);
         assertCorrectDatasetsFound(criteria, DSLoc.LOC1, DSLoc.LOC2, DSLoc.LOC3, DSLoc.LOC4,
                 DSLoc.LOC5);
     }
@@ -451,10 +450,10 @@ public final class HibernateSearchDAOTest extends AbstractDAOTest
     public final void testSearchForDataSetsAfterPropertiesUpdate() throws InterruptedException
     {
         String propertyCode = "COMMENT";
-        DataSetSearchCriterion criterion =
-                mkCriterion(DataSetSearchField.createDataSetProperty(propertyCode), "no comment");
+        DetailedSearchCriterion criterion =
+                mkCriterion(DetailedSearchField.createPropertyField(propertyCode), "no comment");
 
-        DataSetSearchCriteria criteria = createAndDatasetQuery(criterion);
+        DetailedSearchCriteria criteria = createAndDatasetQuery(criterion);
         assertCorrectDatasetsFound(criteria, DSLoc.LOC1, DSLoc.LOC2, DSLoc.LOC3, DSLoc.LOC4,
                 DSLoc.LOC5);
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
index 449fb85df09..a48ef186592 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
@@ -46,7 +46,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelatedEntities;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
@@ -76,6 +75,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -473,7 +473,7 @@ public interface ICommonServer extends IServer
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.OBSERVER)
     @ReturnValueFilter(validatorClass = ExternalDataValidator.class)
-    public List<ExternalData> searchForDataSets(String sessionToken, DataSetSearchCriteria criteria);
+    public List<ExternalData> searchForDataSets(String sessionToken, DetailedSearchCriteria criteria);
 
     /**
      * Returns all data sets related to specified entities.
-- 
GitLab