diff --git a/openbis/resource/dependency-structure.ddf b/openbis/resource/dependency-structure.ddf
index 0e082b812234cc99079d173eb71ac3a93a560385..84db16e5d23cddbc5ee3c375b7cccef2de5207e6 100644
--- a/openbis/resource/dependency-structure.ddf
+++ b/openbis/resource/dependency-structure.ddf
@@ -37,9 +37,14 @@ check layeringOf generic.web.shared generic.web.client-server
 {generic.web.ui} = ${generic.web}.client.application.ui
 
 [sample-browser] = ${generic.web.ui}.sample_browser
+[experiment-browser] = ${generic.web.ui}.experiment_browser
 [admin-console] = ${generic.web.ui}.amc
 check [sample-browser] independentOf [admin-console]
 check [admin-console]  independentOf [sample-browser]
+check [experiment-browser]  independentOf [sample-browser]
+check [sample-browser]  independentOf [experiment-browser]
+check [experiment-browser] independentOf [admin-console]
+check [admin-console]  independentOf [experiment-browser]
 
 #-------- Server -------------------------
 {generic.server} = ${generic}.server
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 c920680e4ef441f5efa0f998633b0f6ab12d3f9c..88330ba10572feb4277b5213d53c5a799b3ee1b5 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
@@ -18,12 +18,16 @@ package ch.systemsx.cisd.openbis.generic.client.web.client;
 
 import java.util.List;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Sample;
@@ -97,6 +101,12 @@ public interface ICommonClientService extends IClientService
     public ResultSet<Sample> listSamples(final ListSampleCriteria criteria)
             throws UserFailureException;
 
+    /**
+     * Returns a list of experiments.
+     */
+    public ResultSet<Experiment> listExperiments(final ListExperimentsCriteria criteria)
+            throws UserFailureException;
+
     /**
      * For given <var>sampleIdentifier</var> returns corresponding list of {@link ExternalData}.
      */
@@ -119,4 +129,14 @@ public interface ICommonClientService extends IClientService
      * Removes the session result set associated with given key.
      */
     public void removeResultSet(final String resultSetKey) throws UserFailureException;
+
+    /**
+     * Returns a list of all projects.
+     */
+    public List<Project> listProjects() throws UserFailureException;
+
+    /**
+     * Returns a list of all experiment types.
+     */
+    public List<ExperimentType> listExperimentTypes() 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 6ce7a431ed753b11d126d264373de97095129464..4356ad98063b04939b486cb20c7eba8783749690 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
@@ -20,12 +20,15 @@ import java.util.List;
 
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Sample;
@@ -80,6 +83,13 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void listSamples(final ListSampleCriteria criteria,
             AsyncCallback<ResultSet<Sample>> asyncCallback);
 
+    /**
+     * @see ICommonClientService#listExperiments(ListExperimentsCriteria)
+     */
+    public void listExperiments(
+            final ListExperimentsCriteria criteria,
+            AsyncCallback<ResultSet<ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment>> asyncCallback);
+
     /**
      * @see ICommonClientService#listExternalData(String)
      */
@@ -102,4 +112,10 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
      * @see ICommonClientService#removeResultSet(String)
      */
     public void removeResultSet(final String resultSetKey, final AsyncCallback<Void> asyncCallback);
+
+    /** @see ICommonClientService#listProjects() */
+    public void listProjects(AsyncCallback<List<Project>> asyncCallback);
+
+    /** @see ICommonClientService#listExperimentTypes() */
+    public void listExperimentTypes(AsyncCallback<List<ExperimentType>> listExperimentTypesCallback);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CategoriesBuilder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CategoriesBuilder.java
index 4c2d62f1a5e3d2f1bd2e0127b2b276c6b1adfee7..5a0347b7bb13df284b2e3cd8790080c8dfed68d3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CategoriesBuilder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CategoriesBuilder.java
@@ -184,7 +184,7 @@ public class CategoriesBuilder
     private MenuCategory createExperimentCategory()
     {
         final List<MenuElement> elements = new ArrayList<MenuElement>();
-        elements.add(new MenuElement(MENU_ELEMENTS.LIST, "List", provider.getDummyComponent()));
+        elements.add(new MenuElement(MENU_ELEMENTS.LIST, "List", provider.getExperimentBrowser()));
         elements.add(new MenuElement(MENU_ELEMENTS.LIST_TYPES, "List types", provider
                 .getDummyComponent()));
         elements.add(new MenuElement(MENU_ELEMENTS.REGISTER, "Register", provider
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
index faba53b39ef692ba7b8ca5713a7ee637d4972dcd..755894ac2de0f853783327b0577877f97b3e8d6c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
@@ -22,6 +22,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.PersonsVie
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.RolesView;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.SampleBatchRegistrationMock;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.SampleRegistrationPanel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment_browser.ExperimentBrowser;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample_browser.SampleBrowser;
 
 /**
@@ -48,6 +49,8 @@ final class ComponentProvider
 
     private final SampleBatchRegistrationMock sampleBatchRegistration;
 
+    private final ExperimentBrowser experimentBrowser;
+
     ComponentProvider(final CommonViewContext viewContext)
     {
         sampleBrowser = new SampleBrowser(viewContext);
@@ -57,6 +60,7 @@ final class ComponentProvider
         personsView = new PersonsView(viewContext);
         sampleRegistration = new SampleRegistrationPanel(viewContext);
         sampleBatchRegistration = new SampleBatchRegistrationMock(viewContext);
+        experimentBrowser = new ExperimentBrowser(viewContext);
     }
 
     public final ITabItem getSampleBrowser()
@@ -93,4 +97,9 @@ final class ComponentProvider
     {
         return new ContentPanelAdapter(sampleBatchRegistration);
     }
+
+    public ITabItem getExperimentBrowser()
+    {
+        return new DefaultTabItem("Experiment browser", experimentBrowser, experimentBrowser);
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ExperimentModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ExperimentModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cfe59823467d4ec832f73eb464e98388e323791
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ExperimentModel.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.data.BaseModelData;
+import com.extjs.gxt.ui.client.data.ModelData;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.DateRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.PersonRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.PropertyType;
+
+/**
+ * {@link ModelData} for {@link Experiment}
+ * 
+ * @author Izabela Adamczyk
+ */
+public final class ExperimentModel extends BaseModelData
+{
+    private static final long serialVersionUID = 1L;
+
+    private static final String PROPERTY_PREFIX = "property";
+
+    public static String createID(final PropertyType propertyType)
+    {
+        return PROPERTY_PREFIX + propertyType.isInternalNamespace() + propertyType.getSimpleCode();
+    }
+
+    public ExperimentModel(final Experiment experiment)
+    {
+        set(ModelDataPropertyNames.CODE, experiment.getCode());
+        set(ModelDataPropertyNames.EXPERIMENT_TYPE, experiment.getExperimentType().getCode());
+        set(ModelDataPropertyNames.GROUP, experiment.getProject().getGroup().getCode());
+        set(ModelDataPropertyNames.PROJECT, experiment.getProject().getCode());
+        set(ModelDataPropertyNames.OBJECT, experiment);
+        set(ModelDataPropertyNames.REGISTRATOR, PersonRenderer.createPersonAnchor(experiment
+                .getRegistrator()));
+        set(ModelDataPropertyNames.REGISTRATION_DATE, DateRenderer.renderDate(experiment
+                .getRegistrationDate()));
+    }
+
+    public final static List<ExperimentModel> asExperimentModels(final List<Experiment> experiments)
+    {
+        final List<ExperimentModel> sampleModels =
+                new ArrayList<ExperimentModel>(experiments.size());
+        for (final Experiment exp : experiments)
+        {
+            sampleModels.add(new ExperimentModel(exp));
+        }
+        return sampleModels;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ExperimentTypeModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ExperimentTypeModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..e747b3714bc20954389519bed5ebf240e400c61a
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ExperimentTypeModel.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.model;
+
+import com.extjs.gxt.ui.client.data.BaseModelData;
+import com.extjs.gxt.ui.client.data.ModelData;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentType;
+
+/**
+ * {@link ModelData} for {@link ExperimentType}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ExperimentTypeModel extends BaseModelData
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public ExperimentTypeModel(final ExperimentType experimentType)
+    {
+        set(ModelDataPropertyNames.CODE, experimentType.getCode());
+        set(ModelDataPropertyNames.OBJECT, experimentType);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ModelDataPropertyNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ModelDataPropertyNames.java
index 5210d9d20379f8f7ae5ef99e377b139ef3a8d0b8..dd165230625826b6792d3a8feed6695c80686ec0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ModelDataPropertyNames.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ModelDataPropertyNames.java
@@ -117,8 +117,14 @@ public final class ModelDataPropertyNames
 
     public static final String SAMPLE_TYPE = "sampleType";
 
+    public static final String EXPERIMENT_TYPE = "experimentType";
+
     public static final String USER_ID = "userId";
 
+    public static final String PROJECT_WITH_GROUP = "projectWithGroup";
+
+    public static final String PROJECT = "project";
+
     private ModelDataPropertyNames()
     {
         // Can not be instantiated.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ProjectModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ProjectModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..81dd55851c2a867d74ed7085e84c9316280223d5
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/ProjectModel.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.data.BaseModelData;
+import com.extjs.gxt.ui.client.data.ModelData;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
+
+/**
+ * {@link ModelData} for {@link Project}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ProjectModel extends BaseModelData
+{
+    private static final long serialVersionUID = 1L;
+
+    public ProjectModel()
+    {
+    }
+
+    public ProjectModel(final Project project)
+    {
+        set(ModelDataPropertyNames.CODE, project.getCode());
+        set(ModelDataPropertyNames.DESCRIPTION, project.getDescription());
+        set(ModelDataPropertyNames.GROUP, project.getGroup());
+        set(ModelDataPropertyNames.PROJECT_WITH_GROUP, renderProjectWithGroup(project));
+        set(ModelDataPropertyNames.OBJECT, project);
+    }
+
+    String renderProjectWithGroup(final Project p)
+    {
+        return p.getGroup() + ": " + p.getCode();
+    }
+
+    public final static List<ProjectModel> convert(final List<Project> projects)
+    {
+        final List<ProjectModel> result = new ArrayList<ProjectModel>();
+        for (final Project p : projects)
+        {
+            result.add(new ProjectModel(p));
+        }
+        return result;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/GroupSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
similarity index 99%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/GroupSelectionWidget.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
index a5928763f728f16d78ce3ef7cdc9708635167923..14e207269d22f10b65dc135692e6beb0ba9f6027 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/GroupSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample_browser;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 
 import java.util.List;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowser.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5db1e320708938f2e2a0bc09b962aa85697f8b2
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowser.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment_browser;
+
+import com.extjs.gxt.ui.client.Events;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.event.TabPanelEvent;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.layout.RowData;
+import com.extjs.gxt.ui.client.widget.layout.RowLayout;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+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.VoidAsyncCallback;
+
+/**
+ * Main view component of experiment browser.
+ * 
+ * @author Izabela Adamczyk
+ */
+public final class ExperimentBrowser extends LayoutContainer implements Listener<TabPanelEvent>
+{
+    private static final String PREFIX = "experiment-browser";
+
+    public static final String ID = GenericConstants.ID_PREFIX + PREFIX;
+
+    private final ExperimentBrowserGrid experimentBrowserGrid;
+
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    public ExperimentBrowser(final IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        this.viewContext = viewContext;
+        setId(ID);
+        setLayout(new RowLayout());
+
+        experimentBrowserGrid = new ExperimentBrowserGrid(viewContext);
+        final ExperimentBrowserToolbar toolbar =
+                new ExperimentBrowserToolbar(viewContext, experimentBrowserGrid);
+
+        add(toolbar);
+        add(experimentBrowserGrid, new RowData(1, 1));
+    }
+
+    public final void handleEvent(final TabPanelEvent be)
+    {
+        final String resultSetKey = experimentBrowserGrid.getResultSetKey();
+        if (be.type == Events.Close && resultSetKey != null)
+        {
+            viewContext.getService().removeResultSet(resultSetKey,
+                    new VoidAsyncCallback<Void>(viewContext));
+        }
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowserGrid.java
new file mode 100644
index 0000000000000000000000000000000000000000..f63c4f8748e109d3a0f491324c2988d243df3b42
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowserGrid.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment_browser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.Style.SelectionMode;
+import com.extjs.gxt.ui.client.data.BasePagingLoadResult;
+import com.extjs.gxt.ui.client.data.BasePagingLoader;
+import com.extjs.gxt.ui.client.data.PagingLoadConfig;
+import com.extjs.gxt.ui.client.data.PagingLoadResult;
+import com.extjs.gxt.ui.client.data.PagingLoader;
+import com.extjs.gxt.ui.client.data.RpcProxy;
+import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.widget.ContentPanel;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.PagingToolBar;
+import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
+import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
+import com.extjs.gxt.ui.client.widget.grid.Grid;
+import com.extjs.gxt.ui.client.widget.layout.FitLayout;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+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.VoidAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ExperimentModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.ColumnConfigFactory;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample_browser.PagingToolBarWithoutRefresh;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GxtTranslator;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentType;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
+
+/**
+ * A {@link LayoutContainer} which contains the grid where the experiments are displayed.
+ * 
+ * @author Christian Ribeaud
+ * @author Izabela Adamczyk
+ */
+public final class ExperimentBrowserGrid extends LayoutContainer
+{
+    private static final int PAGE_SIZE = 50;
+
+    private static final String PREFIX = "experiment-browser-grid_";
+
+    public static final String GRID_ID = GenericConstants.ID_PREFIX + PREFIX + "grid";
+
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    private ContentPanel contentPanel;
+
+    private Grid<ExperimentModel> grid;
+
+    private final PagingLoader<PagingLoadConfig> experimentLoader;
+
+    private ListExperimentsCriteria criteria;
+
+    private String resultSetKey;
+
+    ExperimentBrowserGrid(final IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        this.viewContext = viewContext;
+        experimentLoader = createExperimentLoader();
+        createUI();
+    }
+
+    private final void createUI()
+    {
+        setLayout(new FitLayout());
+        contentPanel = createContentPanel();
+        grid = createGrid();
+        contentPanel.add(grid);
+        final PagingToolBar toolBar = createPagingToolBar();
+        toolBar.bind(experimentLoader);
+        contentPanel.setBottomComponent(toolBar);
+        add(contentPanel);
+    }
+
+    private final PagingLoader<PagingLoadConfig> createExperimentLoader()
+    {
+        final RpcProxy<PagingLoadConfig, PagingLoadResult<ExperimentModel>> proxy = createProxy();
+        final BasePagingLoader<PagingLoadConfig, PagingLoadResult<ExperimentModel>> pagingLoader =
+                new BasePagingLoader<PagingLoadConfig, PagingLoadResult<ExperimentModel>>(proxy);
+        pagingLoader.setRemoteSort(true);
+        return pagingLoader;
+    }
+
+    private final RpcProxy<PagingLoadConfig, PagingLoadResult<ExperimentModel>> createProxy()
+    {
+        return new RpcProxy<PagingLoadConfig, PagingLoadResult<ExperimentModel>>()
+            {
+
+                //
+                // RpcProxy
+                //
+
+                @Override
+                public final void load(final PagingLoadConfig loadConfig,
+                        final AsyncCallback<PagingLoadResult<ExperimentModel>> callback)
+                {
+                    final int offset = loadConfig.getOffset();
+                    criteria.setLimit(loadConfig.getLimit());
+                    criteria.setOffset(offset);
+                    criteria.setSortInfo(GxtTranslator.translate(loadConfig.getSortInfo()));
+                    criteria.setResultSetKey(resultSetKey);
+                    viewContext.getService().listExperiments(criteria,
+                            new ListExperimentsCallback(viewContext, callback, offset));
+                }
+
+            };
+    }
+
+    private final static ContentPanel createContentPanel()
+    {
+        final ContentPanel contentPanel = new ContentPanel();
+        contentPanel.setBorders(false);
+        contentPanel.setBodyBorder(false);
+        contentPanel.setLayout(new FitLayout());
+        return contentPanel;
+    }
+
+    private final Grid<ExperimentModel> createGrid()
+    {
+        final Grid<ExperimentModel> experimentGrid =
+                new Grid<ExperimentModel>(new ListStore<ExperimentModel>(experimentLoader),
+                        new ColumnModel(new ArrayList<ColumnConfig>()));
+        experimentGrid.setId(GRID_ID);
+        experimentGrid.setLoadMask(true);
+        experimentGrid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
+        return experimentGrid;
+    }
+
+    private final static PagingToolBar createPagingToolBar()
+    {
+        return new PagingToolBarWithoutRefresh(PAGE_SIZE);
+    }
+
+    private final ColumnModel createColumnModel()
+    {
+        final List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
+        configs.add(ColumnConfigFactory.createCodeColumnConfig(viewContext.getMessageProvider()));
+
+        configs.add(ColumnConfigFactory.createDefaultConfig(viewContext.getMessageProvider(),
+                ModelDataPropertyNames.EXPERIMENT_TYPE, "experiment_type"));
+        configs.add(ColumnConfigFactory.createDefaultConfig(viewContext.getMessageProvider(),
+                ModelDataPropertyNames.GROUP));
+        configs.add(ColumnConfigFactory.createDefaultConfig(viewContext.getMessageProvider(),
+                ModelDataPropertyNames.PROJECT));
+
+        configs.add(ColumnConfigFactory.createRegistratorColumnConfig(viewContext
+                .getMessageProvider()));
+        configs.add(ColumnConfigFactory.createRegistrationDateColumnConfig(viewContext
+                .getMessageProvider()));
+        return new ColumnModel(configs);
+    }
+
+    private final String createHeader(final ExperimentType experimentType,
+            final Project selectedProject)
+    {
+        final StringBuilder builder = new StringBuilder("Experiments");
+        builder.append(" of type ");
+        builder.append(experimentType.getCode());
+        builder.append(" belonging to the project ");
+        builder.append(selectedProject.getCode());
+        builder.append(" from group ");
+        builder.append(selectedProject.getGroup().getCode());
+        return builder.toString();
+    }
+
+    final void refresh(final ExperimentType selectedType, final Project selectedProject)
+    {
+        if (resultSetKey != null)
+        {
+            viewContext.getService().removeResultSet(resultSetKey,
+                    new VoidAsyncCallback<Void>(viewContext));
+            resultSetKey = null;
+        }
+        criteria = new ListExperimentsCriteria();
+        criteria.setExperimentType(selectedType);
+        criteria.setProjectCode(selectedProject.getCode());
+        criteria.setGroupCode(selectedProject.getGroup().getCode());
+        contentPanel.setHeading(createHeader(selectedType, selectedProject));
+        grid.reconfigure(grid.getStore(), createColumnModel());
+        experimentLoader.load(0, PAGE_SIZE);
+    }
+
+    /**
+     * Returns the result set key.
+     */
+    final String getResultSetKey()
+    {
+        return resultSetKey;
+    }
+
+    /**
+     * Returns the current grid column model.
+     */
+    final ColumnModel getColumnModel()
+    {
+        return grid.getColumnModel();
+    }
+
+    //
+    // Helper classes
+    //
+
+    public final class ListExperimentsCallback extends AbstractAsyncCallback<ResultSet<Experiment>>
+    {
+        private final AsyncCallback<PagingLoadResult<ExperimentModel>> delegate;
+
+        private final int offset;
+
+        ListExperimentsCallback(final IViewContext<ICommonClientServiceAsync> viewContext,
+                final AsyncCallback<PagingLoadResult<ExperimentModel>> delegate, final int offset)
+        {
+            super(viewContext);
+            this.delegate = delegate;
+            this.offset = offset;
+        }
+
+        private void setResultSetKey(final String resultSetKey)
+        {
+            if (ExperimentBrowserGrid.this.resultSetKey == null)
+            {
+                ExperimentBrowserGrid.this.resultSetKey = resultSetKey;
+            } else
+            {
+                assert ExperimentBrowserGrid.this.resultSetKey.equals(resultSetKey) : "Result set keys not the same.";
+            }
+        }
+
+        //
+        // AbstractAsyncCallback
+        //
+
+        @Override
+        protected final void finishOnFailure(final Throwable caught)
+        {
+            delegate.onFailure(caught);
+        }
+
+        @Override
+        protected final void process(final ResultSet<Experiment> result)
+        {
+            setResultSetKey(result.getResultSetKey());
+            final List<ExperimentModel> experimentModels =
+                    ExperimentModel.asExperimentModels(result.getList());
+            final PagingLoadResult<ExperimentModel> loadResult =
+                    new BasePagingLoadResult<ExperimentModel>(experimentModels, offset, result
+                            .getTotalLength());
+            delegate.onSuccess(loadResult);
+        }
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowserToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowserToolbar.java
new file mode 100644
index 0000000000000000000000000000000000000000..f07549fed63cd92a1a4fccdd47ef0a349739e6e6
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentBrowserToolbar.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment_browser;
+
+import com.extjs.gxt.ui.client.data.ModelData;
+import com.extjs.gxt.ui.client.event.ComponentEvent;
+import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
+import com.extjs.gxt.ui.client.event.SelectionChangedListener;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.MessageBox;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
+import com.google.gwt.user.client.Element;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+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.dto.ExperimentType;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
+
+/**
+ * The toolbar of experiment browser.
+ * 
+ * @author Izabela Adamczyk
+ * @author Christian Ribeaud
+ */
+class ExperimentBrowserToolbar extends ToolBar
+{
+    public static final String ID = "experiment-browser-toolbar";
+
+    private static final String PREFIX = ID + "_";
+
+    static final String REFRESH_BUTTON_ID = GenericConstants.ID_PREFIX + PREFIX + "refresh-button";
+
+    private final ExperimentBrowserGrid experimentBrowserGrid;
+
+    private final ExperimentTypeSelectionWidget selectExperimentTypeCombo;
+
+    private final ProjectSelectionWidget selectProjectCombo;
+
+    private final Button submitButton;
+
+    private final Button exportButton;
+
+    public ExperimentBrowserToolbar(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final ExperimentBrowserGrid experimentBrowserGrid)
+    {
+        this.experimentBrowserGrid = experimentBrowserGrid;
+        selectExperimentTypeCombo = new ExperimentTypeSelectionWidget(viewContext, ID);
+        selectProjectCombo = new ProjectSelectionWidget(viewContext);
+        submitButton = createSubmitButton();
+        submitButton.setEnabled(false);
+        exportButton = createExportButton();
+        exportButton.setEnabled(false);
+        addSelectSampleTypeListeners();
+        addSelectGroupListeners();
+    }
+
+    private void refreshButtons()
+    {
+        final boolean experiementTypeSelected = selectExperimentTypeCombo.tryGetSelected() != null;
+        final boolean projectChosen = selectProjectCombo.tryGetSelected() != null;
+        final boolean enable = experiementTypeSelected && projectChosen;
+        submitButton.setEnabled(enable);
+        exportButton.setEnabled(enable);
+        if (enable)
+        {
+            submitButton.setTitle("Load or update experiment table");
+            exportButton.setTitle("Export experiment table to excel file");
+        } else
+        {
+            final String msg = "HINT: To activate choose experiment type and project.";
+            submitButton.setTitle(msg);
+            exportButton.setTitle(msg);
+        }
+
+    }
+
+    private void addSelectGroupListeners()
+    {
+        selectProjectCombo.addSelectionChangedListener(new SelectionChangedListener<ModelData>()
+            {
+                @Override
+                public final void selectionChanged(final SelectionChangedEvent<ModelData> se)
+                {
+                    refreshButtons();
+                }
+            });
+
+    }
+
+    private void addSelectSampleTypeListeners()
+    {
+        selectExperimentTypeCombo
+                .addSelectionChangedListener(new SelectionChangedListener<ModelData>()
+                    {
+                        @Override
+                        public final void selectionChanged(final SelectionChangedEvent<ModelData> se)
+                        {
+                            refreshButtons();
+                        }
+                    });
+    }
+
+    private void display()
+    {
+        setBorders(true);
+        removeAll();
+        add(new LabelToolItem("Experiment type:"));
+        add(new AdapterToolItem(selectExperimentTypeCombo));
+
+        add(new SeparatorToolItem());
+
+        add(new LabelToolItem("Project:"));
+        add(new AdapterToolItem(selectProjectCombo));
+
+        add(new SeparatorToolItem());
+
+        add(new FillToolItem());
+
+        add(new AdapterToolItem(submitButton));
+
+        add(new SeparatorToolItem());
+
+        add(new AdapterToolItem(exportButton));
+        layout();
+    }
+
+    private Button createSubmitButton()
+    {
+        final Button refreshButton = new Button("Refresh", new SelectionListener<ComponentEvent>()
+            {
+                @Override
+                public final void componentSelected(final ComponentEvent ce)
+                {
+                    final ExperimentType selectedType = selectExperimentTypeCombo.tryGetSelected();
+                    final Project selectedProject =
+                            selectProjectCombo.tryGetSelected() == null ? null : selectProjectCombo
+                                    .tryGetSelected();
+
+                    experimentBrowserGrid.refresh(selectedType, selectedProject);
+                }
+            });
+        refreshButton.setId(REFRESH_BUTTON_ID);
+        return refreshButton;
+    }
+
+    private Button createExportButton()
+    {
+        final Button button = new Button("Export data", new SelectionListener<ComponentEvent>()
+            {
+                @Override
+                public final void componentSelected(final ComponentEvent ce)
+                {
+                    MessageBox.alert("Warning", "Not yet implemented!", null);
+                }
+            });
+        return button;
+    }
+
+    @Override
+    protected final void onRender(final Element parent, final int pos)
+    {
+        super.onRender(parent, pos);
+        display();
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentTypeSelectionWidget.java
new file mode 100644
index 0000000000000000000000000000000000000000..18506bf8f593d6dda1d73f8c113daf8b7d6f4f6c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ExperimentTypeSelectionWidget.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment_browser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.Events;
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.widget.form.ComboBox;
+import com.google.gwt.user.client.Element;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+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.model.ExperimentTypeModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentType;
+
+/**
+ * {@link ComboBox} containing list of experiment types loaded from the server.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ExperimentTypeSelectionWidget extends ComboBox<ExperimentTypeModel>
+{
+
+    public final class ListExperimentTypesCallback extends
+            AbstractAsyncCallback<List<ExperimentType>>
+    {
+        private final boolean allowEmptyCall;
+
+        ListExperimentTypesCallback(final IViewContext<?> viewContext, final boolean allowEmpty)
+        {
+            super(viewContext);
+            allowEmptyCall = allowEmpty;
+        }
+
+        @Override
+        protected void process(final List<ExperimentType> result)
+        {
+            experimentTypeStore.removeAll();
+            experimentTypeStore.add(convert(result));
+            if (experimentTypeStore.getCount() > 0)
+            {
+                setEnabled(true);
+                if (allowEmptyCall == false)
+                {
+                    setValue(experimentTypeStore.getAt(0));
+                }
+            }
+        }
+
+        List<ExperimentTypeModel> convert(final List<ExperimentType> experimentTypes)
+        {
+            final List<ExperimentTypeModel> result = new ArrayList<ExperimentTypeModel>();
+            for (final ExperimentType st : experimentTypes)
+            {
+                result.add(new ExperimentTypeModel(st));
+            }
+            return result;
+        }
+    }
+
+    private static final String PREFIX = "experiment-type-select-";
+
+    public static final String ID = GenericConstants.ID_PREFIX + PREFIX;
+
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    private final ListStore<ExperimentTypeModel> experimentTypeStore;
+
+    private final boolean allowEmpty;
+
+    public ExperimentTypeSelectionWidget(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final String idSuffix)
+    {
+        this(viewContext, false, idSuffix);
+    }
+
+    public ExperimentTypeSelectionWidget(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final boolean allowEmpty, final String idSuffix)
+    {
+        this.viewContext = viewContext;
+        this.allowEmpty = allowEmpty;
+        setId(ID + idSuffix);
+        setEmptyText(allowEmpty ? "Choose experiment type..." : "- No experiment types found -");
+        setEnabled(false);
+        setDisplayField(ModelDataPropertyNames.CODE);
+        setEditable(false);
+        setWidth(150);
+        setFieldLabel("Experiment type");
+        experimentTypeStore = new ListStore<ExperimentTypeModel>();
+        setStore(experimentTypeStore);
+        addListener(Events.OnClick, new Listener<BaseEvent>()
+            {
+
+                public void handleEvent(final BaseEvent be)
+                {
+                    expand();
+                }
+            });
+    }
+
+    public ExperimentType tryGetSelected()
+    {
+
+        final List<ExperimentTypeModel> selection = getSelection();
+        if (selection.size() > 0)
+        {
+            return selection.get(0).get(ModelDataPropertyNames.OBJECT);
+        } else
+        {
+            return null;
+        }
+    }
+
+    @Override
+    protected void onRender(final Element parent, final int pos)
+    {
+        super.onRender(parent, pos);
+        refresh();
+    }
+
+    void refresh()
+    {
+        viewContext.getService().listExperimentTypes(
+                new ListExperimentTypesCallback(viewContext, allowEmpty));
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ProjectSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ProjectSelectionWidget.java
new file mode 100644
index 0000000000000000000000000000000000000000..34da372f4e775a85866e0c7d6b60066e69158117
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment_browser/ProjectSelectionWidget.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment_browser;
+
+import java.util.List;
+
+import com.extjs.gxt.ui.client.Events;
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.widget.form.ComboBox;
+import com.google.gwt.user.client.Element;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+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.framework.AppEvents;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ProjectModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
+
+/**
+ * {@link ComboBox} containing list of projects loaded from the server.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ProjectSelectionWidget extends ComboBox<ProjectModel>
+{
+    public final class ListProjectsCallback extends AbstractAsyncCallback<List<Project>>
+    {
+        ListProjectsCallback(final IViewContext<?> viewContext)
+        {
+            super(viewContext);
+        }
+
+        @Override
+        protected void process(final List<Project> result)
+        {
+            projectStore.removeAll();
+            projectStore.add(ProjectModel.convert(result));
+            if (projectStore.getCount() > 0)
+            {
+                setEnabled(true);
+                setValue(projectStore.getAt(0));
+            }
+            fireEvent(AppEvents.CALLBACK_FINISHED);
+        }
+    }
+
+    private static final String PREFIX = "project-select";
+
+    public static final String ID = GenericConstants.ID_PREFIX + PREFIX;
+
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    private final ListStore<ProjectModel> projectStore;
+
+    public ProjectSelectionWidget(final IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        this.viewContext = viewContext;
+        setId(ID);
+        setEmptyText("- No projects found -");
+        setDisplayField(ModelDataPropertyNames.PROJECT_WITH_GROUP);
+        setEditable(false);
+        setEnabled(false);
+        setWidth(250);
+        setFieldLabel("Project");
+        projectStore = new ListStore<ProjectModel>();
+        setStore(projectStore);
+        addListener(Events.OnClick, new Listener<BaseEvent>()
+            {
+                public void handleEvent(final BaseEvent be)
+                {
+                    expand();
+                }
+            });
+    }
+
+    public Project tryGetSelected()
+    {
+        final List<ProjectModel> selection = getSelection();
+        if (selection.size() > 0)
+        {
+            return selection.get(0).get(ModelDataPropertyNames.OBJECT);
+        } else
+        {
+            return null;
+        }
+    }
+
+    @Override
+    protected void onRender(final Element parent, final int pos)
+    {
+        super.onRender(parent, pos);
+        refresh();
+    }
+
+    void refresh()
+    {
+        viewContext.getService().listProjects(new ListProjectsCallback(viewContext));
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ColumnChooser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ColumnChooser.java
index abc4ac9bfecde19ecddad6e7c45965e8aa3043ce..6eb316f7679599b0e0f39e1225d3f72a45fe7e8a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ColumnChooser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ColumnChooser.java
@@ -39,7 +39,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.Propert
  * 
  * @author Izabela Adamczyk
  */
-final class ColumnChooser extends TextToolItem
+public final class ColumnChooser extends TextToolItem
 {
     public static final String ID = GenericConstants.ID_PREFIX + "column_chooser";
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/SampleBrowserToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/SampleBrowserToolbar.java
index 59070d0886f0561a9f0f9e5020ff8a0f5bc61456..6167b53f4d21b097d40addb739e4d6e29e2a7d57 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/SampleBrowserToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/SampleBrowserToolbar.java
@@ -38,6 +38,7 @@ 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.framework.AppEvents;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.ParentColumns;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PropertyColumns;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleType;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ToolbarController.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ToolbarController.java
index 67e781d050801dca86caad1974b7272e5aa46281..af933cdf3c8e6c5f4ea490e844209c216db074e2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ToolbarController.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ToolbarController.java
@@ -21,6 +21,7 @@ import com.extjs.gxt.ui.client.widget.form.CheckBox;
 import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
 import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.ParentColumns;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PropertyColumns;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleType;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListExperimentsCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListExperimentsCriteria.java
new file mode 100644
index 0000000000000000000000000000000000000000..aec5c8a03b07f58f011c20254a049055be48806f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListExperimentsCriteria.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Criteria for listing <i>experiments</i>.
+ * 
+ * @author Izabela Adamczyk
+ */
+public final class ListExperimentsCriteria extends DefaultResultSetConfig<String> implements
+        IsSerializable
+{
+    private ExperimentType experimentType;
+
+    private String groupCode;
+
+    private String projectCode;
+
+    public ExperimentType getExperimentType()
+    {
+        return experimentType;
+    }
+
+    public void setExperimentType(final ExperimentType experimentType)
+    {
+        this.experimentType = experimentType;
+    }
+
+    public String getGroupCode()
+    {
+        return groupCode;
+    }
+
+    public void setGroupCode(final String groupCode)
+    {
+        this.groupCode = groupCode;
+    }
+
+    public String getProjectCode()
+    {
+        return projectCode;
+    }
+
+    public void setProjectCode(final String projectCode)
+    {
+        this.projectCode = projectCode;
+    }
+
+}
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 d45d0afbfb80d7c53c6ad8f7a53a15d74e576b48..bc899765a9f8e6d2387d196687139aadb59480db 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
@@ -25,12 +25,16 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.servlet.IRequestContextProvider;
 import ch.systemsx.cisd.common.utilities.BeanUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientService;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Sample;
@@ -40,9 +44,11 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IOriginalDat
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IResultSetManager;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.DtoConverters;
+import ch.systemsx.cisd.openbis.generic.client.web.server.util.ExperimentTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.GroupTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.ListSampleCriteriaTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.PersonTranslator;
+import ch.systemsx.cisd.openbis.generic.client.web.server.util.ProjectTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.ResultSetTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.RoleAssignmentTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.RoleCodeTranslator;
@@ -53,14 +59,18 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.util.UserFailureExcept
 import ch.systemsx.cisd.openbis.generic.server.SessionConstants;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
 import ch.systemsx.cisd.openbis.plugin.AbstractClientService;
@@ -302,6 +312,41 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    public final ResultSet<Experiment> listExperiments(final ListExperimentsCriteria listCriteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final IResultSetManager<String> resultSetManager = getResultSetManager();
+            final IResultSet<String, Experiment> result =
+                    resultSetManager.getResultSet(listCriteria,
+                            new IOriginalDataProvider<Experiment>()
+                                {
+                                    public final List<Experiment> getOriginalData()
+                                    {
+                                        final List<ExperimentPE> experiments =
+                                                commonServer.listExperiments(getSessionToken(),
+                                                        ExperimentTranslator.translate(listCriteria
+                                                                .getExperimentType()),
+                                                        new ProjectIdentifier(listCriteria
+                                                                .getGroupCode(), listCriteria
+                                                                .getProjectCode()));
+                                        final List<Experiment> list =
+                                                new ArrayList<Experiment>(experiments.size());
+                                        for (final ExperimentPE experiment : experiments)
+                                        {
+                                            list.add(ExperimentTranslator.translate(experiment));
+                                        }
+                                        return list;
+                                    }
+                                });
+            return ResultSetTranslator.translate(result);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     public final List<ExternalData> listExternalData(final String sampleIdentifier)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
@@ -381,4 +426,41 @@ public final class CommonClientService extends AbstractClientService implements
             throw UserFailureExceptionTranslator.translate(e);
         }
     }
+
+    public List<Project> listProjects()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final List<Project> result = new ArrayList<Project>();
+            final List<ProjectPE> projects = commonServer.listProjects(getSessionToken());
+            for (final ProjectPE project : projects)
+            {
+                result.add(ProjectTranslator.translate(project));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public List<ExperimentType> listExperimentTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final List<ExperimentType> result = new ArrayList<ExperimentType>();
+            final List<ExperimentTypePE> projects =
+                    commonServer.listExperimentTypes(getSessionToken());
+            for (final ExperimentTypePE expType : projects)
+            {
+                result.add(ExperimentTranslator.translate(expType));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/ExperimentTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/ExperimentTranslator.java
index e9dbd78ceb6b2810462df4c1d05bf78a004ca251..03fcad46c4174d6f03999adc40b533733deb32c2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/ExperimentTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/ExperimentTranslator.java
@@ -45,10 +45,12 @@ public final class ExperimentTranslator
         result.setExperimentType(translate(experiment.getExperimentType()));
         result.setExperimentIdentifier(experiment.getIdentifier());
         result.setProject(ProjectTranslator.translate(experiment.getProject()));
+        result.setRegistrationDate(experiment.getRegistrationDate());
+        result.setRegistrator(PersonTranslator.translate(experiment.getRegistrator()));
         return result;
     }
 
-    private final static ExperimentType translate(final ExperimentTypePE experimentType)
+    public final static ExperimentType translate(final ExperimentTypePE experimentType)
     {
         final ExperimentType result = new ExperimentType();
         result.setCode(experimentType.getCode());
@@ -58,4 +60,14 @@ public final class ExperimentTranslator
         return result;
     }
 
+    public final static ExperimentTypePE translate(final ExperimentType experimentType)
+    {
+        final ExperimentTypePE result = new ExperimentTypePE();
+        result.setCode(experimentType.getCode());
+        result.setDescription(experimentType.getDescription());
+        result.setDatabaseInstance(DatabaseInstanceTranslator.translate(experimentType
+                .getDatabaseInstance()));
+        return result;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
index 95aabe175c68d35db02860871065011a963726ef..690b96f17aa3c4bf3597015e28623e1a3d4c919b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
@@ -17,9 +17,11 @@
 package ch.systemsx.cisd.openbis.generic.server;
 
 import ch.systemsx.cisd.openbis.generic.server.business.bo.AbstractBusinessObjectFactory;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.ExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.GroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
@@ -72,4 +74,9 @@ public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFac
     {
         return new ExternalDataTable(getDaoFactory(), session);
     }
+
+    public IExperimentTable createExperimentTable(final Session session)
+    {
+        return new ExperimentTable(getDaoFactory(), session);
+    }
 }
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 28a195f167da79c5f2e9f9dc9828dfbcd92aca64..c679c38d3280ee58815f98c2ef73c0782ecc43f3 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
@@ -29,6 +29,7 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.utilities.ParameterChecker;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
@@ -39,11 +40,15 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IRoleAssignmentDAO;
 import ch.systemsx.cisd.openbis.generic.server.util.GroupIdentifierHelper;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSampleCriteriaDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewRoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
@@ -54,7 +59,9 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
 /**
  * Implementation of client-server interface.
@@ -256,6 +263,14 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         return persons;
     }
 
+    public final List<ProjectPE> listProjects(final String sessionToken)
+    {
+        getSessionManager().getSession(sessionToken);
+        final List<ProjectPE> projects = getDAOFactory().getProjectDAO().listProjects();
+        Collections.sort(projects);
+        return projects;
+    }
+
     public final List<SampleTypePE> listSampleTypes(final String sessionToken)
     {
         getSessionManager().getSession(sessionToken);
@@ -312,4 +327,31 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         sampleBO.define(newSample);
         sampleBO.save();
     }
+
+    public List<ExperimentPE> listExperiments(final String sessionToken,
+            final ExperimentTypePE experimentType, final ProjectIdentifier projectIdentifier)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IExperimentTable experimentTable =
+                businessObjectFactory.createExperimentTable(session);
+        experimentTable.load(experimentType.getCode(), projectIdentifier);
+        final List<ExperimentPE> experiments = experimentTable.getExperiments();
+        Collections.sort(experiments);
+        return experiments;
+    }
+
+    public List<ExperimentTypePE> listExperimentTypes(final String sessionToken)
+    {
+        getSessionManager().getSession(sessionToken);
+        final List<ExperimentTypePE> experimentTypes =
+                cast(getDAOFactory().getEntityTypeDAO(EntityKind.EXPERIMENT).listEntityTypes());
+        Collections.sort(experimentTypes);
+        return experimentTypes;
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<ExperimentTypePE> cast(final List<? extends EntityTypePE> experimentTypes)
+    {
+        return (List<ExperimentTypePE>) experimentTypes;
+    }
 }
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 29161b052c72ec7062d9189f8a28c2c4ccede3c1..b664503d45b9a80227bd8fcacffdf9ece24311c7 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
@@ -21,10 +21,13 @@ import java.util.List;
 
 import ch.systemsx.cisd.authentication.ISessionManager;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSampleCriteriaDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
@@ -38,6 +41,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 
 /**
@@ -154,23 +158,22 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
     public final SampleGenerationDTO getSampleInfo(final String sessionToken,
             final SampleIdentifier identifier)
     {
-        logTracking(sessionToken, "get_sample_info", "IDENTIFIER(%s)", identifier);
+        logAccess(sessionToken, "get_sample_info", "IDENTIFIER(%s)", identifier);
         return null;
     }
 
     public final List<ExternalDataPE> listExternalData(final String sessionToken,
             final SampleIdentifier identifier)
     {
-        logTracking(sessionToken, "list_external_data", "IDENTIFIER(%s)", identifier);
+        logAccess(sessionToken, "list_external_data", "IDENTIFIER(%s)", identifier);
         return null;
     }
 
     public final List<SearchHit> listMatchingEntities(final String sessionToken,
             final SearchableEntity[] searchableEntities, final String queryText)
     {
-        logTracking(sessionToken, "list_matching_entities",
-                "SEARCHABLE-ENTITIES(%s) QUERY-TEXT(%s)", Arrays.toString(searchableEntities),
-                queryText);
+        logAccess(sessionToken, "list_matching_entities", "SEARCHABLE-ENTITIES(%s) QUERY-TEXT(%s)",
+                Arrays.toString(searchableEntities), queryText);
         return null;
     }
 
@@ -179,4 +182,23 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         logTracking(sessionToken, "register_sample", "SAMPLE_TYPE(%s) SAMPLE(%S)", newSample
                 .getSampleTypeCode(), newSample.getSampleIdentifier());
     }
+
+    public List<ExperimentPE> listExperiments(final String sessionToken,
+            final ExperimentTypePE experimentType, final ProjectIdentifier project)
+    {
+        logAccess(sessionToken, "list_experiments", "TYPE(%s) PROJECT(%s)", experimentType, project);
+        return null;
+    }
+
+    public List<ProjectPE> listProjects(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_projects");
+        return null;
+    }
+
+    public List<ExperimentTypePE> listExperimentTypes(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_experiment_types");
+        return null;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
index 35aa05107e6c47799d0a01aa1e06041079fcba77..25e812f3790315678f03033f5e5eb57af3a37410 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
@@ -23,10 +23,12 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDatabaseInstanceDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityPropertyTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGroupDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPersonDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPropertyTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IRoleAssignmentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
@@ -58,7 +60,7 @@ abstract class AbstractBusinessObject implements IDAOFactory
 
     protected final PersonPE findRegistrator()
     {
-        PersonPE registrator = session.tryGetPerson();
+        final PersonPE registrator = session.tryGetPerson();
         assert registrator != null : "Missing person instance in session object.";
         return registrator;
     }
@@ -123,13 +125,23 @@ abstract class AbstractBusinessObject implements IDAOFactory
         return daoFactory.getPropertyTypeDAO();
     }
 
-    public IEntityTypeDAO getEntityTypeDAO(EntityKind entityKind)
+    public IEntityTypeDAO getEntityTypeDAO(final EntityKind entityKind)
     {
         return daoFactory.getEntityTypeDAO(entityKind);
     }
 
-    public IEntityPropertyTypeDAO getEntityPropertyTypeDAO(EntityKind entityKind)
+    public IEntityPropertyTypeDAO getEntityPropertyTypeDAO(final EntityKind entityKind)
     {
         return daoFactory.getEntityPropertyTypeDAO(entityKind);
     }
+
+    public IExperimentDAO getExperimentDAO()
+    {
+        return daoFactory.getExperimentDAO();
+    }
+
+    public IProjectDAO getProjectDAO()
+    {
+        return daoFactory.getProjectDAO();
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8b4b749b1fbb203d6b240db28c431a7aa42c5ae
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentTable.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2007 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.business.bo;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import ch.rinn.restrictions.Private;
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.server.util.GroupIdentifierHelper;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProcedurePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
+
+/**
+ * The only productive implementation of {@link IExperimentTable}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public final class ExperimentTable extends AbstractBusinessObject implements IExperimentTable
+{
+    private List<ExperimentPE> experiments;
+
+    public ExperimentTable(final IDAOFactory daoFactory, final Session session)
+    {
+        super(daoFactory, session);
+    }
+
+    //
+    // IExperimentTable
+    //
+
+    public final void load(final String experimentTypeCode,
+            final ProjectIdentifier projectIdentifier)
+    {
+        checkNotNull(experimentTypeCode, projectIdentifier);
+        final EntityTypePE entityType =
+                getEntityTypeDAO(EntityKind.EXPERIMENT).tryToFindEntityTypeByCode(
+                        experimentTypeCode);
+        checkNotNull(experimentTypeCode, entityType);
+        if (org.apache.commons.lang.StringUtils.isBlank(projectIdentifier.getGroupCode()))
+        {
+            final GroupPE group =
+                    GroupIdentifierHelper.tryGetGroup(projectIdentifier, findRegistrator(), this);
+            checkNotNull(projectIdentifier, group);
+            projectIdentifier.setDatabaseInstanceCode(group.getDatabaseInstance().getCode());
+            projectIdentifier.setGroupCode(group.getCode());
+        }
+        final ProjectPE project =
+                getProjectDAO().tryFindProject(projectIdentifier.getDatabaseInstanceCode(),
+                        projectIdentifier.getGroupCode(), projectIdentifier.getProjectCode());
+        checkNotNull(projectIdentifier, project);
+        experiments = getExperimentDAO().listExperiments((ExperimentTypePE) entityType, project);
+    }
+
+    private void checkNotNull(final ProjectIdentifier projectIdentifier, final ProjectPE project)
+    {
+        if (project == null)
+        {
+            throw new UserFailureException("Project '" + projectIdentifier + "' unknown.");
+        }
+    }
+
+    private void checkNotNull(final ProjectIdentifier projectIdentifier, final GroupPE group)
+    {
+        if (group == null)
+        {
+            throw new UserFailureException("Unknown project '" + projectIdentifier + "'.");
+        }
+    }
+
+    private void checkNotNull(final String experimentTypeCode, final EntityTypePE entityType)
+    {
+        if (entityType == null)
+        {
+            throw new UserFailureException("Unknown experiment type '" + experimentTypeCode + "'.");
+        }
+    }
+
+    private void checkNotNull(final String experimentTypeCode,
+            final ProjectIdentifier projectIdentifier)
+    {
+        if (experimentTypeCode == null)
+        {
+            throw new UserFailureException("Experiment type not specified.");
+        }
+        if (projectIdentifier == null)
+        {
+            throw new UserFailureException("Project not specified.");
+        }
+    }
+
+    public final void save()
+    {
+        throw new UnsupportedOperationException("Experiment table can not be saved.");
+    }
+
+    public final Iterator<ExperimentPE> iterator()
+    {
+        return experiments == null ? Collections.<ExperimentPE> emptyList().iterator()
+                : experiments.iterator();
+    }
+
+    public final void enrichWithProperties()
+    {
+        if (experiments != null)
+        {
+            for (final ExperimentPE experiment : experiments)
+            {
+                HibernateUtils.initialize(experiment.getProperties());
+            }
+        }
+    }
+
+    public final List<ExperimentPE> getExperiments()
+    {
+        assert experiments != null : "Experiments have not been loaded.";
+        return experiments;
+    }
+
+    public void enrichWithLastDataSetDates()
+    {
+        if (experiments == null)
+        {
+            return;
+        }
+
+        for (final ExperimentPE e : experiments)
+        {
+            setLastDatasetDate(e);
+        }
+
+    }
+
+    /**
+     * Helper method setting the last data set date for given experiment.
+     */
+    @Private
+    final void setLastDatasetDate(final ExperimentPE experiment)
+    {
+        final List<ProcedurePE> procedures = experiment.getProcedures();
+        if (procedures.isEmpty())
+        {
+            return;
+        }
+        Date soFarNewestDataSetDateFound = null;
+        for (final ProcedurePE procedure : procedures)
+        {
+            final Set<DataPE> dataPEs = procedure.getData();
+            if (dataPEs.isEmpty())
+            {
+                continue;
+            }
+            for (final DataPE dataPE : dataPEs)
+            {
+                final Date registrationDate = dataPE.getRegistrationDate();
+                if (isAttachedToValidSample(dataPE)
+                        && newerDataSetDateFound(soFarNewestDataSetDateFound, registrationDate))
+                {
+                    soFarNewestDataSetDateFound = registrationDate;
+                }
+            }
+        }
+        experiment.setLastDataSetDate(soFarNewestDataSetDateFound);
+
+    }
+
+    @Private
+    final boolean newerDataSetDateFound(final Date newestDataSetDateFound,
+            final Date registrationDate)
+    {
+        return newestDataSetDateFound == null || newestDataSetDateFound.before(registrationDate);
+    }
+
+    /**
+     * Helper method checking if given data set is attached to valid sample.
+     */
+    @Private
+    final boolean isAttachedToValidSample(final DataPE data)
+    {
+        boolean attachedSampleIsValid = false;
+        final SamplePE sampleAcquired = data.getSampleAcquiredFrom();
+        final SamplePE sampleDerived = data.getSampleDerivedFrom();
+        if (sampleAcquired != null && sampleAcquired.getInvalidation() == null
+                || sampleDerived != null && sampleDerived.getInvalidation() == null)
+        {
+            attachedSampleIsValid = true;
+        }
+        return attachedSampleIsValid;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
index 3ac6db43f94d87c7c1fbd438f7d7701722ff99c2..fdd5aa33dc5a01b9b088860c2b0edf020402c655 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
@@ -40,4 +40,9 @@ public interface ICommonBusinessObjectFactory
      * Creates a {@link IExternalDataTable} <i>Business Object</i>.
      */
     public IExternalDataTable createExternalDataTable(final Session session);
+
+    /**
+     * Creates a {@link IExperimentTable} <i>Business Object</i>.
+     */
+    public IExperimentTable createExperimentTable(final Session session);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..c16d1ba3a3d0fa8d62c8c00b43b383fd01095096
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentTable.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2007 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.business.bo;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
+
+/**
+ * Read-only table for experiments. Holds a collection of instances of {@link ExperimentPE}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IExperimentTable extends IBusinessObject, Iterable<ExperimentPE>
+{
+    /**
+     * Loads all experiments of given type and from given project.
+     * 
+     * @param experimentTypeCodeOrNull the experiment type code or <code>null</code>.
+     * @param projectIdentifier identifier of the project to which we restrict the load.
+     */
+    public void load(String experimentTypeCodeOrNull, ProjectIdentifier projectIdentifier);
+
+    /**
+     * Enriches the experiments with their property type values.
+     */
+    public void enrichWithProperties();
+
+    /** Returns the loaded {@link ExperimentPE}. */
+    public List<ExperimentPE> getExperiments();
+
+    /**
+     * Enriches the experiments with their the date of registration of the last datasets attached to
+     * them.
+     */
+    public void enrichWithLastDataSetDates();
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java
index 407860d8756658030c2dbdd27d7efbd8e0464227..235af757f268fb624264cdf79a855a239fb2549e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java
@@ -60,4 +60,14 @@ public interface IDAOFactory extends IAuthorizationDAOFactory
      * Returns the {@link IEntityPropertyTypeDAO} implementation.
      */
     public IEntityPropertyTypeDAO getEntityPropertyTypeDAO(EntityKind entityKind);
+
+    /**
+     * Returns the implementation of {@link IExperimentDAO}.
+     */
+    public IExperimentDAO getExperimentDAO();
+
+    /**
+     * @return The implementation of the {@link IProjectDAO}.
+     */
+    public IProjectDAO getProjectDAO();
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbb524f86bedb72477196364e9cd5c131107c63c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007 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;
+
+import java.util.List;
+
+import org.springframework.dao.DataAccessException;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+
+/**
+ * <i>Data Access Object</i> for {@link ExperimentPE}.
+ * 
+ * @author Franz-Josef Elmer
+ */
+public interface IExperimentDAO
+{
+    /**
+     * Lists all of given <code>type</code> belonging to given <code>project</code>.
+     */
+    public List<ExperimentPE> listExperiments(final ExperimentTypePE experimentType,
+            final ProjectPE project) throws DataAccessException;
+
+    /**
+     * Lists all registered experiments.
+     */
+    public List<ExperimentPE> listExperiments() throws DataAccessException;
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IProjectDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IProjectDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..3bc66d86a1cae9251710f3976b59b2a4cce623e3
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IProjectDAO.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+
+/**
+ * <i>Data Access Object</i> for {@link ProjectPE}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IProjectDAO
+{
+    public List<ProjectPE> listProjects();
+
+    public List<ProjectPE> listProjects(GroupPE group);
+
+    public ProjectPE tryFindProject(String databaseInstanceCode, String groupCode,
+            String projectCode);
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java
index 927aae72412dab2dddf0d1b038d44310fa07f8ef..855255ab716cdb2de4a6459808d7ccf6fbe838aa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java
@@ -62,6 +62,7 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory
         personDAO = new PersonDAO(sessionFactory, homeDatabaseInstance);
         groupDAO = new GroupDAO(sessionFactory, homeDatabaseInstance);
         roleAssignmentDAO = new RoleAssignmentDAO(sessionFactory, homeDatabaseInstance);
+
     }
 
     private final DatabaseInstancePE getDatabaseInstanceId(final String databaseInstanceCode)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
index 93fdf095f5413b0eaed03331a6af3630fc22870b..bdd628d434c1bfae6c941ca474bdf3d2f570b028 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
@@ -25,8 +25,10 @@ import ch.systemsx.cisd.dbmigration.DatabaseConfigurationContext;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityPropertyTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPropertyTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleTypeDAO;
@@ -57,6 +59,10 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
     private final Map<EntityKind, IEntityPropertyTypeDAO> entityPropertyTypeDAOs =
             new HashMap<EntityKind, IEntityPropertyTypeDAO>();
 
+    private final ExperimentDAO experimentDAO;
+
+    private final IProjectDAO projectDAO;
+
     public DAOFactory(final DatabaseConfigurationContext context,
             final SessionFactory sessionFactory)
     {
@@ -67,6 +73,8 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
         externalDataDAO = new ExternalDataDAO(sessionFactory, databaseInstance);
         hibernateSearchDAO = new HibernateSearchDAO(sessionFactory);
         propertyTypeDAO = new PropertyTypeDAO(sessionFactory, databaseInstance);
+        experimentDAO = new ExperimentDAO(sessionFactory, databaseInstance);
+        projectDAO = new ProjectDAO(sessionFactory, databaseInstance);
         final EntityKind[] entityKinds = EntityKind.values();
         for (final EntityKind entityKind : entityKinds)
         {
@@ -102,12 +110,12 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
         return hibernateSearchDAO;
     }
 
-    public IEntityPropertyTypeDAO getEntityPropertyTypeDAO(EntityKind entityKind)
+    public IEntityPropertyTypeDAO getEntityPropertyTypeDAO(final EntityKind entityKind)
     {
         return entityPropertyTypeDAOs.get(entityKind);
     }
 
-    public IEntityTypeDAO getEntityTypeDAO(EntityKind entityKind)
+    public IEntityTypeDAO getEntityTypeDAO(final EntityKind entityKind)
     {
         return entityTypeDAOs.get(entityKind);
     }
@@ -116,4 +124,14 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
     {
         return propertyTypeDAO;
     }
+
+    public IExperimentDAO getExperimentDAO()
+    {
+        return experimentDAO;
+    }
+
+    public final IProjectDAO getProjectDAO()
+    {
+        return projectDAO;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6dba391ac9de88d11d1cd603d8e907733b6352c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Restrictions;
+import org.springframework.dao.DataAccessException;
+
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.utilities.MethodUtils;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+
+/**
+ * Data access object for {@link ExperimentPE}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ExperimentDAO extends AbstractDAO implements IExperimentDAO
+{
+
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, ExperimentDAO.class);
+
+    protected ExperimentDAO(final SessionFactory sessionFactory,
+            final DatabaseInstancePE databaseInstance)
+    {
+        super(sessionFactory, databaseInstance);
+    }
+
+    public List<ExperimentPE> listExperiments(final ExperimentTypePE experimentType,
+            final ProjectPE project) throws DataAccessException
+    {
+        assert experimentType != null : "Unspecified experiment type.";
+        assert project != null : "Unspecified project.";
+
+        final DetachedCriteria criteria = DetachedCriteria.forClass(ExperimentPE.class);
+        criteria.add(Restrictions.eq("experimentType", experimentType));
+        criteria.add(Restrictions.eq("project", project));
+        final List<ExperimentPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format(
+                    "%d experiments have been found for experiment type '%s' and project '%s'.",
+                    list.size(), experimentType, project));
+        }
+        return list;
+    }
+
+    public List<ExperimentPE> listExperiments() throws DataAccessException
+    {
+        final List<ExperimentPE> list = cast(getHibernateTemplate().loadAll(ExperimentPE.class));
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format("%s(): %d experiment(s) have been found.", MethodUtils
+                    .getCurrentMethod().getName(), list.size()));
+        }
+        return list;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ProjectDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ProjectDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e64a0754e70a7d45f3652319fa43d6bb34476765
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ProjectDAO.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.hibernate.Criteria;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Restrictions;
+
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.utilities.MethodUtils;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.CodeConverter;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+
+/**
+ * Implementation of {@link IProjectDAO}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ProjectDAO extends AbstractDAO implements IProjectDAO
+{
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, ProjectDAO.class);
+
+    protected ProjectDAO(final SessionFactory sessionFactory,
+            final DatabaseInstancePE databaseInstance)
+    {
+        super(sessionFactory, databaseInstance);
+    }
+
+    public List<ProjectPE> listProjects()
+    {
+        final List<ProjectPE> list = cast(getHibernateTemplate().loadAll(ProjectPE.class));
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format("%s(): %d projects(s) have been found.", MethodUtils
+                    .getCurrentMethod().getName(), list.size()));
+        }
+        return list;
+    }
+
+    public List<ProjectPE> listProjects(final GroupPE group)
+    {
+        assert group != null : "Unspecified group.";
+
+        final DetachedCriteria criteria = DetachedCriteria.forClass(ProjectPE.class);
+        criteria.add(Restrictions.eq("group", group));
+        final List<ProjectPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format("%s(%s): %d project(s) have been found.", MethodUtils
+                    .getCurrentMethod().getName(), group, list.size()));
+        }
+        return list;
+    }
+
+    public ProjectPE tryFindProject(final String databaseInstanceCode, final String groupCode,
+            final String projectCode)
+    {
+        assert projectCode != null : "Unspecified project code.";
+        assert groupCode != null : "Unspecified group code.";
+
+        final Criteria criteria = getSession().createCriteria(ProjectPE.class);
+        criteria.add(Restrictions.eq("code", CodeConverter.tryToDatabase(projectCode)));
+        final Criteria groupCriteria = criteria.createCriteria("group");
+        groupCriteria.add(
+                Restrictions.eq("code", CodeConverter.tryToDatabase(groupCode)));
+        if (StringUtils.isBlank(databaseInstanceCode))
+        {
+            groupCriteria.add(
+                    Restrictions.eq("databaseInstance", getDatabaseInstance()));
+        } else
+        {
+            groupCriteria.createCriteria("databaseInstance").add(
+                    Restrictions.eq("code", CodeConverter.tryToDatabase(databaseInstanceCode)));
+        }
+        final ProjectPE project = (ProjectPE) criteria.uniqueResult();
+        return project;
+    }
+
+}
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 c10ab3bbd6ce91b3aefff320b8a8ce14179ae213..f630f3086b0748162a11a25f9f42c7708472356f 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
@@ -27,10 +27,13 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAll
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.GroupIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.GroupValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.MatchingEntityValidator;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSampleCriteriaDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
@@ -39,6 +42,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SearchHit;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 
 /**
@@ -71,6 +75,13 @@ public interface ICommonServer extends IServer
     @RolesAllowed(RoleSet.OBSERVER)
     public List<PersonPE> listPersons(String sessionToken);
 
+    /**
+     * Returns all projects.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<ProjectPE> listProjects(String sessionToken);
+
     /**
      * Registers a new person.
      */
@@ -132,6 +143,14 @@ public interface ICommonServer extends IServer
     public List<SamplePE> listSamples(final String sessionToken,
             final ListSampleCriteriaDTO criteria);
 
+    /**
+     * Lists experiments.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<ExperimentPE> listExperiments(final String sessionToken,
+            ExperimentTypePE experimentType, ProjectIdentifier project);
+
     /**
      * For given {@link SampleIdentifier} returns the corresponding list of {@link ExternalDataPE}.
      */
@@ -149,4 +168,11 @@ public interface ICommonServer extends IServer
     public List<SearchHit> listMatchingEntities(final String sessionToken,
             final SearchableEntity[] searchableEntities, final String queryText);
 
+    /**
+     * List experiment types.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<ExperimentTypePE> listExperimentTypes(String sessionToken);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java
index e18f0b4a239f06980646c87ea2f6aeafc6884af0..fed12051dc546cad9a93d2bf23671dc67c275f44 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java
@@ -43,7 +43,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAs
 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.renderer.DateRenderer;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample_browser.GroupSelectionWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
@@ -62,6 +62,7 @@ import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientS
  */
 public final class GenericSampleRegistrationForm extends FormPanel
 {
+
     private static final String PREFIX = "generic-sample-registration_";
 
     public static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX;
@@ -467,6 +468,7 @@ public final class GenericSampleRegistrationForm extends FormPanel
             super(label, true);
             setRegex(GenericConstants.CODE_PATTERN);
         }
+
     }
 
     private final static class RealField extends BasicTextField<Double>
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java
index 1f8309cb63352703c6c80516fd4de8e020eef4ef..df0860299d8568ae93125b1e99974681fe59d4a7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java
@@ -31,7 +31,7 @@ import ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames;
 @Component(ResourceNames.GENERIC_BUSINESS_OBJECT_FACTORY)
 public final class GenericBusinessObjectFactory extends AbstractPluginBusinessObjectFactory
         implements IGenericBusinessObjectFactory
-{
+    {
 
     //
     // IGenericBusinessObjectFactory
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index fc35df539f863cb48902a70b2474db2dee3eb33a..ba53fa3a104cc4c7b00aceea09c17b7491531058 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -85,6 +85,12 @@ var common = {
   generated_samples: "Generated Samples",
   generated_from: "Parent {0}",
   part_of: "Container {0}",
+  
+  //
+  // Experiment Browser
+  //
+  
+  experiment_type: "Experiment type",
 
   // LAST LINE: KEEP IT AT THE END
   lastline: "" // we need a line without a comma
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ListSamples.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ListSamples.java
index 27096d2c11c0d506e53791fa5e112b8b2863eb3e..442abd8ef0d371e0184a3c8e78e830e457d58746 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ListSamples.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample_browser/ListSamples.java
@@ -22,6 +22,7 @@ import com.extjs.gxt.ui.client.widget.form.ComboBox;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.SampleTypeModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget;
 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;
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5e00f7c1c23ae9a3a17d16793699061400e0405
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.dto.types.ExperimentTypeCode;
+
+/**
+ * Test cases for {@link ExperimentDAO}.
+ * 
+ * @author Izabela Adamczyk
+ */
+@Test(groups =
+    { "db", "experiment" })
+public class ExperimentDAOTest extends AbstractDAOTest
+{
+
+    private static final String CISD_CISD_NEMO_EXP11 = "CISD:/CISD/NEMO/EXP11";
+
+    private static final String CISD_CISD_NEMO_EXP10 = "CISD:/CISD/NEMO/EXP10";
+
+    private static final String CISD_CISD_NEMO_EXP1 = "CISD:/CISD/NEMO/EXP1";
+
+    private static final String CISD_CISD_DEFAULT_EXP_X = "CISD:/CISD/DEFAULT/EXP-X";
+
+    private static final String CISD_CISD_DEFAULT_EXP_REUSE = "CISD:/CISD/DEFAULT/EXP-REUSE";
+
+    @Test
+    public void testListExperiments() throws Exception
+    {
+        final List<ExperimentPE> experiments = daoFactory.getExperimentDAO().listExperiments();
+        Collections.sort(experiments);
+        assertEquals(5, experiments.size());
+        assertEquals(CISD_CISD_DEFAULT_EXP_REUSE, experiments.get(0).getIdentifier());
+        assertEquals(CISD_CISD_DEFAULT_EXP_X, experiments.get(1).getIdentifier());
+        assertEquals(CISD_CISD_NEMO_EXP1, experiments.get(2).getIdentifier());
+        assertEquals(CISD_CISD_NEMO_EXP10, experiments.get(3).getIdentifier());
+        assertEquals(CISD_CISD_NEMO_EXP11, experiments.get(4).getIdentifier());
+    }
+
+    @Test
+    public void testListExperimentsFromProject() throws Exception
+    {
+        List<ExperimentPE> experiments = daoFactory.getExperimentDAO().listExperiments();
+        Collections.sort(experiments);
+        assertEquals(5, experiments.size());
+        final ExperimentPE expInNemo = experiments.get(4);
+        assertEquals(CISD_CISD_NEMO_EXP11, expInNemo.getIdentifier());
+
+        final ProjectPE projectNemo = expInNemo.getProject();
+        assertEquals(ProjectDAOTest.NEMO, projectNemo.getCode());
+
+        final ExperimentTypePE expType = expInNemo.getExperimentType();
+        assertEquals(ExperimentTypeCode.SIRNA_HCS.getCode(), expType.getCode());
+
+        experiments = daoFactory.getExperimentDAO().listExperiments(expType, projectNemo);
+        Collections.sort(experiments);
+        assertEquals(3, experiments.size());
+        assertEquals(CISD_CISD_NEMO_EXP1, experiments.get(0).getIdentifier());
+        assertEquals(CISD_CISD_NEMO_EXP10, experiments.get(1).getIdentifier());
+        assertEquals(CISD_CISD_NEMO_EXP11, experiments.get(2).getIdentifier());
+    }
+
+    @Test
+    public void testListExperimentsFromAnotherProject() throws Exception
+    {
+        List<ExperimentPE> experiments = daoFactory.getExperimentDAO().listExperiments();
+        Collections.sort(experiments);
+        assertEquals(5, experiments.size());
+        final ExperimentPE expInDefault = experiments.get(0);
+        assertEquals(CISD_CISD_DEFAULT_EXP_REUSE, expInDefault.getIdentifier());
+
+        final ProjectPE projectDefault = expInDefault.getProject();
+        assertEquals(ProjectDAOTest.DEFAULT, projectDefault.getCode());
+
+        final ExperimentTypePE expType = expInDefault.getExperimentType();
+        assertEquals(ExperimentTypeCode.SIRNA_HCS.getCode(), expType.getCode());
+
+        experiments = daoFactory.getExperimentDAO().listExperiments(expType, projectDefault);
+        Collections.sort(experiments);
+        assertEquals(2, experiments.size());
+        assertEquals(CISD_CISD_DEFAULT_EXP_REUSE, experiments.get(0).getIdentifier());
+        assertEquals(CISD_CISD_DEFAULT_EXP_X, experiments.get(1).getIdentifier());
+    }
+
+    @Test
+    public void testListExperimentsOfAnotherType() throws Exception
+    {
+        List<ExperimentPE> experiments = daoFactory.getExperimentDAO().listExperiments();
+        Collections.sort(experiments);
+        assertEquals(5, experiments.size());
+        final ExperimentPE expInDefault = experiments.get(0);
+        assertEquals(CISD_CISD_DEFAULT_EXP_REUSE, expInDefault.getIdentifier());
+
+        final ProjectPE projectDefault = expInDefault.getProject();
+        assertEquals(ProjectDAOTest.DEFAULT, projectDefault.getCode());
+
+        final List<EntityTypePE> types =
+                daoFactory.getEntityTypeDAO(EntityKind.EXPERIMENT).listEntityTypes();
+        Collections.sort(types);
+        assertEquals(2, types.size());
+        final ExperimentTypePE expType = (ExperimentTypePE) types.get(0);
+        assertEquals(ExperimentTypeCode.COMPOUND_HCS.getCode(), expType.getCode());
+
+        experiments = daoFactory.getExperimentDAO().listExperiments(expType, projectDefault);
+        Collections.sort(experiments);
+        assertEquals(0, experiments.size());
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ProjectDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ProjectDAOTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..753180380aa4cbafa9d6abe07362d6a75fc04049
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ProjectDAOTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+
+/**
+ * Test cases for {@link ProjectDAO}.
+ * 
+ * @author Izabela Adamczyk
+ */
+@Test(groups =
+    { "db", "project" })
+public class ProjectDAOTest extends AbstractDAOTest
+{
+
+    public static final String NOE = "NOE";
+
+    public static final String TESTPROJ = "TESTPROJ";
+
+    public static final String NEMO = "NEMO";
+
+    public static final String DEFAULT = "DEFAULT";
+
+    public static final String[] PRELOADED_PROJECTS =
+        { DEFAULT, NEMO, NOE, TESTPROJ };
+
+    @Test
+    public void testListProjects() throws Exception
+    {
+        final List<ProjectPE> projects = daoFactory.getProjectDAO().listProjects();
+        Collections.sort(projects);
+        for (int i = 0; i < projects.size(); i++)
+        {
+            assertEquals(PRELOADED_PROJECTS[i], projects.get(i).getCode());
+        }
+        assertEquals(4, projects.size());
+    }
+
+    @Test(dependsOnMethods = "testListProjects")
+    public void testListProjectsFromGroup() throws Exception
+    {
+        final List<ProjectPE> allProjects = daoFactory.getProjectDAO().listProjects();
+        Collections.sort(allProjects);
+        final ProjectPE defaultProject = allProjects.get(0);
+        assertEquals(DEFAULT, defaultProject.getCode());
+        final List<ProjectPE> groupProjects =
+                daoFactory.getProjectDAO().listProjects(defaultProject.getGroup());
+        assertEquals(3, groupProjects.size());
+        Collections.sort(groupProjects);
+        assertEquals(DEFAULT, groupProjects.get(0).getCode());
+        assertEquals(NEMO, groupProjects.get(1).getCode());
+        assertEquals(NOE, groupProjects.get(2).getCode());
+    }
+
+    @Test(dependsOnMethods = "testListProjects")
+    public void testListProjectsFromAnotherGroup() throws Exception
+    {
+        final List<ProjectPE> allProjects = daoFactory.getProjectDAO().listProjects();
+        Collections.sort(allProjects);
+        final ProjectPE testProject = allProjects.get(3);
+        assertEquals(testProject.getCode(), TESTPROJ);
+        final List<ProjectPE> groupProjects =
+                daoFactory.getProjectDAO().listProjects(testProject.getGroup());
+        assertEquals(1, groupProjects.size());
+        Collections.sort(groupProjects);
+        assertEquals(groupProjects.get(0).getCode(), TESTPROJ);
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/FillSampleRegistrationForm.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/FillSampleRegistrationForm.java
index 5bfce41edbf23e66dccdd06095bdf9825cbee37a..edced55c58a3ade80d48e70a919d9324a6239e18 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/FillSampleRegistrationForm.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/FillSampleRegistrationForm.java
@@ -20,7 +20,7 @@ import com.extjs.gxt.ui.client.widget.form.CheckBox;
 import com.extjs.gxt.ui.client.widget.form.TextField;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample_browser.GroupSelectionWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget;
 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;