From 6e71909773397e449f4fe5c16fbfe07b971b1513 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Wed, 13 Oct 2010 08:03:56 +0000
Subject: [PATCH] LMS-1782 PlateMetadataBrowser is now subclass of
 TypedTableGrid. GenericTableBrowserGrid and related classes deleted.
 TypeTableGrid framework improved.

SVN: 18277
---
 .../client/application/ui/TypedTableGrid.java |  28 ++-
 .../GenericTableRowColumnDefinition.java      |  84 --------
 .../ui/grid/GenericTableBrowserGrid.java      | 201 ------------------
 .../GenericTableRowColumnDefinitionUI.java    |  80 -------
 .../application/ui/report/ReportGrid.java     |   4 +-
 .../web/client/dto/GenericTableResultSet.java |  61 ------
 .../resultset/AbstractTableModelProvider.java |  48 +++++
 .../server/util/TypedTableModelBuilder.java   |   5 +
 .../basic/dto/TableModelColumnHeader.java     |  31 ---
 .../shared/basic/dto/TypedTableModel.java     |   6 +-
 .../client/application/RawDataSampleGrid.java |   5 +-
 .../web/server/RawDataSampleProvider.java     |  52 +++--
 .../basic/dto/RawDataSampleGridIDs.java       |  11 +-
 .../web/client/IScreeningClientService.java   |  13 +-
 .../client/IScreeningClientServiceAsync.java  |   9 +-
 .../detailviewers/PlateMetadataBrowser.java   | 134 +++---------
 .../detailviewers/WellSearchGrid.java         |  11 +-
 .../web/server/PlateMetadataProvider.java     |  91 +++-----
 .../web/server/ScreeningClientService.java    |  60 +-----
 ...Columns.java => PlateMetadataGridIDs.java} |  27 +--
 20 files changed, 205 insertions(+), 756 deletions(-)
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GenericTableRowColumnDefinition.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableBrowserGrid.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableRowColumnDefinitionUI.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GenericTableResultSet.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java
 rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/{PlateMetadataStaticColumns.java => PlateMetadataGridIDs.java} (65%)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
index cac13c597d2..59d6bd2beac 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
@@ -48,14 +48,19 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
 
 /**
+ * Abstract superclass of all grids based on {@link TypedTableModel}.
+ * 
  * @author Franz-Josef Elmer
  */
 public abstract class TypedTableGrid<T extends IsSerializable>
         extends
         AbstractBrowserGrid<TableModelRowWithObject<T>, BaseEntityModel<TableModelRowWithObject<T>>>
 {
+    public static final String GRID_POSTFIX = "-grid";
+
     /**
      * Do not display more than this amount of columns in the report, web browsers have problem with
      * it
@@ -96,16 +101,18 @@ public abstract class TypedTableGrid<T extends IsSerializable>
 
     private Map<String, IColumnDefinition<TableModelRowWithObject<T>>> columnDefinitions;
 
-    protected TypedTableGrid(IViewContext<ICommonClientServiceAsync> viewContext, String gridId,
+    protected TypedTableGrid(IViewContext<ICommonClientServiceAsync> viewContext, String browserId,
             boolean refreshAutomatically, IDisplayTypeIDGenerator displayTypeIDGenerator)
     {
-        super(viewContext, gridId, refreshAutomatically, displayTypeIDGenerator);
+        super(viewContext, browserId + GRID_POSTFIX, refreshAutomatically, displayTypeIDGenerator);
+        setId(browserId);
     }
 
-    protected TypedTableGrid(IViewContext<ICommonClientServiceAsync> viewContext, String gridId,
+    protected TypedTableGrid(IViewContext<ICommonClientServiceAsync> viewContext, String browserId,
             IDisplayTypeIDGenerator displayTypeIDGenerator)
     {
-        super(viewContext, gridId, displayTypeIDGenerator);
+        super(viewContext, browserId + GRID_POSTFIX, displayTypeIDGenerator);
+        setId(browserId);
     }
     
     protected void setDownloadURL(String downloadURL)
@@ -183,7 +190,7 @@ public abstract class TypedTableGrid<T extends IsSerializable>
                 String title = header.getTitle();
                 if (title == null)
                 {
-                    title = viewContext.getMessage(header.getId());
+                    title = viewContext.getMessage(translateColumnIdToDictonaryKey(header.getId()));
                 }
                 ICellListenerAndLinkGenerator<T> linkGeneratorOrNull =
                         listenerLinkGenerators.get(header.getId());
@@ -203,6 +210,17 @@ public abstract class TypedTableGrid<T extends IsSerializable>
         }
         return list;
     }
+    
+    /**
+     * Translates a column ID to a key used to get title of the column from a dictionary.
+     * This method can be overridden by subclasses.
+     * 
+     * @return <code>getId() + "_" + columnID</code>
+     */
+    protected String translateColumnIdToDictonaryKey(String columnID)
+    {
+        return getId() + "_" + columnID;
+    }
 
     @Override
     protected void listEntities(
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GenericTableRowColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GenericTableRowColumnDefinition.java
deleted file mode 100644
index 011442a7a39..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GenericTableRowColumnDefinition.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2010 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.columns.specific;
-
-import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
-import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
-import ch.systemsx.cisd.openbis.generic.shared.basic.SimpleDateRenderer;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DateTableCell;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
-
-/**
- * @author Franz-Josef Elmer
- */
-public class GenericTableRowColumnDefinition implements IColumnDefinition<TableModelRow>
-{
-    protected TableModelColumnHeader header;
-
-    private String title;
-
-    public GenericTableRowColumnDefinition(TableModelColumnHeader header, String title)
-    {
-        this.header = header;
-        this.title = title;
-    }
-
-    // GWT only
-    @SuppressWarnings("unused")
-    private GenericTableRowColumnDefinition()
-    {
-        this(null, null);
-    }
-
-    public Comparable<?> tryGetComparableValue(GridRowModel<TableModelRow> rowModel)
-    {
-        return getCellValue(rowModel);
-    }
-
-    public String getHeader()
-    {
-        return title;
-    }
-
-    public String getIdentifier()
-    {
-        return header.getId();
-    }
-
-    public String getValue(GridRowModel<TableModelRow> rowModel)
-    {
-        ISerializableComparable value = getCellValue(rowModel);
-        if (value instanceof DateTableCell)
-        {
-            return SimpleDateRenderer.renderDate(((DateTableCell) value).getDateTime());
-        }
-        return value == null ? "" : value.toString();
-    }
-
-    private ISerializableComparable getCellValue(GridRowModel<TableModelRow> rowModel)
-    {
-        return rowModel.getOriginalObject().getValues().get(header.getIndex());
-    }
-
-    public String tryToGetProperty(String key)
-    {
-        return null;
-    }
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableBrowserGrid.java
deleted file mode 100644
index e99242bd52a..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableBrowserGrid.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2010 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.grid;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-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.IViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDisplayTypeIDGenerator;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.RealNumberRenderer;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GenericTableResultSet;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
-import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
-import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
-
-/**
- * Implementation of a table browser grid for {@link TableModelRow} data.
- * 
- * @author Franz-Josef Elmer
- */
-public abstract class GenericTableBrowserGrid extends
-        AbstractBrowserGrid<TableModelRow, BaseEntityModel<TableModelRow>>
-{
-    private static final int TIMSTAMP_COLUMN_WIDTH = 190;
-
-    private static final String BROWSER_ID_PATTERN = "[a-z0-9_]*";
-
-    private List<TableModelColumnHeader> headers;
-
-    /**
-     * Creates an instane for specified view context, browserID, gridID, and display type ID
-     * generator. The browser ID is also used to create dictionary keys for message providing in
-     * according to the following schema:
-     * 
-     * <pre>
-     *    &lt;browser ID&gt;_&lt;column code&gt;
-     * </pre>
-     * 
-     * @param browserId Only lower-case letter, digits, and '_' are allowed as browser ID.
-     */
-    protected GenericTableBrowserGrid(IViewContext<ICommonClientServiceAsync> viewContext,
-            String browserId, String gridId, boolean refreshAutomatically,
-            IDisplayTypeIDGenerator displayTypeIDGenerator)
-    {
-        super(viewContext, gridId, refreshAutomatically, displayTypeIDGenerator);
-        if (browserId.matches(BROWSER_ID_PATTERN) == false)
-        {
-            throw new IllegalArgumentException("Invalid browser ID: " + browserId);
-        }
-        setId(browserId);
-    }
-
-    /**
-     * Lists table rows. Implementations of this method usually call a server method.
-     */
-    protected abstract void listTableRows(
-            IResultSetConfig<String, TableModelRow> resultSetConfig,
-            AsyncCallback<GenericTableResultSet> callback);
-
-    @Override
-    protected ColumnDefsAndConfigs<TableModelRow> createColumnsDefinition()
-    {
-        ColumnDefsAndConfigs<TableModelRow> definitions =
-                ColumnDefsAndConfigs.create(createColDefinitions());
-        if (headers != null)
-        {
-            RealNumberRenderer realNumberRenderer =
-                    new RealNumberRenderer(viewContext.getDisplaySettingsManager()
-                            .getRealNumberFormatingParameters());
-            for (TableModelColumnHeader header : headers)
-            {
-                if (header.getDataType() == DataTypeCode.REAL)
-                {
-                    definitions.setGridCellRendererFor(header.getId(), realNumberRenderer);
-                }
-            }
-        }
-        return definitions;
-    }
-
-    @Override
-    protected BaseEntityModel<TableModelRow> createModel(GridRowModel<TableModelRow> entity)
-    {
-        return new BaseEntityModel<TableModelRow>(entity, createColDefinitions());
-    }
-
-    private List<IColumnDefinitionUI<TableModelRow>> createColDefinitions()
-    {
-        List<IColumnDefinitionUI<TableModelRow>> list =
-                new ArrayList<IColumnDefinitionUI<TableModelRow>>();
-        if (headers != null)
-        {
-            for (final TableModelColumnHeader header : headers)
-            {
-                String title = header.getTitle();
-                if (title == null)
-                {
-                    title = viewContext.getMessage(getId() + "_" + header.getId());
-                }
-                GenericTableRowColumnDefinitionUI columnDef;
-                if (header.getDataType() == DataTypeCode.TIMESTAMP)
-                {
-                    columnDef =
-                            new GenericTableRowColumnDefinitionUI(header, title,
-                                    TIMSTAMP_COLUMN_WIDTH);
-                } else
-                {
-                    columnDef = new GenericTableRowColumnDefinitionUI(header, title);
-                }
-                list.add(columnDef);
-            }
-        }
-        return list;
-    }
-
-    @Override
-    protected void listEntities(DefaultResultSetConfig<String, TableModelRow> resultSetConfig,
-            final AbstractAsyncCallback<ResultSet<TableModelRow>> callback)
-    {
-        AbstractAsyncCallback<GenericTableResultSet> extendedCallback =
-                new AbstractAsyncCallback<GenericTableResultSet>(viewContext)
-                    {
-                        @Override
-                        protected void process(GenericTableResultSet result)
-                        {
-                            headers = result.getHeaders();
-                            callback.onSuccess(result.getResultSet());
-                            refreshColumnsSettingsIfNecessary();
-                        }
-
-                        @Override
-                        public void finishOnFailure(Throwable caught)
-                        {
-                            callback.finishOnFailure(caught);
-                        }
-                    };
-        listTableRows(resultSetConfig, extendedCallback);
-    }
-
-    @Override
-    protected boolean isRefreshEnabled()
-    {
-        return true;
-    }
-
-    protected void refreshColumnsSettingsIfNecessary()
-    {
-        recreateColumnModelAndRefreshColumnsWithFilters();
-    }
-
-    @Override
-    protected void refresh()
-    {
-        refresh(false);
-    }
-
-    public void update(Set<DatabaseModificationKind> observedModifications)
-    {
-        refreshGridSilently();
-    }
-
-    @Override
-    protected void showEntityViewer(TableModelRow entity, boolean editMode, boolean inBackground)
-    {
-    }
-
-    @Override
-    protected List<IColumnDefinition<TableModelRow>> getInitialFilters()
-    {
-        return Collections.emptyList();
-    }
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableRowColumnDefinitionUI.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableRowColumnDefinitionUI.java
deleted file mode 100644
index e75131e38e1..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/GenericTableRowColumnDefinitionUI.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2010 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.grid;
-
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.GenericTableRowColumnDefinition;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
-
-/**
- * UI extension of {@link GenericTableRowColumnDefinition}.
- * 
- *
- * @author Franz-Josef Elmer
- */
-public class GenericTableRowColumnDefinitionUI extends GenericTableRowColumnDefinition implements
-        IColumnDefinitionUI<TableModelRow>
-{
-    private int width;
-
-    public GenericTableRowColumnDefinitionUI(TableModelColumnHeader header, String title)
-    {
-        this(header, title, 100);
-    }
-
-    public GenericTableRowColumnDefinitionUI(TableModelColumnHeader header, String title, int width)
-    {
-        super(header, title);
-        this.width = width;
-    }
-    
-    // GWT only
-    @SuppressWarnings("unused")
-    private GenericTableRowColumnDefinitionUI()
-    {
-        this(null, null);
-    }
-
-    public int getWidth()
-    {
-        return width;
-    }
-
-    public boolean isHidden()
-    {
-        return false;
-    }
-
-    public boolean isNumeric()
-    {
-        DataTypeCode type = header.getDataType();
-        return type == DataTypeCode.INTEGER || type == DataTypeCode.REAL;
-    }
-
-    public boolean isLink()
-    {
-        return header.isLinkable();
-    }
-
-    public String tryGetLink(TableModelRow entity)
-    {
-        return null;
-    }
-    
-}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/report/ReportGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/report/ReportGrid.java
index f191347fe94..5f790aa8001 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/report/ReportGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/report/ReportGrid.java
@@ -47,8 +47,6 @@ public class ReportGrid extends TypedTableGrid<Null>
     // browser consists of the grid and the paging toolbar
     public static final String BROWSER_ID = GenericConstants.ID_PREFIX + "DataSetReporterGrid";
 
-    public static final String GRID_ID = BROWSER_ID + "_grid";
-
     public static IDisposableComponent create(
             final IViewContext<ICommonClientServiceAsync> viewContext,
             TableModelReference tableModelReference, IReportInformationProvider infoProvider)
@@ -71,7 +69,7 @@ public class ReportGrid extends TypedTableGrid<Null>
     private ReportGrid(IViewContext<ICommonClientServiceAsync> viewContext,
             TableModelReference tableModelReference, String reportKind, String downloadURL)
     {
-        super(viewContext, GRID_ID, true, DisplayTypeIDGenerator.DATA_SET_REPORTING_GRID);
+        super(viewContext, BROWSER_ID, true, DisplayTypeIDGenerator.DATA_SET_REPORTING_GRID);
         setDownloadURL(downloadURL);
         setId(BROWSER_ID);
         this.resultSetKey = tableModelReference.getResultSetKey();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GenericTableResultSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GenericTableResultSet.java
deleted file mode 100644
index 0bb7e898244..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GenericTableResultSet.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 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 java.util.List;
-
-import com.google.gwt.user.client.rpc.IsSerializable;
-
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.GenericTableRowColumnDefinition;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
-
-/**
- * Class for the {@link ResultSet} of {@link TableModelRow}. It also contains the
- * {@link GenericTableRowColumnDefinition}s.
- * 
- * @author Franz-Josef Elmer
- */
-public class GenericTableResultSet implements IsSerializable
-{
-    private ResultSet<TableModelRow> resultSet;
-    private List<TableModelColumnHeader> headers;
-
-    public GenericTableResultSet(ResultSet<TableModelRow> resultSet, List<TableModelColumnHeader> headers)
-    {
-        this.resultSet = resultSet;
-        this.headers = headers;
-    }
-    
-    // GWT only
-    @SuppressWarnings("unused")
-    private GenericTableResultSet()
-    {
-    }
-
-    public ResultSet<TableModelRow> getResultSet()
-    {
-        return resultSet;
-    }
-
-    public List<TableModelColumnHeader> getHeaders()
-    {
-        return headers;
-    }
-
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java
new file mode 100644
index 00000000000..d0cf789ea08
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010 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.server.resultset;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
+
+/**
+ * Superclass of {@link ITableModelProvider} implementations which creates the actual table model
+ * lazily.
+ *
+ * @author Franz-Josef Elmer
+ */
+public abstract class AbstractTableModelProvider<T extends IsSerializable> implements ITableModelProvider<T>
+{
+    private TypedTableModel<T> model;
+
+    public final TypedTableModel<T> getTableModel()
+    {
+        if (model == null)
+        {
+            model = createTableModel();
+        }
+        return model;
+    }
+
+    /**
+     * Creates the table model. The returned instance is always returned by {@link #getTableModel()}
+     * .
+     */
+    protected abstract TypedTableModel<T> createTableModel();
+    
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/TypedTableModelBuilder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/TypedTableModelBuilder.java
index 1ba75ec8cef..142a6015be9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/TypedTableModelBuilder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/TypedTableModelBuilder.java
@@ -184,6 +184,11 @@ public class TypedTableModelBuilder<T extends IsSerializable>
         public void addValue(ISerializableComparable valueOrNull)
         {
             int index = indexProvider.getIndex();
+            if (index < 0)
+            {
+                throw new IllegalStateException(
+                        "Row index is < 0: This is most likely caused by missing invocation of builder.addRow().");
+            }
             while (index > values.size())
             {
                 values.add(EMPTY_CELL);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java
index 0d38d0f3af6..2f98e18b163 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java
@@ -29,25 +29,6 @@ public class TableModelColumnHeader implements IsSerializable, Serializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
-    /**
-     * Creates a header without a title.
-     */
-    public static TableModelColumnHeader untitledStringHeader(int index, String id)
-    {
-        TableModelColumnHeader header = new TableModelColumnHeader(null, id, index);
-        header.setDataType(DataTypeCode.VARCHAR);
-        return header;
-    }
-
-    /**
-     * Creates a header without a title and <code>linkable</code> flag set <code>true</code>..
-     */
-    public static TableModelColumnHeader untitledLinkableStringHeader(int index, String id)
-    {
-        TableModelColumnHeader header = untitledStringHeader(index, id);
-        header.setLinkable(true);
-        return header;
-    }
     private String title;
 
     private String id;
@@ -60,8 +41,6 @@ public class TableModelColumnHeader implements IsSerializable, Serializable
     // if column values contain permIds of certain entities entity kind is stored here
     private EntityKind entityKindOrNull;
 
-    private boolean linkable;
-    
     private int defaultColumnWidth = 150;
 
     public TableModelColumnHeader()
@@ -141,16 +120,6 @@ public class TableModelColumnHeader implements IsSerializable, Serializable
         this.entityKindOrNull = entityKind;
     }
 
-    public void setLinkable(boolean linkable)
-    {
-        this.linkable = linkable;
-    }
-
-    public boolean isLinkable()
-    {
-        return linkable;
-    }
-    
     @Override
     public String toString()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TypedTableModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TypedTableModel.java
index 8ccf702279d..7610136b0d1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TypedTableModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TypedTableModel.java
@@ -20,8 +20,12 @@ import java.util.List;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.TypedTableGrid;
+
 /**
- * 
+ * Table model for {@link TypedTableGrid} classes. It contains column meta-data as a
+ * list of {@link TableModelColumnHeader} instances and the row data as a list of
+ * {@link TableModelRowWithObject} instances for row objects of type <code>T</code>.
  *
  * @author Franz-Josef Elmer
  */
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/RawDataSampleGrid.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/RawDataSampleGrid.java
index bdb907fef27..c8cba744e3e 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/RawDataSampleGrid.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/RawDataSampleGrid.java
@@ -24,6 +24,7 @@ import java.util.List;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
 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.DatabaseModificationAwareComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.TypedTableGrid;
@@ -46,7 +47,7 @@ import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.basic.dto.RawDataSampl
  */
 class RawDataSampleGrid extends TypedTableGrid<Sample>
 {
-    public static final String GRID_ID = RawDataSampleGridIDs.BROWSER_ID + "-grid";
+    public static final String BROWSER_ID = GenericConstants.ID_PREFIX + "raw_data_sample_browser";
 
     public static DatabaseModificationAwareComponent create(
             final IViewContext<IPhosphoNetXClientServiceAsync> viewContext)
@@ -60,7 +61,7 @@ class RawDataSampleGrid extends TypedTableGrid<Sample>
 
     RawDataSampleGrid(IViewContext<IPhosphoNetXClientServiceAsync> viewContext)
     {
-        super(viewContext.getCommonViewContext(), GRID_ID, true,
+        super(viewContext.getCommonViewContext(), BROWSER_ID, true,
                 PhosphoNetXDisplayTypeIDGenerator.RAW_DATA_SAMPLE_BROWSER_GRID);
         specificViewContext = viewContext;
         allowMultipleSelection();
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/server/RawDataSampleProvider.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/server/RawDataSampleProvider.java
index 2bb47a0b14e..2d9cbd2b1f4 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/server/RawDataSampleProvider.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/server/RawDataSampleProvider.java
@@ -23,7 +23,7 @@ import static ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.basic.dto.RawDa
 
 import java.util.List;
 
-import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.ITableModelProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.AbstractTableModelProvider;
 import ch.systemsx.cisd.openbis.generic.server.util.TypedTableModelBuilder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
@@ -35,49 +35,45 @@ import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.MsInjectionSample;
 /**
  * @author Franz-Josef Elmer
  */
-class RawDataSampleProvider implements ITableModelProvider<Sample>
+class RawDataSampleProvider extends AbstractTableModelProvider<Sample>
 {
     private final IProteomicsDataServiceInternal service;
 
     private final String sessionToken;
 
-    private TypedTableModel<Sample> model;
-
     RawDataSampleProvider(IProteomicsDataServiceInternal service, String sessionToken)
     {
         this.service = service;
         this.sessionToken = sessionToken;
     }
 
-    public TypedTableModel<Sample> getTableModel()
+    @Override
+    public TypedTableModel<Sample> createTableModel()
     {
-        if (model == null)
+        List<MsInjectionSample> samples = service.listRawDataSamples(sessionToken);
+        TypedTableModelBuilder<Sample> builder = new TypedTableModelBuilder<Sample>();
+        builder.addColumn(CODE).withDataType(DataTypeCode.VARCHAR);
+        builder.addColumn(REGISTRATION_DATE).withDataType(DataTypeCode.TIMESTAMP)
+                .withDefaultWidth(190);
+        builder.addColumn(PARENT).withDataType(DataTypeCode.VARCHAR);
+        builder.addColumn(EXPERIMENT).withDataType(DataTypeCode.VARCHAR);
+        for (MsInjectionSample msInjectionSample : samples)
         {
-            List<MsInjectionSample> samples = service.listRawDataSamples(sessionToken);
-            TypedTableModelBuilder<Sample> builder = new TypedTableModelBuilder<Sample>();
-            builder.addColumn(CODE).withDataType(DataTypeCode.VARCHAR);
-            builder.addColumn(REGISTRATION_DATE).withDataType(DataTypeCode.TIMESTAMP).withDefaultWidth(190);
-            builder.addColumn(PARENT).withDataType(DataTypeCode.VARCHAR);
-            builder.addColumn(EXPERIMENT).withDataType(DataTypeCode.VARCHAR);
-            for (MsInjectionSample msInjectionSample : samples)
+            Sample sample = msInjectionSample.getSample();
+            builder.addRow(sample);
+            builder.column(CODE).addString(sample.getCode());
+            builder.column(REGISTRATION_DATE).addDate(sample.getRegistrationDate());
+            Sample parent = sample.getGeneratedFrom();
+            builder.column(PARENT).addString(parent.getIdentifier());
+            Experiment experiment = parent.getExperiment();
+            if (experiment != null)
             {
-                Sample sample = msInjectionSample.getSample();
-                builder.addRow(sample);
-                builder.column(CODE).addString(sample.getCode());
-                builder.column(REGISTRATION_DATE).addDate(sample.getRegistrationDate());
-                Sample parent = sample.getGeneratedFrom();
-                builder.column(PARENT).addString(parent.getIdentifier());
-                Experiment experiment = parent.getExperiment();
-                if (experiment != null)
-                {
-                    builder.column(EXPERIMENT).addString(experiment.getIdentifier());
-                }
-                builder.columnGroup("MS").addProperties("", sample.getProperties());
-                builder.columnGroup("BIO_").addProperties(parent.getProperties());
+                builder.column(EXPERIMENT).addString(experiment.getIdentifier());
             }
-            model = builder.getModel();
+            builder.columnGroup("MS").addProperties("", sample.getProperties());
+            builder.columnGroup("BIO_").addProperties(parent.getProperties());
         }
-        return model;
+        return builder.getModel();
     }
 
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/basic/dto/RawDataSampleGridIDs.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/basic/dto/RawDataSampleGridIDs.java
index 448c219661a..2691127c3f2 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/basic/dto/RawDataSampleGridIDs.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/basic/dto/RawDataSampleGridIDs.java
@@ -16,7 +16,6 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.basic.dto;
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 
 
 /**
@@ -26,15 +25,13 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericCon
  */
 public class RawDataSampleGridIDs
 {
-    public static final String BROWSER_ID = GenericConstants.ID_PREFIX + "raw_data_sample_browser";
-
-    public static final String EXPERIMENT = BROWSER_ID + "_" + "EXPERIMENT";
+    public static final String EXPERIMENT = "EXPERIMENT";
     
-    public static final String PARENT = BROWSER_ID + "_" + "PARENT";
+    public static final String PARENT = "PARENT";
 
-    public static final String REGISTRATION_DATE = BROWSER_ID + "_" + "REGISTRATION_DATE";
+    public static final String REGISTRATION_DATE = "REGISTRATION_DATE";
 
-    public static final String CODE = BROWSER_ID + "_" + "CODE";
+    public static final String CODE = "CODE";
 
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java
index 498ac745cb1..338954c1698 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java
@@ -20,7 +20,6 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.IClientService;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientService;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GenericTableResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListMaterialDisplayCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
@@ -31,7 +30,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.LibraryRegistrationInfo;
@@ -40,6 +38,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
 
 /**
@@ -97,10 +96,10 @@ public interface IScreeningClientService extends IClientService
             throws UserFailureException;
 
     /**
-     * Returns {@link GenericTableResultSet} containing plate metadata.
+     * Returns {@link TypedTableResultSet} containing plate metadata.
      */
-    public GenericTableResultSet listPlateMetadata(
-            IResultSetConfig<String, TableModelRow> resultSetConfig, TechId sampleId)
+    public TypedTableResultSet<WellMetadata> listPlateMetadata(
+            IResultSetConfig<String, TableModelRowWithObject<WellMetadata>> resultSetConfig, TechId sampleId)
             throws UserFailureException;
 
     /**
@@ -111,9 +110,9 @@ public interface IScreeningClientService extends IClientService
 
     /**
      * Like {@link ICommonClientService#prepareExportSamples(TableExportCriteria)}, but for
-     * GenericTableRow.
+     * TypedTableResultSet.
      */
-    public String prepareExportPlateMetadata(TableExportCriteria<TableModelRow> exportCriteria)
+    public String prepareExportPlateMetadata(TableExportCriteria<TableModelRowWithObject<WellMetadata>> exportCriteria)
             throws UserFailureException;
 
     /** Lists all images for a given well in the given dataset */
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java
index e2777cb44ec..e1d46c3167b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java
@@ -21,7 +21,6 @@ import java.util.List;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.IClientServiceAsync;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GenericTableResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListMaterialDisplayCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
@@ -31,7 +30,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.LibraryRegistrationInfo;
@@ -40,6 +38,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
 
 /**
@@ -86,13 +85,13 @@ public interface IScreeningClientServiceAsync extends IClientServiceAsync
     /**
      * @see IScreeningClientService#listPlateMetadata(IResultSetConfig, TechId)
      */
-    public void listPlateMetadata(IResultSetConfig<String, TableModelRow> resultSetConfig,
-            TechId sampleId, AsyncCallback<GenericTableResultSet> callback);
+    public void listPlateMetadata(IResultSetConfig<String, TableModelRowWithObject<WellMetadata>> resultSetConfig,
+            TechId sampleId, AsyncCallback<TypedTableResultSet<WellMetadata>> callback);
 
     /**
      * @see IScreeningClientService#prepareExportPlateMetadata(TableExportCriteria)
      */
-    public void prepareExportPlateMetadata(TableExportCriteria<TableModelRow> exportCriteria,
+    public void prepareExportPlateMetadata(TableExportCriteria<TableModelRowWithObject<WellMetadata>> exportCriteria,
             AsyncCallback<String> callback);
 
     /**
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateMetadataBrowser.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateMetadataBrowser.java
index 458011990ea..c4c4862758a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateMetadataBrowser.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateMetadataBrowser.java
@@ -28,36 +28,32 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageDomain;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.GenericTableBrowserGrid;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ICellListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.TypedTableGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.LinkExtractor;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ICellListenerAndLinkGenerator;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GenericTableResultSet;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TypedTableResultSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithPermId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BasicEntityType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SerializableComparableIDDecorator;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningDisplayTypeIDGenerator;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ui.columns.specific.ScreeningLinkExtractor;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateMetadataStaticColumns;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateMetadataGridIDs;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
  * Allows to create a table containing metadata of selected plate.
  * 
  * @author Izabela Adamczyk
  */
-public class PlateMetadataBrowser extends GenericTableBrowserGrid
+public class PlateMetadataBrowser extends TypedTableGrid<WellMetadata>
 {
     public static final String BROWSER_ID = GenericConstants.ID_PREFIX + "plate_metadata_browser";
-
-    public static final String GRID_ID = BROWSER_ID + "-grid";
-
+    
     /**
      * Fetches information about the plate with the specified plate id and opens plate metadata
      * browser tab for that plate.
@@ -137,118 +133,48 @@ public class PlateMetadataBrowser extends GenericTableBrowserGrid
     private PlateMetadataBrowser(IViewContext<IScreeningClientServiceAsync> viewContext,
             TechId sampleId)
     {
-
-        super(viewContext.getCommonViewContext(), BROWSER_ID, GRID_ID, true,
+        super(viewContext.getCommonViewContext(), BROWSER_ID, true,
                 ScreeningDisplayTypeIDGenerator.PLATE_METADATA_GRID);
         this.screeningViewContext = viewContext;
         this.sampleId = sampleId;
-        registerLinkClickListeners();
-
         allowMultipleSelection();
+
+        linkWellSample();
     }
 
-    private void registerLinkClickListeners()
+    private void linkWellSample()
     {
-        registerLinkClickListenerFor(PlateMetadataStaticColumns.WELL.getColumnId(),
-                new ICellListener<TableModelRow>()
+        registerListenerAndLinkGenerator(PlateMetadataGridIDs.CODE,
+                new ICellListenerAndLinkGenerator<WellMetadata>()
                     {
-                        public void handle(TableModelRow rowItem, boolean keyPressed)
+
+                        public void handle(TableModelRowWithObject<WellMetadata> rowItem,
+                                boolean specialKeyPressed)
                         {
-                            showEntityViewer(rowItem, false, keyPressed);
+                            showEntityInformationHolderViewer(rowItem.getObjectOrNull()
+                                    .getWellSample(), false, specialKeyPressed);
+                        }
+
+                        public String tryGetLink(WellMetadata entity)
+                        {
+                            return LinkExtractor.tryExtract(entity.getWellSample());
                         }
                     });
     }
 
     @Override
-    protected void listTableRows(IResultSetConfig<String, TableModelRow> resultSetConfig,
-            AsyncCallback<GenericTableResultSet> callback)
+    protected void listTableRows(
+            DefaultResultSetConfig<String, TableModelRowWithObject<WellMetadata>> resultSetConfig,
+            AsyncCallback<TypedTableResultSet<WellMetadata>> callback)
     {
         screeningViewContext.getService().listPlateMetadata(resultSetConfig, sampleId, callback);
-
     }
 
     @Override
-    protected void prepareExportEntities(TableExportCriteria<TableModelRow> exportCriteria,
+    protected void prepareExportEntities(TableExportCriteria<TableModelRowWithObject<WellMetadata>> exportCriteria,
             AbstractAsyncCallback<String> callback)
     {
         screeningViewContext.getService().prepareExportPlateMetadata(exportCriteria, callback);
     }
 
-    public DatabaseModificationKind[] getRelevantModifications()
-    {
-        return new DatabaseModificationKind[] {};
-    }
-
-    private void showEntityInformationHolderViewer(final TableModelRow entity,
-            final PlateMetadataStaticColumns column, final String typeCode,
-            final EntityKind entityKind, boolean editMode, boolean active)
-    {
-        showEntityInformationHolderViewer(
-                createEntityInformationHolder(entity, column, typeCode, entityKind), editMode,
-                active);
-    }
-
-    @Override
-    protected void showEntityViewer(final TableModelRow entity, boolean editMode, boolean active)
-    {
-        showEntityInformationHolderViewer(entity, PlateMetadataStaticColumns.WELL, "UNDEFINED",
-                EntityKind.SAMPLE, editMode, active);
-    }
-
-    private static ISerializableComparable getColumn(final TableModelRow entity,
-            PlateMetadataStaticColumns column)
-    {
-        return entity.getValues().get(column.ordinal());
-    }
-
-    private static String getColumnAsString(TableModelRow entity,
-            PlateMetadataStaticColumns column)
-    {
-        return getColumn(entity, column).toString();
-    }
-
-    private static Long extractTechIdFromColumn(final TableModelRow entity,
-            PlateMetadataStaticColumns column)
-    {
-        return ((SerializableComparableIDDecorator) getColumn(entity, column)).getID();
-    }
-
-    private static BasicEntityType createEntityType(String typeCode)
-    {
-        return new BasicEntityType(typeCode);
-    }
-
-    private static IEntityInformationHolderWithPermId createEntityInformationHolder(
-            final TableModelRow entity, final PlateMetadataStaticColumns column,
-            final String typeCode, final EntityKind entityKind)
-    {
-        return new IEntityInformationHolderWithPermId()
-            {
-
-                public String getCode()
-                {
-                    return getColumnAsString(entity, column);
-                }
-
-                public Long getId()
-                {
-                    return extractTechIdFromColumn(entity, column);
-                }
-
-                public BasicEntityType getEntityType()
-                {
-                    return createEntityType(typeCode);
-                }
-
-                public EntityKind getEntityKind()
-                {
-                    return entityKind;
-                }
-
-                public String getPermId()
-                {
-                    return null; // TODO 2010-10-11, Piotr Buczek: needed for permlink
-                }
-            };
-    }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java
index 7114359c8d5..9ef3d0a801a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java
@@ -95,8 +95,6 @@ public class WellSearchGrid extends TypedTableGrid<WellContent>
     public static final String BROWSER_ID = GenericConstants.ID_PREFIX
             + "PlateMaterialReviewer2Grid";
 
-    public static final String GRID_ID = BROWSER_ID + "-grid";
-
     private static final String CHANNEL_CHOOSER_LABEL = "Channel:";
 
     private static final String SINGLE_EXPERIMENT_TEXT = "Single experiment";
@@ -230,12 +228,11 @@ public class WellSearchGrid extends TypedTableGrid<WellContent>
             ExperimentSearchCriteria experimentCriteriaOrNull,
             MaterialSearchCriteria materialCriteria)
     {
-        super(viewContext.getCommonViewContext(), GRID_ID, experimentCriteriaOrNull != null,
+        super(viewContext.getCommonViewContext(), BROWSER_ID, experimentCriteriaOrNull != null,
                 DisplayTypeIDGenerator.PLATE_MATERIAL_REVIEWER);
         this.viewContext = viewContext;
         this.experimentCriteriaOrNull = experimentCriteriaOrNull;
         this.materialCriteria = materialCriteria;
-        setId(BROWSER_ID);
         channelChooser = new ChannelComboBox();
         linkWellContent();
         linkExperiment();
@@ -545,6 +542,12 @@ public class WellSearchGrid extends TypedTableGrid<WellContent>
         return columnDefs;
     }
 
+    @Override
+    protected String translateColumnIdToDictonaryKey(String columnID)
+    {
+        return columnID;
+    }
+
     private void setImageRenderer(ColumnDefsAndConfigs<TableModelRowWithObject<WellContent>> schema)
     {
         GridCellRenderer<BaseEntityModel<?>> render = new GridCellRenderer<BaseEntityModel<?>>()
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java
index 89109e5ea56..468629fba1b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java
@@ -16,89 +16,56 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.server;
 
-import java.util.ArrayList;
+import static ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateMetadataGridIDs.CODE;
+import static ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateMetadataGridIDs.TYPE;
+
 import java.util.List;
 
-import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.openbis.generic.client.web.server.AbstractOriginalDataProviderWithoutHeaders;
-import ch.systemsx.cisd.openbis.generic.client.web.server.GenericColumnsHelper;
-import ch.systemsx.cisd.openbis.generic.client.web.server.GenericColumnsHelper.Column;
-import ch.systemsx.cisd.openbis.generic.client.web.server.GenericColumnsHelper.PropertyColumns;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.AbstractTableModelProvider;
+import ch.systemsx.cisd.openbis.generic.server.util.TypedTableModelBuilder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.IScreeningServer;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateMetadataStaticColumns;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
  * Original data provider for plate content.
  * 
  * @author Izabela Adamczyk
+ * @author Franz-Josef Elmer
  */
-class PlateMetadataProvider extends AbstractOriginalDataProviderWithoutHeaders<TableModelRow>
+class PlateMetadataProvider extends AbstractTableModelProvider<WellMetadata>
 {
-
-    private final List<WellMetadata> wells;
-
+    private final IScreeningServer server;
+    private final String sessionToken;
+    private final TechId plateId;
+    
     public PlateMetadataProvider(IScreeningServer server, String sessionToken, TechId plateId)
     {
-        PlateContent plateContent = server.getPlateContent(sessionToken, plateId);
-        this.wells = plateContent.getPlateMetadata().getWells();
-    }
-
-    public List<TableModelRow> getOriginalData() throws UserFailureException
-    {
-        return GenericColumnsHelper.createTableRows(getColumns());
+        this.server = server;
+        this.sessionToken = sessionToken;
+        this.plateId = plateId;
     }
 
-    public List<TableModelColumnHeader> getGenericHeaders()
+    @Override
+    public TypedTableModel<WellMetadata> createTableModel()
     {
-        List<Column> columns = getColumns();
-        List<TableModelColumnHeader> headers =
-                new ArrayList<TableModelColumnHeader>(columns.size());
-        for (Column column : columns)
+        TypedTableModelBuilder<WellMetadata> builder = new TypedTableModelBuilder<WellMetadata>();
+        PlateContent plateContent = server.getPlateContent(sessionToken, plateId);
+        List<WellMetadata> wells = plateContent.getPlateMetadata().getWells();
+        builder.addColumn(CODE);
+        builder.addColumn(TYPE);
+        for (WellMetadata wellMetadata : wells)
         {
-            headers.add(column.getHeader());
+            builder.addRow(wellMetadata);
+            Sample well = wellMetadata.getWellSample();
+            builder.column(CODE).addString(well.getCode());
+            builder.column(TYPE).addString(well.getSampleType().getCode());
+            builder.columnGroup("CONTENT_PROPERTY__").addProperties(well.getProperties());
         }
-        return headers;
+        return builder.getModel();
     }
 
-    private List<Column> getColumns()
-    {
-        List<Column> columns = new ArrayList<Column>();
-        Column codeColumn =
-                new Column(TableModelColumnHeader.untitledLinkableStringHeader(
-                        PlateMetadataStaticColumns.WELL.ordinal(),
-                        PlateMetadataStaticColumns.WELL.getColumnId()));
-        columns.add(codeColumn);
-
-        Column typeColumn =
-                new Column(TableModelColumnHeader.untitledStringHeader(
-                        PlateMetadataStaticColumns.TYPE.ordinal(),
-                        PlateMetadataStaticColumns.TYPE.getColumnId()));
-        columns.add(typeColumn);
-
-        int fixedColumns = columns.size();
-        PropertyColumns propertyColumns = new PropertyColumns();
-        for (int i = 0; i < wells.size(); i++)
-        {
-            WellMetadata metadata = wells.get(i);
-            Sample well = metadata.getWellSample();
-            codeColumn.addStringWithID(i, well.getCode(), well.getId());
-            typeColumn.addString(i, well.getSampleType().getCode());
-
-            for (IEntityProperty wellProperty : well.getProperties())
-            {
-                propertyColumns.add(i, wellProperty);
-            }
-        }
-        propertyColumns.reindexColumns(fixedColumns);
-        propertyColumns.addPrefixToColumnHeaderCodes("CONTENT_PROPERTY__");
-        columns.addAll(propertyColumns.getColumns());
-        return columns;
-    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java
index de5c502d8c3..2327537df42 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java
@@ -16,9 +16,7 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.server;
 
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -32,8 +30,6 @@ import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.common.mail.MailClientParameters;
 import ch.systemsx.cisd.common.servlet.IRequestContextProvider;
 import ch.systemsx.cisd.common.spring.IUncheckedMultipartFile;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.GenericTableRowColumnDefinition;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GenericTableResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListMaterialDisplayCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
@@ -47,13 +43,10 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.DataProvider
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.ITableModelProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.server.translator.UserFailureExceptionTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
-import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
@@ -69,6 +62,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConst
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
 
 /**
@@ -192,53 +186,19 @@ public final class ScreeningClientService extends AbstractClientService implemen
         return prepareExportEntities(criteria);
     }
 
-    public GenericTableResultSet listPlateMetadata(
-            IResultSetConfig<String, TableModelRow> criteria, TechId sampleId)
+    public TypedTableResultSet<WellMetadata> listPlateMetadata(
+            IResultSetConfig<String, TableModelRowWithObject<WellMetadata>> criteria, TechId sampleId)
     {
-        PlateMetadataProvider dataProvider =
+        PlateMetadataProvider metaDataProvider =
                 new PlateMetadataProvider(server, getSessionToken(), sampleId);
-        // This is a different kind of query because the criteria does not define which columns
-        // are available -- the provider does. Thus, inform the criteria which columns are
-        // available.
-        updateResultSetColumnsFromProvider(criteria, dataProvider);
-        ResultSet<TableModelRow> resultSet = listEntities(criteria, dataProvider);
-        return new GenericTableResultSet(resultSet, dataProvider.getGenericHeaders());
+        DataProviderAdapter<WellMetadata> dataProvider =
+                new DataProviderAdapter<WellMetadata>(metaDataProvider);
+        ResultSet<TableModelRowWithObject<WellMetadata>> resultSet =
+                listEntities(criteria, dataProvider);
+        return new TypedTableResultSet<WellMetadata>(resultSet);
     }
 
-    /**
-     * In the plate metadata query, the result set does not define which columns are available --
-     * the provider does. This method informs the result set about the columns available in the
-     * provider.
-     */
-    private void updateResultSetColumnsFromProvider(
-            IResultSetConfig<String, TableModelRow> criteria, PlateMetadataProvider dataProvider)
-    {
-        Set<IColumnDefinition<TableModelRow>> columns = criteria.getAvailableColumns();
-        Set<String> availableColumnIdentifiers = extractColumnIdentifiers(columns);
-
-        List<TableModelColumnHeader> headers = dataProvider.getGenericHeaders();
-        for (TableModelColumnHeader header : headers)
-        {
-            // the header's code is the same as the definition's identifier
-            if (!availableColumnIdentifiers.contains(header.getId()))
-            {
-                columns.add(new GenericTableRowColumnDefinition(header, header.getTitle()));
-            }
-        }
-    }
-
-    private static Set<String> extractColumnIdentifiers(
-            Set<IColumnDefinition<TableModelRow>> columns)
-    {
-        Set<String> availableColumnIdentifiers = new HashSet<String>();
-        for (IColumnDefinition<TableModelRow> colDef : columns)
-        {
-            availableColumnIdentifiers.add(colDef.getIdentifier());
-        }
-        return availableColumnIdentifiers;
-    }
-
-    public String prepareExportPlateMetadata(TableExportCriteria<TableModelRow> criteria)
+    public String prepareExportPlateMetadata(TableExportCriteria<TableModelRowWithObject<WellMetadata>> criteria)
     {
         return prepareExportEntities(criteria);
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateMetadataStaticColumns.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateMetadataGridIDs.java
similarity index 65%
rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateMetadataStaticColumns.java
rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateMetadataGridIDs.java
index 5a0182c459b..87119b5ba9c 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateMetadataStaticColumns.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateMetadataGridIDs.java
@@ -16,28 +16,13 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto;
 
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.PlateMetadataBrowser;
+
 /**
- * Defines static columns of plate metadata row.
- * 
- * @author Izabela Adamczyk
+ * Defines IDs of {@link PlateMetadataBrowser}.
  */
-public enum PlateMetadataStaticColumns
+public class PlateMetadataGridIDs
 {
-    WELL("CODE"),
-
-    TYPE("TYPE"),
-
-    THUMBNAIL("THUMBNAIL");
-
-    private final String id;
-
-    private PlateMetadataStaticColumns(String id)
-    {
-        this.id = id;
-    }
-
-    public String getColumnId()
-    {
-        return id;
-    }
+    public static final String CODE = "CODE"; 
+    public static final String TYPE = "TYPE"; 
 }
-- 
GitLab