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 33983975f21ee34e3e30546ffdb9a614fe79b395..183043033a965eec1ed00cb860fcd76af29799ac 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
@@ -795,12 +795,12 @@ public interface ICommonClientService extends IClientService
     /**
      * Lists custom grid columns available for given grid.
      */
-    public List<GridCustomColumn> listColumns(String gridId) throws UserFailureException;
+    public List<GridCustomColumn> listGridCustomColumns(String gridId) throws UserFailureException;
 
     /**
      * Returns {@link GridCustomColumn}s for given grid and display criteria.
      */
-    public ResultSet<GridCustomColumn> listColumns(String gridId,
+    public ResultSet<GridCustomColumn> listGridCustomColumns(String gridId,
             DefaultResultSetConfig<String, GridCustomColumn> resultSetConfig)
             throws UserFailureException;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index b075a2abc2b3a7d46a8d09f6a6d5d616a716c052..a9818698ff5f06f4d1b31d3a5d310ae676fbddef 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
@@ -700,14 +700,14 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     // -- custom grid columns
 
     /**
-     * @see ICommonClientService#listColumns(String)
+     * @see ICommonClientService#listGridCustomColumns(String)
      */
-    public void listColumns(String gridId, AsyncCallback<List<GridCustomColumn>> callback);
+    public void listGridCustomColumns(String gridId, AsyncCallback<List<GridCustomColumn>> callback);
 
     /**
-     * @see ICommonClientService#listColumns(String, DefaultResultSetConfig)
+     * @see ICommonClientService#listGridCustomColumns(String, DefaultResultSetConfig)
      */
-    public void listColumns(String gridId,
+    public void listGridCustomColumns(String gridId,
             DefaultResultSetConfig<String, GridCustomColumn> resultSetConfig,
             AsyncCallback<ResultSet<GridCustomColumn>> callback);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
index 47f85ce1eebad17dc9eac89517119d1869e735b6..48508326da382c32aeea59b239575110ff84eeca 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
@@ -44,6 +44,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IC
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.IDataRefreshCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -170,7 +171,7 @@ final class MatchingEntitiesPanel extends AbstractBrowserGrid<MatchingEntity, Ma
     }
 
     @Override
-    protected MatchingEntityModel createModel(MatchingEntity entity)
+    protected MatchingEntityModel createModel(GridRowModel<MatchingEntity> entity)
     {
         return new MatchingEntityModel(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
index 0405ec0afed30044bff858b5e80b97d8c9b8a50b..ee5f6ab086f5945c4e55c4ad55712b31a79f4125 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
@@ -32,6 +32,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.MultilineHTML;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnValue;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IInvalidationProvider;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractRegistrationHolder;
@@ -41,27 +43,39 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
  * The generic model which can be created automatically using the array of
  * {@link IColumnDefinitionKind} or {@link IColumnDefinition}.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  * @author Tomasz Pylak
  */
 public class BaseEntityModel<T> extends BaseModelData
 {
     private static final long serialVersionUID = 1L;
 
-    public BaseEntityModel(final T entity, IColumnDefinitionKind<T>[] staticColumnDefinitions)
+    public BaseEntityModel(final GridRowModel<T> entity,
+            IColumnDefinitionKind<T>[] staticColumnDefinitions)
     {
         this(entity, createColumnsDefinition(staticColumnDefinitions, null));
     }
 
-    public BaseEntityModel(final T entity, List<? extends IColumnDefinition<T>> columnDefinitions)
+    /** NOTE: it's assumed that columnDefinitions do not contain custom columns */
+    public BaseEntityModel(final GridRowModel<T> entity,
+            List<? extends IColumnDefinition<T>> columnDefinitions)
     {
-        set(ModelDataPropertyNames.OBJECT, entity);
+        set(ModelDataPropertyNames.OBJECT, entity.getOriginalObject());
 
         for (IColumnDefinition<T> column : columnDefinitions)
         {
             String value = renderColumnValue(entity, column);
             set(column.getIdentifier(), value);
         }
+        addCustomColumns(entity.getCalculatedColumnValues());
+    }
+
+    private void addCustomColumns(List<GridCustomColumnValue> list)
+    {
+        for (GridCustomColumnValue column : list)
+        {
+            set(column.getColumnId(), column.getValue());
+        }
     }
 
     public final T getBaseObject()
@@ -103,23 +117,27 @@ public class BaseEntityModel<T> extends BaseModelData
     }
 
     // ugly, ugly, ugly!
-    protected String renderColumnValue(final T entity, IColumnDefinition<T> column)
+    protected String renderColumnValue(final GridRowModel<T> entity, IColumnDefinition<T> column)
     {
         String value = column.getValue(entity);
         if (column instanceof CommonColumnDefinition<?>)
         {
             String headerMsgKey = ((CommonColumnDefinition<?>) column).getHeaderMsgKey();
+            T originalRecord = entity.getOriginalObject();
             if (headerMsgKey.equals(Dict.REGISTRATOR)
-                    && entity instanceof AbstractRegistrationHolder)
+                    && originalRecord instanceof AbstractRegistrationHolder)
             {
-                Person registrator = ((AbstractRegistrationHolder) entity).getRegistrator();
+                Person registrator = ((AbstractRegistrationHolder) originalRecord).getRegistrator();
                 if (registrator != null)
                 {
                     value = PersonRenderer.createPersonAnchor(registrator, value);
                 }
-            } else if (headerMsgKey.equals(Dict.CODE) && entity instanceof IInvalidationProvider)
+            } else if (headerMsgKey.equals(Dict.CODE)
+                    && originalRecord instanceof IInvalidationProvider)
             {
-                value = InvalidableWithCodeRenderer.render((IInvalidationProvider) entity, value);
+                value =
+                        InvalidableWithCodeRenderer.render((IInvalidationProvider) originalRecord,
+                                value);
             }
         }
         return value;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/EntityGridModelFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/EntityGridModelFactory.java
index 729001334f9eb4342395da249fdff0decfcf2a53..6b806665657ade9e8479b406fdd6382d167fc695 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/EntityGridModelFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/EntityGridModelFactory.java
@@ -26,6 +26,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.entity.PropertyTypesFilterUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
@@ -34,6 +36,12 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 /**
  * Factory for creating model or column definitions for grids which displays entities with
  * properties.
+ * <p>
+ * Note that we do not create {@link IColumnDefinition} for custom columns. We do not need this both
+ * in the case of row values rendering (row model has all needed information) and in case of grid
+ * header construction (custom columns definition will be constructed later when the row data will
+ * be fetched).
+ * </p>
  * 
  * @author Tomasz Pylak
  */
@@ -48,7 +56,7 @@ public class EntityGridModelFactory<T extends IEntityPropertiesHolder>
         this.staticColumnDefinitions = staticColumnDefinitions;
     }
 
-    public BaseEntityModel<T> createModel(T entity)
+    public BaseEntityModel<T> createModel(GridRowModel<T> entity)
     {
         List<IColumnDefinitionUI<T>> allColumnsDefinition =
                 new EntityGridModelFactory<T>(staticColumnDefinitions)
@@ -60,11 +68,10 @@ public class EntityGridModelFactory<T extends IEntityPropertiesHolder>
      * here we create the columns definition having just one table row. We need them only to render
      * column values (headers have been already created), so no message provider is needed.
      */
-    public List<IColumnDefinitionUI<T>> createColumnsSchemaForRendering(
-            IEntityPropertiesHolder entity)
+    public List<IColumnDefinitionUI<T>> createColumnsSchemaForRendering(GridRowModel<T> rowModel)
     {
         List<IColumnDefinitionUI<T>> list = createStaticColumnDefinitions(null);
-        for (IEntityProperty prop : entity.getProperties())
+        for (IEntityProperty prop : rowModel.getOriginalObject().getProperties())
         {
             PropertyType propertyType = prop.getPropertyType();
             EntityPropertyColDef<T> colDef = new EntityPropertyColDef<T>(propertyType, true, null);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/MatchingEntityModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/MatchingEntityModel.java
index 4bb2fa6ff734210bba6125b3b565a9a3400fb4d9..7856ad11b56941c2bc0e3d016e6960af55ab54f8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/MatchingEntityModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/MatchingEntityModel.java
@@ -22,6 +22,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.PersonRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 
 /**
@@ -33,13 +34,14 @@ public final class MatchingEntityModel extends BaseEntityModel<MatchingEntity>
 {
     private static final long serialVersionUID = 1L;
 
-    public MatchingEntityModel(final MatchingEntity entity)
+    public MatchingEntityModel(final GridRowModel<MatchingEntity> entity)
     {
         super(entity, getStaticColumnsDefinition());
 
         // override registrator column adding a link
-        set(MatchingEntityColumnKind.REGISTRATOR.id(), PersonRenderer.createPersonAnchor(entity
-                .getRegistrator()));
+        String person =
+                PersonRenderer.createPersonAnchor(entity.getOriginalObject().getRegistrator());
+        set(MatchingEntityColumnKind.REGISTRATOR.id(), person);
     }
 
     public static IColumnDefinitionKind<MatchingEntity>[] getStaticColumnsDefinition()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/PropertyTypeModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/PropertyTypeModel.java
index 08874a8f3ca51649f2b9d9a108ad939fa25153a0..4ab5cf80b376db5b72cafee68dcddb9f45a6ed99 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/PropertyTypeModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/PropertyTypeModel.java
@@ -22,6 +22,7 @@ import com.google.gwt.user.client.Element;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.PropertyTypeColDefKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 
 /**
@@ -34,7 +35,8 @@ public class PropertyTypeModel extends BaseEntityModel<PropertyType>
 {
     private static final long serialVersionUID = 1L;
 
-    public PropertyTypeModel(PropertyType entity, IColumnDefinitionKind<PropertyType>[] colDefKinds)
+    public PropertyTypeModel(GridRowModel<PropertyType> entity,
+            IColumnDefinitionKind<PropertyType>[] colDefKinds)
     {
         super(entity, colDefKinds);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SampleModelFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SampleModelFactory.java
index 21122510eda3896e78bb05978192884fa2c7df26..5e6223c9424af2a4fd8cb4b4bf403a0f8c014388 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SampleModelFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SampleModelFactory.java
@@ -29,6 +29,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.sample.ParentGeneratedFromSampleColDef;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
@@ -51,11 +52,12 @@ public final class SampleModelFactory
                 parentColumnsSchema);
     }
 
-    public static BaseEntityModel<Sample> createModel(Sample entity)
+    public static BaseEntityModel<Sample> createModel(GridRowModel<Sample> sampleModel)
     {
-        List<IColumnDefinitionUI<Sample>> allColumnsDefinition =
-                new SampleModelFactory().createColumnsSchemaForRendering(entity);
-        BaseEntityModel<Sample> model = new BaseEntityModel<Sample>(entity, allColumnsDefinition);
+        List<? extends IColumnDefinitionUI<Sample>> allColumnsDefinition =
+                new SampleModelFactory().createColumnsSchemaForRendering(sampleModel);
+        BaseEntityModel<Sample> model =
+                new BaseEntityModel<Sample>(sampleModel, allColumnsDefinition);
         return model;
     }
 
@@ -67,18 +69,20 @@ public final class SampleModelFactory
                 new EntityGridModelFactory<Sample>(CommonSampleColDefKind.values());
     }
 
-    private List<IColumnDefinitionUI<Sample>> createColumnsSchemaForRendering(Sample sample)
+    private List<IColumnDefinitionUI<Sample>> createColumnsSchemaForRendering(
+            GridRowModel<Sample> sampleModel)
     {
         List<IColumnDefinitionUI<Sample>> columns =
-                entityGridModelFactory.createColumnsSchemaForRendering(sample);
+                entityGridModelFactory.createColumnsSchemaForRendering(sampleModel);
         List<AbstractParentSampleColDef> parentColumns =
-                createParentColumnsSchema(null, sample.getSampleType());
+                createParentColumnsSchema(null, sampleModel.getOriginalObject().getSampleType());
         columns.addAll(parentColumns);
         return columns;
     }
 
     private ColumnDefsAndConfigs<Sample> doCreateColumnsSchema(IMessageProvider messageProvider,
-            List<PropertyType> propertyTypes, List<AbstractParentSampleColDef> parentColumnsSchema)
+            List<PropertyType> propertyTypes,
+            List<? extends IColumnDefinitionUI<Sample>> parentColumnsSchema)
     {
         assert messageProvider != null : "message provider needed to create table headers";
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/AbstractPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/AbstractPropertyColRenderer.java
index a53ed5ed7cc2f30147e4b7f3e2b3846c8118b789..895258bb0e9508771b890e685eed407fe3a491c8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/AbstractPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/AbstractPropertyColRenderer.java
@@ -18,13 +18,14 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ren
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.EntityPropertyColDef;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 
 /**
  * An abstract decorator for {@link EntityPropertyColDef} to be used in grids for rendering values
  * in a different way in grids than in export. <br>
- * It changes {@link EntityPropertyColDef#getValue(Object)} behavior distinguishing certain property
+ * It changes {@link EntityPropertyColDef#getValue(GridRowModel)} behavior distinguishing certain property
  * types so in grid there can be e.g. a link displayed for hyperlink property. Other methods are
  * delegated without any change.
  * 
@@ -63,12 +64,12 @@ public abstract class AbstractPropertyColRenderer<T extends IEntityPropertiesHol
         this.colDef = colDef;
     }
 
-    public String getValue(T entity)
+    public String getValue(GridRowModel<T> entity)
     {
         return renderValue(entity);
     }
 
-    public Comparable<?> getComparableValue(T rowModel)
+    public Comparable<?> getComparableValue(GridRowModel<T> rowModel)
     {
         return colDef.getComparableValue(rowModel);
     }
@@ -76,7 +77,7 @@ public abstract class AbstractPropertyColRenderer<T extends IEntityPropertiesHol
     /**
      * @return given <var>value</var> rendered depending on property type
      */
-    protected abstract String renderValue(T entity);
+    protected abstract String renderValue(GridRowModel<T> entity);
 
     // default delegate methods
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/DefaultPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/DefaultPropertyColRenderer.java
index 4b47f1088b24920dc01ad15d2d08bf03b0f6b331..6a0b6b3ac0691555f5a0d0acde73309e39c5fd5c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/DefaultPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/DefaultPropertyColRenderer.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.EntityPropertyColDef;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 
 /**
@@ -34,7 +35,7 @@ class DefaultPropertyColRenderer<T extends IEntityPropertiesHolder> extends
     }
 
     @Override
-    protected String renderValue(T entity)
+    protected String renderValue(GridRowModel<T> entity)
     {
         return colDef.getValue(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/HyperlinkPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/HyperlinkPropertyColRenderer.java
index dfe0ad071a17a6016a81e1bb409dae0ac82c9ce1..26e0947ad0a014e0a43d62ecb2464be309165076 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/HyperlinkPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/HyperlinkPropertyColRenderer.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ren
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.EntityPropertyColDef;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ExternalHyperlink;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 
 /**
@@ -35,7 +36,7 @@ class HyperlinkPropertyColRenderer<T extends IEntityPropertiesHolder> extends
     }
 
     @Override
-    protected String renderValue(T entity)
+    protected String renderValue(GridRowModel<T> entity)
     {
         String value = colDef.getValue(entity);
         return ExternalHyperlink.createAnchorString(value, value);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/MultilineVarcharPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/MultilineVarcharPropertyColRenderer.java
index 8ba7cbcb4dc4d18259dae30637990a27a824f398..6ca54d009e2972adadb2dbf2f0c143c95af8efbf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/MultilineVarcharPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/MultilineVarcharPropertyColRenderer.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ren
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.EntityPropertyColDef;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.MultilineHTML;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 
 /**
@@ -35,7 +36,7 @@ class MultilineVarcharPropertyColRenderer<T extends IEntityPropertiesHolder> ext
     }
 
     @Override
-    protected String renderValue(T entity)
+    protected String renderValue(GridRowModel<T> entity)
     {
         String value = colDef.getValue(entity);
         return (new MultilineHTML(value)).toString();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/TimestampPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/TimestampPropertyColRenderer.java
index 5f8ebac15e27c734b9a1e88a09e7235d42ee1173..b27b9cf0b0fbaebc27ca58e24e6e89f58d920d2d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/TimestampPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/TimestampPropertyColRenderer.java
@@ -20,6 +20,7 @@ import java.util.Date;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.DateRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.EntityPropertyColDef;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 
@@ -40,7 +41,7 @@ class TimestampPropertyColRenderer<T extends IEntityPropertiesHolder> extends
     }
 
     @Override
-    protected String renderValue(T entity)
+    protected String renderValue(GridRowModel<T> entity)
     {
         String value = colDef.getValue(entity);
         if (value == null)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java
index 3d29697149df3628657c76359ea5a2918b39c164..9003c83f4d189a1fab4c845a1b07f96f61d24d1d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ren
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.EntityPropertyColDef;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ExternalHyperlink;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.MultilineHTML;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -37,9 +38,9 @@ public class VocabularyPropertyColRenderer<T extends IEntityPropertiesHolder> ex
     }
 
     @Override
-    protected String renderValue(T entity)
+    protected String renderValue(GridRowModel<T> entity)
     {
-        final IEntityProperty property = colDef.tryGetProperty(entity);
+        final IEntityProperty property = colDef.tryGetProperty(entity.getOriginalObject());
         String result = "";
         if (property != null)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnConfigFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnConfigFactory.java
index 5faa9393bb5122e88ed8cdbfd9fe11b3753a17b5..95e3a1164a105e0d22d802aad80877cc7aadb201 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnConfigFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnConfigFactory.java
@@ -42,18 +42,12 @@ public final class ColumnConfigFactory
         return createRegistratorColumnConfig(messageProvider, ModelDataPropertyNames.REGISTRATOR);
     }
 
-    public final static ColumnConfig createRegistratorColumnConfig(
+    private final static ColumnConfig createRegistratorColumnConfig(
             final IMessageProvider messageProvider, String id)
     {
         return createDefaultColumnConfig(messageProvider.getMessage(Dict.REGISTRATOR), id);
     }
 
-    public final static ColumnConfig createCodeColumnConfig(final IMessageProvider messageProvider,
-            String id)
-    {
-        return createDefaultColumnConfig(messageProvider.getMessage(Dict.CODE), id);
-    }
-
     public final static ColumnConfig createRegistrationDateColumnConfig(
             final IMessageProvider messageProvider)
     {
@@ -61,7 +55,7 @@ public final class ColumnConfigFactory
                 ModelDataPropertyNames.REGISTRATION_DATE);
     }
 
-    public final static ColumnConfig createRegistrationDateColumnConfig(
+    private final static ColumnConfig createRegistrationDateColumnConfig(
             final IMessageProvider messageProvider, String id)
     {
         final ColumnConfig registrationDateColumnConfig =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
index 87a37dbab4f8d3712a3dbabdf4e9423a8c77467b..8b0baee3c7ffa3f1bbe4d775223d209cf1b54e82 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
@@ -115,7 +115,7 @@ public class GroupSelectionWidget extends DropDownList<GroupModel, Group>
             {
                 groupStore.add(new GroupModel(createSharedGroup()));
             }
-            groupStore.add(convertItems(result.getList()));
+            groupStore.add(convertItems(result.getList().extractOriginalObjects()));
             if (groupStore.getCount() > 0)
             {
                 setEmptyText(viewContext.getMessage(Dict.COMBO_BOX_CHOOSE, CHOOSE_SUFFIX));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java
index 0871a0712eff28d1ffadcccb338f7afebe3df7bf..fa8608cb527b0c01f5e6594697a3f143b84cb345 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java
@@ -69,6 +69,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.Windo
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.AttachmentVersions;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IAttachmentHolder;
@@ -315,7 +316,8 @@ public class AttachmentBrowser extends AbstractSimpleBrowserGrid<AttachmentVersi
     }
 
     @Override
-    protected BaseEntityModel<AttachmentVersions> createModel(AttachmentVersions entity)
+    protected BaseEntityModel<AttachmentVersions> createModel(
+            GridRowModel<AttachmentVersions> entity)
     {
         BaseEntityModel<AttachmentVersions> model = super.createModel(entity);
         model.renderAsLinkWithAnchor(AttachmentColDefKind.FILE_NAME.id());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java
index a9b87329517d9865be7812e959c63f1c6c1abdde..b6d118b427aac1be1fa3b3dbe8af6ea347bcb345 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+
 /**
  * @author Tomasz Pylak
  */
@@ -61,13 +63,13 @@ public abstract class AbstractColumnDefinition<T> implements IColumnDefinitionUI
         return headerText;
     }
 
-    public String getValue(T entity)
+    public String getValue(GridRowModel<T> entity)
     {
-        String value = tryGetValue(entity);
+        String value = tryGetValue(entity.getOriginalObject());
         return value != null ? value : "";
     }
 
-    public Comparable<?> getComparableValue(T rowModel)
+    public Comparable<?> getComparableValue(GridRowModel<T> rowModel)
     {
         return getValue(rowModel);
     }
@@ -82,5 +84,4 @@ public abstract class AbstractColumnDefinition<T> implements IColumnDefinitionUI
         return null;
     }
 
-    
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinitionKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinitionKind.java
index 035b137da68ea4fa10dae887496ea94aa486c7af..bb0c58975f48bbf86ffc4fa702e39972a3466f6a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinitionKind.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinitionKind.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.column
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.renderers.SimpleDateRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.renderers.SimplePersonRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.renderers.SimpleYesNoRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IInvalidationProvider;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractRegistrationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
@@ -32,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
  * are similar, but cannot extend a class directly (they are enums, not classes).
  * </p>
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public abstract class AbstractColumnDefinitionKind<T>
 {
@@ -90,9 +91,9 @@ public abstract class AbstractColumnDefinitionKind<T>
         return headerMsgKey;
     }
 
-    public Comparable<?> getComparableValue(T entity)
+    public Comparable<?> getComparableValue(GridRowModel<T> entity)
     {
-        String value = tryGetValue(entity);
+        String value = tryGetValue(entity.getOriginalObject());
         return value == null ? "" : value;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/CommonColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/CommonColumnDefinition.java
index 5255ce2c60b808bdce4d8f158328e35d8e5e89e3..8e0e6cf7df53144d147fe9462acbe36c2caff7e7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/CommonColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/CommonColumnDefinition.java
@@ -16,12 +16,14 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+
 /**
  * Definition of table columns for entities of type <code>T</code> together with the instructions to
  * render each column value.
  * 
  * @author Tomasz Pylak
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public class CommonColumnDefinition<T> extends AbstractColumnDefinition<T>
 {
@@ -58,7 +60,7 @@ public class CommonColumnDefinition<T> extends AbstractColumnDefinition<T>
     }
 
     @Override
-    public Comparable<?> getComparableValue(T rowModel)
+    public Comparable<?> getComparableValue(GridRowModel<T> rowModel)
     {
         return columnDefinitionKind.getDescriptor().getComparableValue(rowModel);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/EntityPropertyColDef.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/EntityPropertyColDef.java
index 3996522528d4c8eec8dd70be8f4891b1d67da8b5..07412f80e00b81e003ab635a85003603fcd1c66f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/EntityPropertyColDef.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/EntityPropertyColDef.java
@@ -21,6 +21,7 @@ import java.util.List;
 import com.google.gwt.user.client.rpc.IsSerializable;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.PropertyTypeRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
@@ -111,9 +112,9 @@ public class EntityPropertyColDef<T extends IEntityPropertiesHolder> extends
     }
 
     @Override
-    public Comparable<?> getComparableValue(T rowModel)
+    public Comparable<?> getComparableValue(GridRowModel<T> rowModel)
     {
-        String valueAsString = tryGetValue(rowModel);
+        String valueAsString = tryGetValue(rowModel.getOriginalObject());
         DataTypeCode dataType = propertyType.getDataType().getCode();
         switch (dataType)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
new file mode 100644
index 0000000000000000000000000000000000000000..918b278ef9996cdea522e6afa20f579c3639e921
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+
+/**
+ * Column definition for a grid custom column.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridCustomColumnDefinition<T> implements IColumnDefinitionUI<T>
+{
+    private GridCustomColumnInfo columnMetadata;
+
+    public GridCustomColumnDefinition(GridCustomColumnInfo columnMetadata)
+    {
+        this.columnMetadata = columnMetadata;
+    }
+
+    public int getWidth()
+    {
+        return AbstractColumnDefinitionKind.DEFAULT_COLUMN_WIDTH;
+    }
+
+    public boolean isHidden()
+    {
+        return false;
+    }
+
+    public boolean isNumeric()
+    {
+        return false;
+    }
+
+    public Comparable<?> getComparableValue(GridRowModel<T> rowModel)
+    {
+        return getValue(rowModel);
+    }
+
+    public String getValue(GridRowModel<T> rowModel)
+    {
+        String columnId = columnMetadata.getCode();
+        return rowModel.findColumnValue(columnId);
+    }
+
+    public String getHeader()
+    {
+        return columnMetadata.getLabel();
+    }
+
+    public String getIdentifier()
+    {
+        return columnMetadata.getCode();
+    }
+
+    public String tryToGetProperty(String key)
+    {
+        return null;
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private GridCustomColumnDefinition()
+    {
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private GridCustomColumnInfo getColumnMetadata()
+    {
+        return columnMetadata;
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private void setColumnMetadata(GridCustomColumnInfo columnMetadata)
+    {
+        this.columnMetadata = columnMetadata;
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/data/DataSetReportColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/data/DataSetReportColumnDefinition.java
index 82c13935c7af9e2936e11ec55bd5973d2be59149..3762ef2931c01f9ee87229a7962160a147865555 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/data/DataSetReportColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/data/DataSetReportColumnDefinition.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.data;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel.TableModelColumnHeader;
@@ -36,7 +37,7 @@ public class DataSetReportColumnDefinition implements IColumnDefinition<TableMod
         this.columnHeader = columnHeader;
     }
 
-    public Comparable<?> getComparableValue(TableModelRow rowModel)
+    public Comparable<?> getComparableValue(GridRowModel<TableModelRow> rowModel)
     {
         TableModelColumnType type = columnHeader.getType();
         String value = getValue(rowModel);
@@ -74,12 +75,12 @@ public class DataSetReportColumnDefinition implements IColumnDefinition<TableMod
         return "colIndex_" + columnHeader.getIndex();
     }
 
-    public String getValue(TableModelRow rowModel)
+    public String getValue(GridRowModel<TableModelRow> rowModel)
     {
         int index = columnHeader.getIndex();
-        return rowModel.getValues().get(index);
+        return rowModel.getOriginalObject().getValues().get(index);
     }
-    
+
     public String tryToGetProperty(String key)
     {
         return null;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java
index 0c30d36456584d1efcd0d6ea316e23f55608c229..7d424a1b06ae1a647000fa0f1d9541732952054f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java
@@ -53,6 +53,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.DataS
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedActionWithResult;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedDatasetCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -316,7 +317,7 @@ public abstract class AbstractExternalDataGrid
     }
 
     @Override
-    protected BaseEntityModel<ExternalData> createModel(ExternalData entity)
+    protected BaseEntityModel<ExternalData> createModel(GridRowModel<ExternalData> entity)
     {
         return getColumnsFactory().createModel(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java
index b44aad0e4565762bc48d3cd858eb6591a1df8f39..56835fc344d761dd3517848b8b8f418062d434fb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java
@@ -34,6 +34,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Ab
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableModelReference;
@@ -151,7 +152,7 @@ public class DataSetReporterGrid extends
     }
 
     @Override
-    protected BaseEntityModel<TableModelRow> createModel(TableModelRow entity)
+    protected BaseEntityModel<TableModelRow> createModel(GridRowModel<TableModelRow> entity)
     {
         return new BaseEntityModel<TableModelRow>(entity, createColumnDefinitions(tableHeader));
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitModel.java
index c65aaa1f3b9c9138f9e1cd96fdb97526dba5ea6f..4a273f17bb23ef60d55cc97e0f66e6154ac2390d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitModel.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.entity.PropertyTypesFilterUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
@@ -40,21 +41,22 @@ public class DataSetSearchHitModel extends BaseEntityModel<ExternalData>
 
     private static final int PROPERTY_COLUMN_WIDTH = 150;
 
-    public DataSetSearchHitModel(final ExternalData entity)
+    public DataSetSearchHitModel(final GridRowModel<ExternalData> entity)
     {
         super(entity, createColumnsSchema(entity));
     }
 
     // here we create the columns definition having just one table row. We need them only to render
     // column values (headers have been already created), so no message provider is needed.
-    private static List<IColumnDefinitionUI<ExternalData>> createColumnsSchema(ExternalData entity)
+    private static List<IColumnDefinitionUI<ExternalData>> createColumnsSchema(
+            GridRowModel<ExternalData> entity)
     {
         List<IColumnDefinitionUI<ExternalData>> list = createCommonColumnsSchema(null);
 
-        List<PropertyType> datasetProperties =
-                extractPropertyTypes(DataSetPropertyColDef.getDataSetProperties(entity));
+        List<IEntityProperty> properties =
+                DataSetPropertyColDef.getDataSetProperties(entity.getOriginalObject());
+        List<PropertyType> datasetProperties = extractPropertyTypes(properties);
         list.addAll(createDatasetPropertyTypeColDefs(datasetProperties));
-
         return list;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/RelatedDataSetGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/RelatedDataSetGrid.java
index 87d83dd25be9ab7c0170e392eebc469048cf42ac..d4974e83cdfa0c72268f273cec9715f3bc636a79 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/RelatedDataSetGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/RelatedDataSetGrid.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RelatedDataSetCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
@@ -80,7 +81,7 @@ public class RelatedDataSetGrid extends AbstractExternalDataGrid
     }
 
     @Override
-    protected DataSetSearchHitModel createModel(ExternalData entity)
+    protected DataSetSearchHitModel createModel(GridRowModel<ExternalData> entity)
     {
         return new DataSetSearchHitModel(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
index 5e151b739cca3606132317c5200fdd652ed7c6e4..b1fdc5098693dd1c8d6ed9bba202c8b9c8308571 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
@@ -50,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IB
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedActionWithResult;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedIdHolderCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -213,7 +214,7 @@ public class ExperimentBrowserGrid extends
     }
 
     @Override
-    protected BaseEntityModel<Experiment> createModel(Experiment entity)
+    protected BaseEntityModel<Experiment> createModel(GridRowModel<Experiment> entity)
     {
         return getColumnsFactory().createModel(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionTreeWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionTreeWidget.java
index ae5e0e9dcc27c67aab2c8272beb8367ff2a89c0e..e91ef60186651a103fcef722c6086ee2cc689286 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionTreeWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionTreeWidget.java
@@ -214,7 +214,7 @@ public final class ProjectSelectionTreeWidget extends Tree implements IDatabaseM
         @Override
         protected void process(final ResultSet<Project> result)
         {
-            List<Project> projects = result.getList();
+            List<Project> projects = result.getList().extractOriginalObjects();
             rebuildTree(projects);
 
             if (selectedProjectOrNull != null)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java
index 5546cf7d8b28eb1d15fa5e2f099d526ab61bc438..6af60829450f721ce8fc5f34b0f3a137b11a1a00 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java
@@ -128,7 +128,7 @@ public final class ProjectSelectionWidget extends
         {
             final ListStore<ProjectComboModel> projectStore = getStore();
             projectStore.removeAll();
-            projectStore.add(convertItems(result.getList()));
+            projectStore.add(convertItems(result.getList().extractOriginalObjects()));
             if (projectStore.getCount() > 0)
             {
                 setEmptyText(viewContext.getMessage(Dict.COMBO_BOX_CHOOSE, CHOOSE_SUFFIX));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java
index 4c38d643270df9486594eef37a53c760f3c347ff..1eaa5c5c678d69bad2ac6bd3fd4b83c48c504a44 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java
@@ -81,15 +81,20 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Base
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.InternalLinkCellRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.MultilineStringCellRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.BorderLayoutDataFactory;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
+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.GridCustomColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.expressions.filter.FilterToolbar;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.IDataRefreshCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IResultUpdater;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.WindowUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RelatedDataSetCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -118,7 +123,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
             AbstractAsyncCallback<ResultSet<T>> callback);
 
     /** Converts specified entity into a grid row model */
-    abstract protected M createModel(T entity);
+    abstract protected M createModel(GridRowModel<T> entity);
 
     /**
      * Called when user wants to export the data. It can happen only after a previous refresh of the
@@ -190,6 +195,8 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
     // available columns definitions
     private Set<IColumnDefinition<T>> columnDefinitions;
 
+    private CustomColumnsMetadataProvider customColumnsMetadataProvider;
+
     // result set key of the last refreshed data
     private String resultSetKey;
 
@@ -221,6 +228,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
         this.viewContext = viewContext;
         this.refreshAutomatically = refreshAutomatically;
         this.pagingLoader = createPagingLoader();
+        this.customColumnsMetadataProvider = new CustomColumnsMetadataProvider();
 
         this.grid = createGrid(pagingLoader, gridId);
         this.pagingToolbar =
@@ -490,7 +498,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
                     List<GridFilterInfo<T>> appliedFilters = getAppliedFilters();
                     DefaultResultSetConfig<String, T> resultSetConfig =
                             createPagingConfig(loadConfig, columnDefinitions, appliedFilters,
-                                    resultSetKey, getCustomFilter());
+                                    resultSetKey, tryGetCustomFilter(), getGridDisplayTypeID());
                     ListEntitiesCallback listCallback =
                             new ListEntitiesCallback(viewContext, callback, resultSetConfig);
                     listEntities(resultSetConfig, listCallback);
@@ -498,7 +506,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
             };
     }
 
-    protected CustomFilterInfo<T> getCustomFilter()
+    private CustomFilterInfo<T> tryGetCustomFilter()
     {
         return filterToolbar.tryGetCustomFilter();
     }
@@ -543,7 +551,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
     private static <T> DefaultResultSetConfig<String, T> createPagingConfig(
             PagingLoadConfig loadConfig, Set<IColumnDefinition<T>> availableColumns,
             List<GridFilterInfo<T>> appliedFilters, String resultSetKey,
-            CustomFilterInfo<T> customFilterInfo)
+            CustomFilterInfo<T> customFilterInfo, String gridDisplayId)
     {
         int limit = loadConfig.getLimit();
         int offset = loadConfig.getOffset();
@@ -558,6 +566,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
         resultSetConfig.setFilterInfos(appliedFilters);
         resultSetConfig.setResultSetKey(resultSetKey);
         resultSetConfig.setCustomFilterInfo(customFilterInfo);
+        resultSetConfig.setGridDisplayId(gridDisplayId);
         return resultSetConfig;
     }
 
@@ -645,6 +654,9 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
             // key
             saveCacheKey(result.getResultSetKey());
             totalCount = result.getTotalLength();
+            List<GridCustomColumnInfo> customColumnMetadata =
+                    result.getList().getCustomColumnsMetadata();
+            customColumnsMetadataProvider.setCustomColumnsMetadata(customColumnMetadata);
             // convert the result to the model data for the grid control
             final List<M> models = createModels(result.getList());
             final PagingLoadResult<M> loadResult =
@@ -670,12 +682,13 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
         }
     }
 
-    private List<M> createModels(final List<T> entities)
+    private List<M> createModels(final GridRowModels<T> gridRowModels)
     {
         final List<M> result = new ArrayList<M>();
-        for (final T entity : entities)
+        for (final GridRowModel<T> entity : gridRowModels)
         {
-            result.add(createModel(entity));
+            M model = createModel(entity);
+            result.add(model);
         }
         return result;
     }
@@ -946,12 +959,34 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
     protected final void recreateColumnModelAndRefreshColumnsWithFilters()
     {
         ColumnDefsAndConfigs<T> defsAndConfigs = createColumnsDefinition();
+        // add custom columns
+        List<IColumnDefinitionUI<T>> customColumnsDefs =
+                createCustomColumnDefinitions(customColumnsMetadataProvider
+                        .tryGetCustomColumnsMetadata());
+        defsAndConfigs.addColumns(customColumnsDefs);
+
         this.columnDefinitions = defsAndConfigs.getColumnDefs();
         ColumnModel columnModel = createColumnModel(defsAndConfigs.getColumnConfigs());
 
         refreshColumnsAndFilters(columnModel);
     }
 
+    private static <T> List<IColumnDefinitionUI<T>> createCustomColumnDefinitions(
+            List<GridCustomColumnInfo> customColumnsMetadataOrNull)
+    {
+        List<IColumnDefinitionUI<T>> defs = new ArrayList<IColumnDefinitionUI<T>>();
+        if (customColumnsMetadataOrNull == null)
+        {
+            return defs;
+        }
+        for (GridCustomColumnInfo columnMetadata : customColumnsMetadataOrNull)
+        {
+            IColumnDefinitionUI<T> colDef = new GridCustomColumnDefinition<T>(columnMetadata);
+            defs.add(colDef);
+        }
+        return defs;
+    }
+
     private void refreshColumnsAndFiltersWithCurrentModel()
     {
         refreshColumnsAndFilters(getColumnModel());
@@ -1107,6 +1142,11 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
             {
                 public void postRefresh(boolean wasSuccessful)
                 {
+                    if (customColumnsMetadataProvider.getUnsettingHasChanged())
+                    {
+                        recreateColumnModelAndRefreshColumnsWithFilters();
+                    }
+
                     updateDefaultRefreshButton();
                     if (wasSuccessful)
                     {
@@ -1189,27 +1229,52 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
     {
         assert grid != null && grid.getColumnModel() != null : "Grid must be loaded";
 
-        IResultUpdater<List<ColumnDataModel>> updater = new IResultUpdater<List<ColumnDataModel>>()
-            {
-                public void update(List<ColumnDataModel> result)
-                {
-                    boolean filtersChanged = rebuildFiltersFromIds(getFilteredColumnIds(result));
-                    // refresh the data - some filters may have been removed
-                    if (filtersChanged)
-                    {
-                        createApplyFiltersDelagator().execute();
-                    }
-                    updateColumnsSettingsModel(getColumnModel(), result);
-                    // settings will be automatically stored because of event handling
-                    refreshColumnsSettings();
-                    refreshColumnHeaderWidths();
-                    filterToolbar.refresh();
-                }
-            };
         List<ColumnDataModel> settingsModel =
                 createColumnsSettingsModel(getColumnModel(),
                         extractFilteredColumnIds(filterWidgets));
-        ColumnSettingsDialog.show(viewContext, settingsModel, updater, getGridDisplayTypeID());
+        AbstractColumnSettingsDataModelProvider provider =
+                new AbstractColumnSettingsDataModelProvider(settingsModel)
+                    {
+                        @Override
+                        public void onClose(List<ColumnDataModel> newColumnDataModels)
+                        {
+                            updateColumnsSettingsModel(getColumnModel(), newColumnDataModels);
+
+                            // refresh the whole grid if custom columns changed
+                            List<GridCustomColumnInfo> newCustomColumns = tryGetCustomColumnsInfo();
+                            if (newCustomColumns != null)
+                            {
+                                customColumnsMetadataProvider
+                                        .setCustomColumnsMetadata(newCustomColumns);
+                            }
+                            boolean customColumnsChanged =
+                                    customColumnsMetadataProvider.getUnsettingHasChanged();
+                            if (customColumnsChanged)
+                            {
+                                recreateColumnModelAndRefreshColumnsWithFilters();
+                            }
+
+                            boolean filtersChanged =
+                                    rebuildFiltersFromIds(getFilteredColumnIds(newColumnDataModels));
+                            // refresh the data - some filters may have been removed
+                            if (filtersChanged)
+                            {
+                                createApplyFiltersDelagator().execute();
+                            }
+
+                            if (customColumnsChanged)
+                            {
+                                refresh();
+                            } else
+                            {
+                                // settings will be automatically stored because of event handling
+                                refreshColumnsSettings();
+                                refreshColumnHeaderWidths();
+                                filterToolbar.refresh();
+                            }
+                        }
+                    };
+        ColumnSettingsDialog.show(viewContext, provider, getGridDisplayTypeID());
     }
 
     // @Private - for tests
@@ -1229,7 +1294,8 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
         SortInfo<T> sortInfo = getGridSortInfo();
         final TableExportCriteria<T> exportCriteria =
                 new TableExportCriteria<T>(resultSetKey, sortInfo, getAppliedFilters(), columnDefs,
-                        filterToolbar.tryGetCustomFilter());
+                        columnDefinitions, filterToolbar.tryGetCustomFilter(),
+                        getGridDisplayTypeID());
         return exportCriteria;
     }
 
@@ -1324,12 +1390,35 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
         {
             String columnID = m.getColumnID();
             int oldIndex = cm.getIndexById(columnID);
-            cm.setHidden(oldIndex, m.isVisible() == false);
-            cm.move(oldIndex, newIndex++);
+            if (oldIndex != -1)
+            {
+                cm.setHidden(oldIndex, m.isVisible() == false);
+                cm.move(oldIndex, newIndex++);
+            } else
+            { // new custom column has been added.
+                cm.addAt(newIndex++, createTemporaryColumnConfig(m));
+            }
+        }
+        // all deleted custom columns are now at the end starting from 'newIndex' - remove them
+        while (newIndex < cm.getColumnCount())
+        {
+            cm.remove(cm.getColumnCount() - 1);
         }
         cm.fireEvent(AppEvents.ColumnSettingsChanged, new ColumnModelEvent(cm));
     }
 
+    // This column config is created just to make user settings persistent.
+    // It must have been a custom column.
+    // The config will be recreated in a proper form when data will be refreshed.
+    private static ColumnConfig createTemporaryColumnConfig(ColumnDataModel m)
+    {
+        ColumnConfig columnConfig =
+                new ColumnConfig(m.getColumnID(), m.getHeader(),
+                        AbstractColumnDefinitionKind.DEFAULT_COLUMN_WIDTH);
+        columnConfig.setHidden(m.isVisible() == false);
+        return columnConfig;
+    }
+
     private static List<ColumnDataModel> createColumnsSettingsModel(ColumnModel cm,
             List<String> filteredColumnsIds)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractColumnSettingsDataModelProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractColumnSettingsDataModelProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..66a3513d8d1fe14631e08c96525128af3f3fe389
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractColumnSettingsDataModelProvider.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
+
+/**
+ * A common model provider for column settings tab.
+ * 
+ * @author Tomasz Pylak
+ */
+public abstract class AbstractColumnSettingsDataModelProvider
+{
+    /**
+     * Will be called passing the columns settings chosen by the user (with the right order) as a
+     * parameter when the Column Settings dialog closes.
+     */
+    protected abstract void onClose(List<ColumnDataModel> newColumnDataModels);
+
+    private final List<ColumnDataModel> columnDataModels;
+
+    private List<GridCustomColumn> lastLoadedCustomColumnsOrNull;
+
+    public AbstractColumnSettingsDataModelProvider(List<ColumnDataModel> columnDataModels)
+    {
+        this.columnDataModels = columnDataModels;
+        this.lastLoadedCustomColumnsOrNull = null;
+    }
+
+    /**
+     * @return column data model including the current state of the custom columns. Note that the
+     *         order may be different than the one chosen by the user.
+     */
+    public List<ColumnDataModel> getColumnDataModels()
+    {
+        return columnDataModels;
+    }
+
+    /**
+     * Called when all custom columns definitions are loaded from the database. Some custom columns
+     * may have been added or deleted, it will be taken into account when updating columnDataModels.
+     * 
+     * @param customColumns all custom columns for the grid
+     */
+    public void refreshCustomColumns(List<GridCustomColumn> customColumns)
+    {
+        // we assume that custom columns will be loaded once before any modifications will
+        // happen
+        if (lastLoadedCustomColumnsOrNull != null)
+        {
+            List<GridCustomColumn> addedColumns =
+                    getFreshColumns(lastLoadedCustomColumnsOrNull, customColumns);
+            addColumns(addedColumns);
+
+            List<GridCustomColumn> deletedColumns =
+                    getFreshColumns(customColumns, lastLoadedCustomColumnsOrNull);
+            deleteColumns(deletedColumns);
+        }
+        lastLoadedCustomColumnsOrNull = customColumns;
+    }
+
+    /** @return current custom columns or null if custom columns have not finish to load. */
+    public List<GridCustomColumnInfo> tryGetCustomColumnsInfo()
+    {
+        if (lastLoadedCustomColumnsOrNull == null)
+        {
+            return null;
+        }
+        List<GridCustomColumnInfo> result = new ArrayList<GridCustomColumnInfo>();
+        for (GridCustomColumn column : lastLoadedCustomColumnsOrNull)
+        {
+            result.add(createCustomColumnInfo(column));
+        }
+        return result;
+    }
+
+    private GridCustomColumnInfo createCustomColumnInfo(GridCustomColumn column)
+    {
+        return new GridCustomColumnInfo(getId(column), column.getName(), column.getDescription());
+    }
+
+    private void addColumns(List<GridCustomColumn> columns)
+    {
+        for (GridCustomColumn column : columns)
+        {
+            ColumnDataModel columnDataModel = createColumnDataModel(column);
+            columnDataModels.add(columnDataModel);
+        }
+
+    }
+
+    private void deleteColumns(List<GridCustomColumn> columns)
+    {
+        for (GridCustomColumn column : columns)
+        {
+            int ix = tryFindColumnIx(getId(column));
+            if (ix != -1)
+            {
+                columnDataModels.remove(ix);
+            } else
+            {
+                throw new IllegalStateException("cannot remove a column " + getId(column));
+            }
+        }
+    }
+
+    // returns ids of columns which are pressent in 'current' and not present in 'previous'
+    private static List<GridCustomColumn> getFreshColumns(List<GridCustomColumn> previous,
+            List<GridCustomColumn> current)
+    {
+        List<GridCustomColumn> result = new ArrayList<GridCustomColumn>();
+        Set<String> previousIds = extractColumnIds(previous);
+        for (GridCustomColumn column : current)
+        {
+            if (previousIds.contains(getId(column)) == false)
+            {
+                result.add(column);
+            }
+        }
+        return result;
+    }
+
+    private static String getId(GridCustomColumn column)
+    {
+        return column.getCode();
+    }
+
+    private static Set<String> extractColumnIds(List<GridCustomColumn> columns)
+    {
+        Set<String> result = new HashSet<String>();
+        for (GridCustomColumn column : columns)
+        {
+            result.add(getId(column));
+        }
+        return result;
+    }
+
+    private static ColumnDataModel createColumnDataModel(GridCustomColumn column)
+    {
+        return new ColumnDataModel(column.getName(), true, false, getId(column));
+    }
+
+    private int tryFindColumnIx(String columnId)
+    {
+        for (int i = 0; i < columnDataModels.size(); i++)
+        {
+            ColumnDataModel columnDataModel = columnDataModels.get(i);
+            if (columnDataModel.getColumnID().equals(columnId))
+            {
+                return i;
+            }
+        }
+        return -1;
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java
index 75c9a1fbec7911fb2fd21e407b582bb5be18dd46..e2fb93e87c0b933ae20af05bb467957b8233170f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java
@@ -23,6 +23,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewConte
 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.ui.columns.framework.IColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 
 /**
@@ -75,7 +76,7 @@ abstract public class AbstractSimpleBrowserGrid<T/* Entity */> extends
     }
 
     @Override
-    protected BaseEntityModel<T> createModel(T entity)
+    protected BaseEntityModel<T> createModel(GridRowModel<T> entity)
     {
         return new BaseEntityModel<T>(entity, getStaticColumnsDefinition());
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDataModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDataModel.java
index b256d963b7ef3a34c10ebb030ca4af86ffe91b30..5ccea58575ef2f402d044112786fab9479d23670 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDataModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDataModel.java
@@ -71,6 +71,11 @@ public class ColumnDataModel extends BaseModelData
         return get(HAS_FILTER);
     }
 
+    public String getHeader()
+    {
+        return get(HEADER);
+    }
+
     public String getAddress()
     {
         return get(ADDRESS);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsChooser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsChooser.java
index 3a66dfdb745e2b7ef34780c4307172c27f5847d8..95ee6d487267085df951b2f5df2660d006001f19 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsChooser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsChooser.java
@@ -42,8 +42,13 @@ class ColumnSettingsChooser
 
     private final Grid<ColumnDataModel> grid;
 
-    public ColumnSettingsChooser(List<ColumnDataModel> list, IMessageProvider messageProvider)
+    private final AbstractColumnSettingsDataModelProvider columnDataModelProvider;
+
+    public ColumnSettingsChooser(AbstractColumnSettingsDataModelProvider columnDataModelProvider,
+            IMessageProvider messageProvider)
     {
+        this.columnDataModelProvider = columnDataModelProvider;
+
         List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
 
         CheckColumnConfig isVisibleColumn =
@@ -64,7 +69,7 @@ class ColumnSettingsChooser
             column.setMenuDisabled(true);
         }
 
-        grid = new Grid<ColumnDataModel>(createStore(list), new ColumnModel(configs));
+        grid = new Grid<ColumnDataModel>(createStore(), new ColumnModel(configs));
         grid.setHideHeaders(false);
         grid.addPlugin(isVisibleColumn);
         grid.addPlugin(hasFilterColumn);
@@ -95,13 +100,58 @@ class ColumnSettingsChooser
                     });
     }
 
-    private static ListStore<ColumnDataModel> createStore(List<ColumnDataModel> list)
+    private ListStore<ColumnDataModel> createStore()
     {
+        List<ColumnDataModel> columnDataModels = columnDataModelProvider.getColumnDataModels();
+
+        // we want to create a store with new items but the order of old items should be kept
+        List<ColumnDataModel> newOrderedItems;
+        if (grid == null || grid.getStore() == null)
+        {
+            newOrderedItems = columnDataModels;
+        } else
+        {
+            newOrderedItems = keepPreviousOrder(columnDataModels, grid.getStore().getModels());
+        }
         ListStore<ColumnDataModel> store = new ListStore<ColumnDataModel>();
-        store.add(list);
+        store.add(newOrderedItems);
         return store;
     }
 
+    private static List<ColumnDataModel> keepPreviousOrder(
+            List<ColumnDataModel> newColumnDataModels, List<ColumnDataModel> prevOrderedItems)
+    {
+        List<ColumnDataModel> temporaryModels = new ArrayList<ColumnDataModel>(newColumnDataModels);
+
+        List<ColumnDataModel> newOrderedItems = new ArrayList<ColumnDataModel>();
+        for (ColumnDataModel prevModel : prevOrderedItems)
+        {
+            int ix = findIx(temporaryModels, prevModel.getColumnID());
+            if (ix != -1)
+            {
+                newOrderedItems.add(temporaryModels.get(ix));
+                temporaryModels.remove(ix);
+            }
+        }
+        for (ColumnDataModel newItems : temporaryModels)
+        {
+            newOrderedItems.add(newItems);
+        }
+        return newOrderedItems;
+    }
+
+    private static int findIx(List<ColumnDataModel> columnDataModels, String columnID)
+    {
+        for (int i = 0; i < columnDataModels.size(); i++)
+        {
+            if (columnDataModels.get(i).getColumnID().equals(columnID))
+            {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     public Component getComponent()
     {
         ContentPanel cp = new ContentPanel();
@@ -199,9 +249,14 @@ class ColumnSettingsChooser
             };
     }
 
+    /** rebuilds columns which can be chosen */
+    public void refresh()
+    {
+        grid.reconfigure(createStore(), grid.getColumnModel());
+    }
+
     public List<ColumnDataModel> getModels()
     {
         return grid.getStore().getModels();
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsDialog.java
index 1e0882f0ac8e300bd0aaecf8a63d7363bb032530..48e01a14d5939afd9598721939c058e3001c1f11 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnSettingsDialog.java
@@ -1,9 +1,11 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid;
 
-import java.util.List;
 
+import com.extjs.gxt.ui.client.Events;
 import com.extjs.gxt.ui.client.event.ComponentEvent;
+import com.extjs.gxt.ui.client.event.Listener;
 import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.event.TabPanelEvent;
 import com.extjs.gxt.ui.client.widget.Component;
 import com.extjs.gxt.ui.client.widget.Dialog;
 import com.extjs.gxt.ui.client.widget.TabItem;
@@ -18,7 +20,6 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericCon
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.expressions.column.GridCustomColumnGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.expressions.filter.GridCustomFilterGrid;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IResultUpdater;
 
 /**
  * {@link Dialog} displaying {@link ColumnSettingsChooser}.
@@ -38,10 +39,9 @@ public class ColumnSettingsDialog extends Dialog
     private final String gridDisplayId;
 
     public static void show(IViewContext<ICommonClientServiceAsync> viewContext,
-            List<ColumnDataModel> columnModels,
-            IResultUpdater<List<ColumnDataModel>> resultUpdater, String gridDisplayId)
+            AbstractColumnSettingsDataModelProvider columnDataModelProvider, String gridDisplayId)
     {
-        new ColumnSettingsDialog(viewContext, gridDisplayId).show(columnModels, resultUpdater);
+        new ColumnSettingsDialog(viewContext, gridDisplayId).show(columnDataModelProvider);
     }
 
     private ColumnSettingsDialog(IViewContext<ICommonClientServiceAsync> viewContext, String gridId)
@@ -57,27 +57,33 @@ public class ColumnSettingsDialog extends Dialog
     /**
      * Shows window containing {@link ColumnSettingsChooser} based on given {@link ColumnModel}.
      */
-    private void show(final List<ColumnDataModel> columnModels,
-            final IResultUpdater<List<ColumnDataModel>> resultUpdater)
+    private void show(final AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
-        assert columnModels != null : "columnModels not specified";
+        assert columnDataModelProvider != null : "columnDataModelProvider not specified";
         removeAll();
         TabPanel panel = new TabPanel();
         panel.setId(TAB_PANEL_ID_PREFIX + gridDisplayId);
 
         final ColumnSettingsChooser columnChooser =
-                new ColumnSettingsChooser(columnModels, viewContext);
+                new ColumnSettingsChooser(columnDataModelProvider, viewContext);
         TabItem columnsTab = createTabItem(columnChooser.getComponent(), Dict.COLUMNS, "");
+        columnsTab.addListener(Events.Select, new Listener<TabPanelEvent>()
+            {
+                public final void handleEvent(final TabPanelEvent be)
+                {
+                    columnChooser.refresh();
+                }
+            });
         panel.add(columnsTab);
 
         final IDisposableComponent filters =
-                GridCustomFilterGrid.create(viewContext, gridDisplayId, columnModels);
+                GridCustomFilterGrid.create(viewContext, gridDisplayId, columnDataModelProvider);
         TabItem customFiltersTab =
                 createTabItem(filters.getComponent(), Dict.GRID_CUSTOM_FILTERS, FILTERS_TAB);
         panel.add(customFiltersTab);
 
         final IDisposableComponent columns =
-                GridCustomColumnGrid.create(viewContext, gridDisplayId, columnModels);
+                GridCustomColumnGrid.create(viewContext, gridDisplayId, columnDataModelProvider);
         TabItem customColumnsTab =
                 createTabItem(columns.getComponent(), Dict.GRID_CUSTOM_COLUMNS, COLUMNS_TAB);
         panel.add(customColumnsTab);
@@ -91,7 +97,7 @@ public class ColumnSettingsDialog extends Dialog
                 @Override
                 public void componentSelected(ComponentEvent ce)
                 {
-                    resultUpdater.update(columnChooser.getModels());
+                    columnDataModelProvider.onClose(columnChooser.getModels());
                     filters.dispose();
                     columns.dispose();
                     hide();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/CustomColumnsMetadataProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/CustomColumnsMetadataProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..701896dbf8a794a59ba63294b4671ee2abd4687f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/CustomColumnsMetadataProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
+
+/**
+ * Stores metadata about grid custom columns.
+ * 
+ * @author Tomasz Pylak
+ */
+class CustomColumnsMetadataProvider
+{
+    // what custom columns are present in the grid. Used to build column definitions.
+    private List<GridCustomColumnInfo> customColumnsMetadata;
+
+    // has the last setter call changed the matadata?
+    private boolean hasChanged;
+
+    /** true if the value has changed. Subsequent calls will return false. */
+    public boolean getUnsettingHasChanged()
+    {
+        boolean result = hasChanged;
+        this.hasChanged = false;
+        return result;
+    }
+
+    public List<GridCustomColumnInfo> tryGetCustomColumnsMetadata()
+    {
+        return customColumnsMetadata;
+    }
+
+    public void setCustomColumnsMetadata(List<GridCustomColumnInfo> customColumnsMetadata)
+    {
+        this.hasChanged =
+                (this.customColumnsMetadata == null && customColumnsMetadata != null)
+                        || this.customColumnsMetadata.equals(customColumnsMetadata) == false;
+        this.customColumnsMetadata = customColumnsMetadata;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/MoveableColumnModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/MoveableColumnModel.java
index 31b57ab7ccf83cf0c52b441f703292a07d03eea5..b5d18cb6874af84c58ef4f292b3704de10112e58 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/MoveableColumnModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/MoveableColumnModel.java
@@ -51,4 +51,20 @@ public class MoveableColumnModel extends ColumnModel
         }
     }
 
+    /**
+     * Removes the column from the specified position.
+     */
+    public void remove(int fromIndex)
+    {
+        config.remove(fromIndex);
+    }
+
+    /**
+     * Adds the column at the specified position.
+     */
+    public void addAt(int index, ColumnConfig columnConfig)
+    {
+        config.add(index, columnConfig);
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/entity/PropertyTypesCriteriaProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/entity/PropertyTypesCriteriaProvider.java
index 389d80f25cd25cb99edfc90d125e12e7eb7a9ab8..929cfb9d69baf85c2736e386c9e62b7f98a48d18 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/entity/PropertyTypesCriteriaProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/entity/PropertyTypesCriteriaProvider.java
@@ -58,7 +58,7 @@ public class PropertyTypesCriteriaProvider implements ICriteriaProvider<Property
         @Override
         protected void process(ResultSet<PropertyType> result)
         {
-            List<PropertyType> properties = result.getList();
+            List<PropertyType> properties = result.getList().extractOriginalObjects();
             if (propertiesFilterOrNull != null)
             {
                 properties =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/column/GridCustomColumnGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/column/GridCustomColumnGrid.java
index 08e14b140393ea8651c199448517143bbfe42fe2..95b2be7808160bafca81e5a768b8f3daa110ffc8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/column/GridCustomColumnGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/column/GridCustomColumnGrid.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.expressions.column;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import com.extjs.gxt.ui.client.event.ComponentEvent;
@@ -34,8 +35,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.CustomGridColumnColDefKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractColumnSettingsDataModelProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractSimpleBrowserGrid;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDataModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IBrowserGridActionInvoker;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
@@ -43,6 +44,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ex
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractDataConfirmationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
@@ -64,9 +67,9 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
             GenericConstants.ID_PREFIX + "custom-grid-column-browser";
 
     public static IDisposableComponent create(IViewContext<ICommonClientServiceAsync> viewContext,
-            String gridDisplayId, List<ColumnDataModel> columnModels)
+            String gridDisplayId, AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
-        return new GridCustomColumnGrid(viewContext, gridDisplayId, columnModels)
+        return new GridCustomColumnGrid(viewContext, gridDisplayId, columnDataModelProvider)
                 .asDisposableWithoutToolbar();
     }
 
@@ -87,7 +90,7 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
 
     protected final String gridDisplayId;
 
-    private final List<ColumnDataModel> columnModels;
+    private final AbstractColumnSettingsDataModelProvider columnDataModelProvider;
 
     private void extendBottomToolbar()
     {
@@ -136,13 +139,14 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
 
     private Window createAddDialog()
     {
-        return new AddDialog(viewContext, createRefreshGridAction(), gridDisplayId, columnModels);
+        return new AddDialog(viewContext, createRefreshGridAction(), gridDisplayId,
+                columnDataModelProvider);
     }
 
     private Window createEditDialog(AbstractGridExpression updatedItem)
     {
-        return new EditDialog(viewContext, createRefreshGridAction(), gridDisplayId, columnModels,
-                updatedItem);
+        return new EditDialog(viewContext, createRefreshGridAction(), gridDisplayId,
+                columnDataModelProvider, updatedItem);
     }
 
     private static class AddDialog extends AbstractGridCustomExpressionEditOrRegisterDialog
@@ -151,10 +155,10 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
 
         public AddDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
                 final IDelegatedAction postRegistrationCallback, String gridId,
-                List<ColumnDataModel> columnModels)
+                AbstractColumnSettingsDataModelProvider columnDataModelProvider)
         {
             super(viewContext, viewContext.getMessage(Dict.ADD_NEW_COLUMN),
-                    postRegistrationCallback, gridId, columnModels);
+                    postRegistrationCallback, gridId, columnDataModelProvider);
             this.viewContext = viewContext;
         }
 
@@ -174,11 +178,12 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
 
         public EditDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
                 final IDelegatedAction postRegistrationCallback, String gridId,
-                List<ColumnDataModel> columnModels, AbstractGridExpression itemToUpdate)
+                AbstractColumnSettingsDataModelProvider columnDataModelProvider,
+                AbstractGridExpression itemToUpdate)
         {
             super(viewContext, viewContext.getMessage(Dict.EDIT_TITLE, viewContext
                     .getMessage(Dict.COLUMN), itemToUpdate.getName()), postRegistrationCallback,
-                    gridId, columnModels);
+                    gridId, columnDataModelProvider);
             this.viewContext = viewContext;
             this.itemToUpdate = itemToUpdate;
             initializeValues(itemToUpdate);
@@ -233,12 +238,12 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
     }
 
     private GridCustomColumnGrid(IViewContext<ICommonClientServiceAsync> viewContext,
-            String gridDisplayId, List<ColumnDataModel> columnModels)
+            String gridDisplayId, AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
         super(viewContext, createBrowserId(gridDisplayId), createGridId(gridDisplayId),
                 DisplayTypeIDGenerator.CUSTOM_GRID_COLUMN_GRID);
         this.gridDisplayId = gridDisplayId;
-        this.columnModels = columnModels;
+        this.columnDataModelProvider = columnDataModelProvider;
         extendBottomToolbar();
     }
 
@@ -250,9 +255,47 @@ public class GridCustomColumnGrid extends AbstractSimpleBrowserGrid<GridCustomCo
 
     @Override
     protected void listEntities(DefaultResultSetConfig<String, GridCustomColumn> resultSetConfig,
-            AbstractAsyncCallback<ResultSet<GridCustomColumn>> callback)
+            final AbstractAsyncCallback<ResultSet<GridCustomColumn>> callback)
     {
-        viewContext.getService().listColumns(gridDisplayId, resultSetConfig, callback);
+        final int orgOffset = resultSetConfig.getOffset();
+        final int orgLimit = resultSetConfig.getLimit();
+        // we want to fetch all custom columns, not just one page. We will update the whole grid
+        // model with it. There should not be that many custom columns.
+        resultSetConfig.setOffset(0);
+        resultSetConfig.setLimit(DefaultResultSetConfig.NO_LIMIT);
+        AsyncCallback<ResultSet<GridCustomColumn>> wrappedCallback =
+                new AsyncCallback<ResultSet<GridCustomColumn>>()
+                    {
+                        public void onSuccess(ResultSet<GridCustomColumn> result)
+                        {
+                            List<GridCustomColumn> allCustomColumns =
+                                    result.getList().extractOriginalObjects();
+                            columnDataModelProvider.refreshCustomColumns(allCustomColumns);
+                            setPageFromAllFetched(result, orgOffset, orgLimit);
+                            callback.onSuccess(result);
+                        }
+
+                        private void setPageFromAllFetched(ResultSet<GridCustomColumn> result,
+                                final int offset, final int limit)
+                        {
+                            GridRowModels<GridCustomColumn> allModel = result.getList();
+                            List<GridRowModel<GridCustomColumn>> pageResult =
+                                    new ArrayList<GridRowModel<GridCustomColumn>>(limit);
+                            for (int i = offset; i < Math.min(offset + limit, allModel.size()); i++)
+                            {
+                                pageResult.add(allModel.get(i));
+                            }
+                            result.setList(new GridRowModels<GridCustomColumn>(pageResult, allModel
+                                    .getCustomColumnsMetadata()));
+                        }
+
+                        public void onFailure(Throwable caught)
+                        {
+                            callback.onFailure(caught);
+                        }
+                    };
+        viewContext.getService().listGridCustomColumns(gridDisplayId, resultSetConfig,
+                wrappedCallback);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/AbstractGridCustomExpressionEditOrRegisterDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/AbstractGridCustomExpressionEditOrRegisterDialog.java
index 6be0802351663f153b3040882489c572d5db2e89..a2e62e64b7db1fe25810102685e0307dfbbb7942 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/AbstractGridCustomExpressionEditOrRegisterDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/AbstractGridCustomExpressionEditOrRegisterDialog.java
@@ -18,8 +18,6 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.e
 
 import static ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils.unescapeHtml;
 
-import java.util.List;
-
 import com.extjs.gxt.ui.client.event.BaseEvent;
 import com.extjs.gxt.ui.client.event.Listener;
 import com.extjs.gxt.ui.client.widget.Window;
@@ -35,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.L
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.CheckBoxField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.DescriptionField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MultilineVarcharField;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDataModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractColumnSettingsDataModelProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractRegistrationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractGridExpression;
@@ -82,7 +80,7 @@ abstract public class AbstractGridCustomExpressionEditOrRegisterDialog extends
     public AbstractGridCustomExpressionEditOrRegisterDialog(
             final IViewContext<ICommonClientServiceAsync> viewContext, final String title,
             final IDelegatedAction postRegistrationCallback, final String gridId,
-            final List<ColumnDataModel> columnModels)
+            final AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
         super(viewContext, title, postRegistrationCallback);
         this.viewContext = viewContext;
@@ -94,7 +92,8 @@ abstract public class AbstractGridCustomExpressionEditOrRegisterDialog extends
         addField(expressionField = createExpressionField());
         expressionField.setId(createId(gridId, EXPRESSION_FIELD));
         addField(insertColumnsLink =
-                createInsertColumnsLink(viewContext.getMessage(Dict.INSERT_COLUMNS), columnModels));
+                createInsertColumnsLink(viewContext.getMessage(Dict.INSERT_COLUMNS),
+                        columnDataModelProvider));
         insertColumnsLink.setId(createId(gridId, INSERT_COLUMNS_LINK));
         addField(publicField = new CheckBoxField(viewContext.getMessage(Dict.IS_PUBLIC), false));
         publicField.setId(createId(gridId, PUBLIC_FIELD));
@@ -113,7 +112,7 @@ abstract public class AbstractGridCustomExpressionEditOrRegisterDialog extends
     }
 
     private LabelField createInsertColumnsLink(final String label,
-            final List<ColumnDataModel> columnModels)
+            final AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
         LabelField result = new LabelField(LinkRenderer.renderAsLink(label));
         result.sinkEvents(Event.ONCLICK);
@@ -121,7 +120,7 @@ abstract public class AbstractGridCustomExpressionEditOrRegisterDialog extends
             {
                 public void handleEvent(BaseEvent be)
                 {
-                    GridColumnChooserDialog.show(viewContext, columnModels, gridId,
+                    GridColumnChooserDialog.show(viewContext, columnDataModelProvider, gridId,
                             asExpressionHolder(expressionField));
                 }
             });
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooser.java
index 42e97d10c5e84f08938de63315921a53f266cd1e..75012a2a9af37fcc78818bc47d67f4917e738ede 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooser.java
@@ -13,6 +13,7 @@ import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
 import com.extjs.gxt.ui.client.widget.grid.Grid;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractColumnSettingsDataModelProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDataModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 
@@ -28,7 +29,8 @@ class GridColumnChooser
 
     private final Grid<ColumnDataModel> grid;
 
-    public GridColumnChooser(List<ColumnDataModel> list, IMessageProvider messageProvider)
+    public GridColumnChooser(AbstractColumnSettingsDataModelProvider columnDataModelProvider,
+            IMessageProvider messageProvider)
     {
         List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
 
@@ -47,7 +49,10 @@ class GridColumnChooser
             column.setMenuDisabled(true);
         }
 
-        grid = new Grid<ColumnDataModel>(createStore(list), new ColumnModel(configs));
+        grid =
+                new Grid<ColumnDataModel>(
+                        createStore(columnDataModelProvider.getColumnDataModels()),
+                        new ColumnModel(configs));
         grid.setHideHeaders(false);
         grid.getSelectionModel().setSelectionMode(SelectionMode.MULTI);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooserDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooserDialog.java
index 96e47bd2834281694485e9666e3d8a87b8efd99c..c112c0ddf8d671f751fe41592d2e2045c93c2564 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooserDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/common/GridColumnChooserDialog.java
@@ -1,7 +1,5 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.expressions.common;
 
-import java.util.List;
-
 import com.extjs.gxt.ui.client.event.BaseEvent;
 import com.extjs.gxt.ui.client.event.ComponentEvent;
 import com.extjs.gxt.ui.client.event.Listener;
@@ -15,7 +13,7 @@ import com.google.gwt.user.client.Event;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDataModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractColumnSettingsDataModelProvider;
 
 /**
  * {@link Dialog} displaying {@link GridColumnChooser}. Used to insert selected columns into an
@@ -28,9 +26,9 @@ class GridColumnChooserDialog extends Dialog
     private final IViewContext<ICommonClientServiceAsync> viewContext;
 
     public static void show(IViewContext<ICommonClientServiceAsync> viewContext,
-            List<ColumnDataModel> columnModels, String gridId, IExpressionHolder expressionField)
+            AbstractColumnSettingsDataModelProvider columnDataModelProvider, String gridId, IExpressionHolder expressionField)
     {
-        new GridColumnChooserDialog(viewContext, gridId).show(columnModels, expressionField);
+        new GridColumnChooserDialog(viewContext, gridId).show(columnDataModelProvider, expressionField);
     }
 
     private GridColumnChooserDialog(IViewContext<ICommonClientServiceAsync> viewContext,
@@ -47,12 +45,12 @@ class GridColumnChooserDialog extends Dialog
     /**
      * Shows window containing {@link GridColumnChooser} based on given {@link ColumnModel}.
      */
-    private void show(final List<ColumnDataModel> columnModels,
+    private void show(final AbstractColumnSettingsDataModelProvider columnDataModelProvider,
             final IExpressionHolder expressionField)
     {
-        assert columnModels != null : "columnModels not specified";
+        assert columnDataModelProvider != null : "columnModels not specified";
         removeAll();
-        final GridColumnChooser columnChooser = new GridColumnChooser(columnModels, viewContext);
+        final GridColumnChooser columnChooser = new GridColumnChooser(columnDataModelProvider, viewContext);
         final Component columnChooserComponent = columnChooser.getComponent();
         add(columnChooserComponent);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/FilterToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/FilterToolbar.java
index b9d35df553b4cfdbb4f5f4ed2bdb89aea2af8ff8..c7f1d9832c51fe782268561ac42aa60fd7f3ad22 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/FilterToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/FilterToolbar.java
@@ -136,7 +136,7 @@ public class FilterToolbar<T> extends ToolBar implements IDatabaseModificationOb
         return getCustomFilterSelectedState(true);
     }
 
-    public boolean isCustomFilterSelected()
+    private boolean isCustomFilterSelected()
     {
         return getCustomFilterSelectedState(false);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/GridCustomFilterGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/GridCustomFilterGrid.java
index edd0cb2bdf1e986ad36b20062a65df3d65968281..658b93de53789e8d11f5ffcd61e2c1b750cbdb4f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/GridCustomFilterGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/expressions/filter/GridCustomFilterGrid.java
@@ -34,8 +34,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.CustomGridFilterColDefKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractColumnSettingsDataModelProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractSimpleBrowserGrid;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDataModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IBrowserGridActionInvoker;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
@@ -63,9 +63,9 @@ public class GridCustomFilterGrid extends AbstractSimpleBrowserGrid<GridCustomFi
     private static final String BROWSER_ID = GenericConstants.ID_PREFIX + "filter-browser";
 
     public static IDisposableComponent create(IViewContext<ICommonClientServiceAsync> viewContext,
-            String gridDisplayId, List<ColumnDataModel> columnModels)
+            String gridDisplayId, AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
-        return new GridCustomFilterGrid(viewContext, gridDisplayId, columnModels)
+        return new GridCustomFilterGrid(viewContext, gridDisplayId, columnDataModelProvider)
                 .asDisposableWithoutToolbar();
     }
 
@@ -86,7 +86,7 @@ public class GridCustomFilterGrid extends AbstractSimpleBrowserGrid<GridCustomFi
 
     protected final String gridDisplayId;
 
-    private final List<ColumnDataModel> columnModels;
+    private final AbstractColumnSettingsDataModelProvider columnDataModelProvider;
 
     private void extendBottomToolbar()
     {
@@ -135,13 +135,14 @@ public class GridCustomFilterGrid extends AbstractSimpleBrowserGrid<GridCustomFi
 
     private Window createAddDialog()
     {
-        return new AddDialog(viewContext, createRefreshGridAction(), gridDisplayId, columnModels);
+        return new AddDialog(viewContext, createRefreshGridAction(), gridDisplayId,
+                columnDataModelProvider);
     }
 
     private Window createEditDialog(AbstractGridExpression updatedItem)
     {
-        return new EditDialog(viewContext, createRefreshGridAction(), gridDisplayId, columnModels,
-                updatedItem);
+        return new EditDialog(viewContext, createRefreshGridAction(), gridDisplayId,
+                columnDataModelProvider, updatedItem);
     }
 
     private static class AddDialog extends AbstractGridCustomExpressionEditOrRegisterDialog
@@ -150,10 +151,10 @@ public class GridCustomFilterGrid extends AbstractSimpleBrowserGrid<GridCustomFi
 
         public AddDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
                 final IDelegatedAction postRegistrationCallback, String gridId,
-                List<ColumnDataModel> columnModels)
+                AbstractColumnSettingsDataModelProvider columnDataModelProvider)
         {
             super(viewContext, viewContext.getMessage(Dict.ADD_NEW_FILTER),
-                    postRegistrationCallback, gridId, columnModels);
+                    postRegistrationCallback, gridId, columnDataModelProvider);
             this.viewContext = viewContext;
         }
 
@@ -173,11 +174,11 @@ public class GridCustomFilterGrid extends AbstractSimpleBrowserGrid<GridCustomFi
 
         public EditDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
                 final IDelegatedAction postRegistrationCallback, String gridId,
-                List<ColumnDataModel> columnModels, AbstractGridExpression itemToUpdate)
+                AbstractColumnSettingsDataModelProvider columnDataModelProvider, AbstractGridExpression itemToUpdate)
         {
             super(viewContext, viewContext.getMessage(Dict.EDIT_TITLE, viewContext
                     .getMessage(Dict.FILTER), itemToUpdate.getName()), postRegistrationCallback,
-                    gridId, columnModels);
+                    gridId, columnDataModelProvider);
             this.viewContext = viewContext;
             this.itemToUpdate = itemToUpdate;
             initializeValues(itemToUpdate);
@@ -232,12 +233,12 @@ public class GridCustomFilterGrid extends AbstractSimpleBrowserGrid<GridCustomFi
     }
 
     private GridCustomFilterGrid(IViewContext<ICommonClientServiceAsync> viewContext,
-            String gridDisplayId, List<ColumnDataModel> columnModels)
+            String gridDisplayId, AbstractColumnSettingsDataModelProvider columnDataModelProvider)
     {
         super(viewContext, createBrowserId(gridDisplayId), createGridId(gridDisplayId),
                 DisplayTypeIDGenerator.FILTER_BROWSER_GRID);
         this.gridDisplayId = gridDisplayId;
-        this.columnModels = columnModels;
+        this.columnDataModelProvider = columnDataModelProvider;
         extendBottomToolbar();
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java
index 4bdf99f5680ed187fd1eeb6bc6544705704f5887..9637dbe580504c13a1e1ede2ed6c8dcd02538110 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java
@@ -42,6 +42,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Ab
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableEntityChooser;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListMaterialCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -191,7 +192,7 @@ public class MaterialBrowserGrid extends
     }
 
     @Override
-    protected BaseEntityModel<Material> createModel(Material entity)
+    protected BaseEntityModel<Material> createModel(GridRowModel<Material> entity)
     {
         return getColumnsFactory().createModel(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
index 9bb9935d09e4de9db24bce6afd98f046dff93666..8830f3a21e97af135af3fbc5545130c2cafc1368 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
@@ -46,6 +46,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ID
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractRegistrationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
@@ -323,7 +324,7 @@ public class PropertyTypeAssignmentGrid extends
 
     @Override
     protected BaseEntityModel<EntityTypePropertyType<?>> createModel(
-            EntityTypePropertyType<?> entity)
+            GridRowModel<EntityTypePropertyType<?>> entity)
     {
         BaseEntityModel<EntityTypePropertyType<?>> model = super.createModel(entity);
         model.renderAsMultilineStringWithTooltip(PropertyTypeAssignmentColDefKind.DESCRIPTION.id());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java
index 6e7c0c92dda3e5cf4345caa37063cb67150a0e73..e16381058289a7e82540e54b3da6088d3d98002c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java
@@ -50,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
@@ -205,7 +206,7 @@ public class PropertyTypeGrid extends AbstractSimpleBrowserGrid<PropertyType>
     }
 
     @Override
-    protected PropertyTypeModel createModel(PropertyType entity)
+    protected PropertyTypeModel createModel(GridRowModel<PropertyType> entity)
     {
         PropertyTypeModel model = new PropertyTypeModel(entity, getStaticColumnsDefinition());
         model.renderAsMultilineStringWithTooltip(PropertyTypeColDefKind.DESCRIPTION.id());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java
index 73470efdf4de94ddc9fa1b3c1e34630c22ca5ec7..fdf2ae197f1fe97497dda4bfeb30b0b4106bbcf7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java
@@ -100,7 +100,7 @@ public final class PropertyTypeSelectionWidget extends
         {
             final ListStore<PropertyTypeComboModel> propertyTypeStore = getStore();
             propertyTypeStore.removeAll();
-            propertyTypeStore.add(convertItems(result.getList()));
+            propertyTypeStore.add(convertItems(result.getList().extractOriginalObjects()));
             if (propertyTypeStore.getCount() > 0)
             {
                 setEmptyText(viewContext.getMessage(Dict.COMBO_BOX_CHOOSE, CHOOSE_SUFFIX));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
index bdbde1786c9d8469169da3cae996c6b5f013d052..a9b39444b656a93f5c6cbdeac9a329c80d459f0a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
@@ -60,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedActionWithResult;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedIdHolderCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListEntityDisplayCriteriaKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
@@ -440,7 +441,7 @@ public class SampleBrowserGrid extends
     }
 
     @Override
-    protected BaseEntityModel<Sample> createModel(Sample entity)
+    protected BaseEntityModel<Sample> createModel(GridRowModel<Sample> entity)
     {
         return SampleModelFactory.createModel(entity);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java
index d449c15dd7d87c9067f19d6a0f4efcb0e35b3952..a7f3baea3fa1ae10e32c450b938fd093ed4a029d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchFieldsSelectionWidget.java
@@ -145,7 +145,7 @@ public final class DetailedSearchFieldsSelectionWidget extends
         @Override
         protected void process(final ResultSet<PropertyType> result)
         {
-            propertyTypes = result.getList();
+            propertyTypes = result.getList().extractOriginalObjects();
 
             final ListStore<DetailedSearchFieldComboModel> propertyTypeStore = getStore();
             propertyTypeStore.removeAll();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularySelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularySelectionWidget.java
index 78d5a6153ff4dd5489407e9251c7272a2639c399..2af589357003bfae82d07c6afcd9b1e7360e04aa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularySelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularySelectionWidget.java
@@ -92,7 +92,6 @@ public class VocabularySelectionWidget extends DropDownList<BaseModelData, Vocab
     {
         DefaultResultSetConfig<String, Vocabulary> criteria =
                 DefaultResultSetConfig.createFetchAll();
-        // TODO 2009-03-31, Tomasz Pylak: clean the server-side cache at some point
         viewContext.getService().listVocabularies(false, true, criteria,
                 new AsyncCallback<ResultSet<Vocabulary>>()
                     {
@@ -103,7 +102,7 @@ public class VocabularySelectionWidget extends DropDownList<BaseModelData, Vocab
 
                         public void onSuccess(ResultSet<Vocabulary> result)
                         {
-                            callback.onSuccess(result.getList());
+                            callback.onSuccess(result.getList().extractOriginalObjects());
                         }
                     });
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
index be5a2512e1596106869217ddacb2e3cdad08cd44..3cac2d92d811762a3f69dc43addcb59f19eec535 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
@@ -58,6 +58,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
@@ -310,7 +311,8 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
     }
 
     @Override
-    protected BaseEntityModel<VocabularyTermWithStats> createModel(VocabularyTermWithStats entity)
+    protected BaseEntityModel<VocabularyTermWithStats> createModel(
+            GridRowModel<VocabularyTermWithStats> entity)
     {
         BaseEntityModel<VocabularyTermWithStats> model = super.createModel(entity);
         model.renderAsMultilineStringWithTooltip(VocabularyTermColDefKind.DESCRIPTION.id());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java
index 4981a4af2559f1297749a26357d866fbdd51b8e3..e7c13b804d6c5f47a6832136b3c9b9946ad6b11f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java
@@ -36,8 +36,6 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS
     private int limit = NO_LIMIT;
 
     private int offset = 0;
-    
-    private Set<IColumnDefinition<T>> availableColumns;
 
     private SortInfo<T> sortInfo = new SortInfo<T>();
 
@@ -51,7 +49,12 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS
      */
     private K resultSetKeyOrNull;
 
-    private CustomFilterInfo<T> customFilterInfo;
+    private Set<IColumnDefinition<T>> availableColumns;
+
+    private CustomFilterInfo<T> customFilterInfoOrNull;
+
+    // null if no custom columns are needed
+    private String gridDisplayIdOrNull;
 
     public static <K, T> DefaultResultSetConfig<K, T> createFetchAll()
     {
@@ -97,6 +100,7 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS
         setFilterInfos(resultSetConfig.getFilterInfos());
         setResultSetKey(resultSetConfig.getResultSetKey());
         setCustomFilterInfo(resultSetConfig.tryGetCustomFilterInfo());
+        setGridDisplayId(resultSetConfig.tryGetGridDisplayId());
     }
 
     //
@@ -117,7 +121,7 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS
     {
         return availableColumns;
     }
-    
+
     public final SortInfo<T> getSortInfo()
     {
         return sortInfo;
@@ -136,12 +140,21 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS
 
     public CustomFilterInfo<T> tryGetCustomFilterInfo()
     {
-        return customFilterInfo;
+        return customFilterInfoOrNull;
     }
 
     public void setCustomFilterInfo(CustomFilterInfo<T> customFilterInfo)
     {
-        this.customFilterInfo = customFilterInfo;
+        this.customFilterInfoOrNull = customFilterInfo;
     }
 
+    public void setGridDisplayId(String gridDisplayIdOrNull)
+    {
+        this.gridDisplayIdOrNull = gridDisplayIdOrNull;
+    }
+
+    public String tryGetGridDisplayId()
+    {
+        return gridDisplayIdOrNull;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridCustomColumnInfo.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridCustomColumnInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac1960618ffdffee261f87ee4405f88b6bbde7af
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridCustomColumnInfo.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Basic metadata about a grid custom column: code (column identifier), label and description.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridCustomColumnInfo implements IsSerializable
+{
+    private String code;
+
+    private String label;
+
+    private String description;
+
+    public GridCustomColumnInfo(String code, String label, String description)
+    {
+        this.code = code;
+        this.label = label;
+        this.description = description;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    @SuppressWarnings("unused")
+    // GWT only
+    private void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getLabel()
+    {
+        return label;
+    }
+
+    @SuppressWarnings("unused")
+    // GWT only
+    private GridCustomColumnInfo()
+    {
+    }
+
+    @SuppressWarnings("unused")
+    // GWT only
+    private void setLabel(String label)
+    {
+        this.label = label;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    @SuppressWarnings("unused")
+    // GWT only
+    private void setDescription(String description)
+    {
+        this.description = description;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null || obj instanceof GridCustomColumnInfo == false)
+        {
+            return false;
+        }
+        GridCustomColumnInfo that = (GridCustomColumnInfo) obj;
+        return code.equals(that.code) && label.equals(that.label);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridCustomColumnValue.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridCustomColumnValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..daa869ed9f5b68b82808545f90c3be1263f38e68
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridCustomColumnValue.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Stores grid custom column id and value.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridCustomColumnValue implements IsSerializable
+{
+    private String columnId;
+
+    private String value;
+
+    public String getColumnId()
+    {
+        return columnId;
+    }
+
+    public void setColumnId(String columnId)
+    {
+        this.columnId = columnId;
+    }
+
+    public String getValue()
+    {
+        return value;
+    }
+
+    public void setValue(String value)
+    {
+        this.value = value;
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridRowModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridRowModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb7c90a6e59c5e1c26e8c954f354ed05f4a6366f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridRowModel.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Stores the original object which will be a basis to calculate a grid row together with calculated
+ * all custom columns values.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridRowModel<T> implements IsSerializable
+{
+    private T originalObject;
+
+    // We would like to have a Map field, but we cannot do it because of a bug in
+    // displaying serialization warnings in GWT 1.5. It was fixed in GWT 1.6
+    private List<GridCustomColumnValue> calculatedColumnValues;
+
+    public GridRowModel(T originalObject, HashMap<String, String> calculatedColumnMap)
+    {
+        this.originalObject = originalObject;
+        this.calculatedColumnValues = asList(calculatedColumnMap);
+    }
+
+    private List<GridCustomColumnValue> asList(HashMap<String, String> map)
+    {
+        List<GridCustomColumnValue> result = new ArrayList<GridCustomColumnValue>();
+        for (Entry<String, String> entry : map.entrySet())
+        {
+            GridCustomColumnValue column = new GridCustomColumnValue();
+            column.setColumnId(entry.getKey());
+            column.setValue(entry.getValue());
+            result.add(column);
+        }
+        return result;
+    }
+
+    public T getOriginalObject()
+    {
+        return originalObject;
+    }
+
+    public List<GridCustomColumnValue> getCalculatedColumnValues()
+    {
+        return calculatedColumnValues;
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private void setCalculatedColumnValues(List<GridCustomColumnValue> calculatedColumnValues)
+    {
+        this.calculatedColumnValues = calculatedColumnValues;
+    }
+
+    public String findColumnValue(String columnId)
+    {
+        for (GridCustomColumnValue value : calculatedColumnValues)
+        {
+            if (value.getColumnId().equals(columnId))
+            {
+                return value.getValue();
+            }
+        }
+        throw new IllegalStateException("Column not found: " + columnId);
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private GridRowModel()
+    {
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private void setOriginalObject(T originalObject)
+    {
+        this.originalObject = originalObject;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridRowModels.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridRowModels.java
new file mode 100644
index 0000000000000000000000000000000000000000..b60033d95ab8df9157828ab6e7e5b2fa573b7bb3
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/GridRowModels.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * A list of {@link GridRowModel} together with metadata about custom columns.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridRowModels<T> extends ArrayList<GridRowModel<T>> implements IsSerializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Metadata of available custom columns for all rows.
+     */
+    private List<GridCustomColumnInfo> customColumnsMetadata;
+
+    public GridRowModels(List<GridCustomColumnInfo> customColumnsMetadata)
+    {
+        this.customColumnsMetadata = customColumnsMetadata;
+    }
+
+    public GridRowModels(List<GridRowModel<T>> list, List<GridCustomColumnInfo> customColumnsMetadata)
+    {
+        super(list);
+        this.customColumnsMetadata = customColumnsMetadata;
+    }
+
+    /** Used when items are not displayed in a grid (usually we need the values for comboboxes */
+    // TODO 2009-10-08, Tomasz Pylak: this method is a source of many anti-patterns where the
+    // existance of server cache is simply forgotten and cache is never cleared.
+    // Possible solution is to add an
+    // option to a {@link IResultSetConfig} not to use cache when it will not be used.
+    public List<T> extractOriginalObjects()
+    {
+        List<T> result = new ArrayList<T>();
+        for (GridRowModel<T> item : this)
+        {
+            result.add(item.getOriginalObject());
+        }
+        return result;
+    }
+
+    public List<GridCustomColumnInfo> getCustomColumnsMetadata()
+    {
+        return customColumnsMetadata;
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private GridRowModels()
+    {
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private void setCustomColumnsMetadata(List<GridCustomColumnInfo> customColumnsMetadata)
+    {
+        this.customColumnsMetadata = customColumnsMetadata;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java
index ab8715e58ac93afc8f3f4f562621150bec6192c0..b97b3c22503566a93e79db2305c4b0e29ee45b0f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java
@@ -48,9 +48,9 @@ public interface IResultSetConfig<K, T> extends IResultSetKeyHolder<K>
      */
     public int getLimit();
 
-    /** Returns all columns available. Needed for customised filters. */
+    /** Returns all non-custom columns available. Needed for customized filters and columns. */
     public Set<IColumnDefinition<T>> getAvailableColumns();
-    
+
     /**
      * Returns the sort info.
      */
@@ -60,8 +60,14 @@ public interface IResultSetConfig<K, T> extends IResultSetKeyHolder<K>
     public List<GridFilterInfo<T>> getFilterInfos();
 
     /**
-     * Returns custom filter info.
+     * The custom filter which should be applied for the result. If not null the standard filter is
+     * not used.
      */
     public CustomFilterInfo<T> tryGetCustomFilterInfo();
 
+    /**
+     * @return grid id which can be used to figure out what are the available custom columns and how
+     *         to compute them.
+     */
+    public String tryGetGridDisplayId();
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSet.java
index dee8064332432c62557e73facd264e8b3cc05dbc..e3ee74c693eb1ed38ecd7815b9499cd41d3ae4c8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSet.java
@@ -16,8 +16,6 @@
 
 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.server.resultset.IResultSet;
@@ -32,13 +30,13 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IResultSet;
  */
 public final class ResultSet<T> implements IsSerializable
 {
-    private List<T> list;
+    private GridRowModels<T> list;
 
     private int totalLength;
 
     private String resultSetKey;
 
-    public final void setList(final List<T> result)
+    public final void setList(final GridRowModels<T> result)
     {
         this.list = result;
     }
@@ -64,7 +62,7 @@ public final class ResultSet<T> implements IsSerializable
     /**
      * Returns the list produced by a given {@link IResultSetConfig}.
      */
-    public List<T> getList()
+    public GridRowModels<T> getList()
     {
         return list;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java
index ae00d36252f622b0ab5ec64ee33a2fef1f5a49f7..72bb5035e5409b73e1ad59cefb16ff1a0dec8a08 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
@@ -45,8 +46,17 @@ public class TableExportCriteria<T/* exported entity */> implements IResultSetKe
     // which columns should be exported
     private List<IColumnDefinition<T>> columnDefs;
 
+    // all available columns in the grid which is exported. Used to calculate expressions in
+    // custom filters and columns.
+    private Set<IColumnDefinition<T>> availableColumns;
+
     private CustomFilterInfo<T> customFilterInfo;
 
+    // This field would be used only if the exported data could not be found in the
+    // cache and custom columns would have to be computed. In fact it should be always a case that
+    // data are in a cache.
+    private String gridDisplayId;
+
     // GWT only
     public TableExportCriteria()
     {
@@ -54,13 +64,16 @@ public class TableExportCriteria<T/* exported entity */> implements IResultSetKe
 
     public TableExportCriteria(String resultSetKey, SortInfo<T> sortInfo,
             List<GridFilterInfo<T>> filterInfos, List<IColumnDefinition<T>> columnDefs,
-            CustomFilterInfo<T> customFilterInfo)
+            Set<IColumnDefinition<T>> availableColumns, CustomFilterInfo<T> customFilterInfo,
+            String gridDisplayId)
     {
         this.resultSetKey = resultSetKey;
         this.sortInfo = sortInfo;
         this.filterInfos = filterInfos;
         this.columnDefs = columnDefs;
+        this.availableColumns = availableColumns;
         this.customFilterInfo = customFilterInfo;
+        this.gridDisplayId = gridDisplayId;
     }
 
     public String getResultSetKey()
@@ -87,4 +100,19 @@ public class TableExportCriteria<T/* exported entity */> implements IResultSetKe
     {
         return customFilterInfo;
     }
+
+    public Set<IColumnDefinition<T>> getAvailableColumns()
+    {
+        return availableColumns;
+    }
+
+    public void setGridDisplayId(String gridDisplayId)
+    {
+        this.gridDisplayId = gridDisplayId;
+    }
+
+    public String getGridDisplayId()
+    {
+        return gridDisplayId;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java
index f641e3bc4989d5d52bc5a8645d75f92bed722b80..5532f13714aed4bb1e1816581b946a891e2c6bcb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.generic.client.web.server;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import javax.annotation.Resource;
@@ -45,6 +46,7 @@ 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.resultset.CacheManager.TokenBasedResultSetKeyGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CachedResultSetManager.ICustomColumnsProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.server.translator.ResultSetTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.translator.UserFailureExceptionTranslator;
 import ch.systemsx.cisd.openbis.generic.server.SessionConstants;
@@ -54,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 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.DisplaySettings;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 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.Session;
@@ -119,7 +122,8 @@ public abstract class AbstractClientService implements IClientService
     {
         final IResultSetManager<String> resultSetManager = getResultSetManager();
         final IResultSet<String, T> result =
-                resultSetManager.getResultSet(resultSetConfig, dummyDataProvider);
+                resultSetManager
+                        .getResultSet(getSessionToken(), resultSetConfig, dummyDataProvider);
         return result;
     }
 
@@ -130,7 +134,7 @@ public abstract class AbstractClientService implements IClientService
         criteria.setResultSetKey(resultSetKey);
         final IResultSet<String, T> allData = getResultSet(criteria, dataProvider);
         Set<BasicEntityType> result = new HashSet<BasicEntityType>();
-        for (T row : allData.getList())
+        for (T row : allData.getList().extractOriginalObjects())
         {
             result.add(row.getEntityType());
         }
@@ -252,7 +256,15 @@ public abstract class AbstractClientService implements IClientService
 
     private CachedResultSetManager<String> createCachedResultSetManager()
     {
-        return new CachedResultSetManager<String>(new TokenBasedResultSetKeyGenerator());
+        return new CachedResultSetManager<String>(new TokenBasedResultSetKeyGenerator(),
+                new ICustomColumnsProvider()
+                    {
+                        public List<GridCustomColumn> getGridCustomColumn(String sessionToken,
+                                String gridDisplayId)
+                        {
+                            return getServer().listGridCustomColumns(sessionToken, gridDisplayId);
+                        }
+                    });
     }
 
     /** Returns the {@link IServer} implementation for this client service. */
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 5fb62638db08b1338c769519c7bade9f75a1d031..0eca38bd62732b5f0c2fd97336dd85f860591ea9 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
@@ -48,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DataSetUploadParam
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedDatasetCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedIdHolderCriteria;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 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.ListMaterialCriteria;
@@ -70,7 +71,6 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.translator.UserFailure
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.TSVRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 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.IDataStoreBaseURLProvider;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
@@ -187,7 +187,8 @@ public final class CommonClientService extends AbstractClientService implements
         return exportCriteria;
     }
 
-    private final <T> List<T> fetchCachedEntities(final TableExportCriteria<T> exportCriteria)
+    private final <T> GridRowModels<T> fetchCachedEntities(
+            final TableExportCriteria<T> exportCriteria)
     {
         IResultSetConfig<String, T> resultSetConfig = createExportListCriteria(exportCriteria);
         IOriginalDataProvider<T> dummyDataProvider = createDummyDataProvider();
@@ -215,8 +216,8 @@ public final class CommonClientService extends AbstractClientService implements
         criteria.setFilterInfos(exportCriteria.getFilterInfos());
         criteria.setResultSetKey(exportCriteria.getResultSetKey());
         criteria.setCustomFilterInfo(exportCriteria.tryGetCustomFilterInfo());
-        criteria.setAvailableColumns(new HashSet<IColumnDefinition<T>>(exportCriteria
-                .getColumnDefs()));
+        criteria.setAvailableColumns(exportCriteria.getAvailableColumns());
+        criteria.setGridDisplayId(exportCriteria.getGridDisplayId());
         return criteria;
     }
 
@@ -238,7 +239,7 @@ public final class CommonClientService extends AbstractClientService implements
             // Not directly needed but this refreshes the session.
             getSessionToken();
             final TableExportCriteria<T> exportCriteria = getAndRemoveExportCriteria(exportDataKey);
-            final List<T> entities = fetchCachedEntities(exportCriteria);
+            final GridRowModels<T> entities = fetchCachedEntities(exportCriteria);
             return TSVRenderer.createTable(entities, exportCriteria.getColumnDefs(), lineSeparator);
         } catch (final UserFailureException e)
         {
@@ -538,7 +539,7 @@ public final class CommonClientService extends AbstractClientService implements
             TableExportCriteria<? extends IEntityInformationHolder> displayedEntitiesCriteria =
                     criteria.tryGetDisplayedEntities();
             assert displayedEntitiesCriteria != null : "displayedEntitiesCriteria is null";
-            entities = fetchCachedEntities(displayedEntitiesCriteria);
+            entities = fetchCachedEntities(displayedEntitiesCriteria).extractOriginalObjects();
         }
         return new DataSetRelatedEntities(entities);
     }
@@ -1975,7 +1976,8 @@ public final class CommonClientService extends AbstractClientService implements
             TableExportCriteria<ExternalData> displayedItemsCriteria =
                     displayedOrSelectedDatasetCriteria.tryGetDisplayedItems();
             assert displayedItemsCriteria != null : "displayedItemsCriteria is null";
-            List<ExternalData> datasets = fetchCachedEntities(displayedItemsCriteria);
+            List<ExternalData> datasets =
+                    fetchCachedEntities(displayedItemsCriteria).extractOriginalObjects();
             if (serviceDescriptionOrNull != null)
             {
                 datasets = filterDatasets(datasets, serviceDescriptionOrNull);
@@ -2135,7 +2137,7 @@ public final class CommonClientService extends AbstractClientService implements
             TableExportCriteria<T> displayedItemsCriteria =
                     displayedOrSelectedEntitiesCriteria.tryGetDisplayedItems();
             assert displayedItemsCriteria != null : "displayedItemsCriteria is null";
-            List<T> entities = fetchCachedEntities(displayedItemsCriteria);
+            List<T> entities = fetchCachedEntities(displayedItemsCriteria).extractOriginalObjects();
             return TechId.createList(entities);
         }
     }
@@ -2213,7 +2215,7 @@ public final class CommonClientService extends AbstractClientService implements
 
     // -- grid custom columns
 
-    public List<GridCustomColumn> listColumns(String gridId)
+    public List<GridCustomColumn> listGridCustomColumns(String gridId)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         try
@@ -2225,7 +2227,7 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
-    public ResultSet<GridCustomColumn> listColumns(final String gridId,
+    public ResultSet<GridCustomColumn> listGridCustomColumns(final String gridId,
             DefaultResultSetConfig<String, GridCustomColumn> resultSetConfig)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
@@ -2233,7 +2235,7 @@ public final class CommonClientService extends AbstractClientService implements
             {
                 public List<GridCustomColumn> getOriginalData() throws UserFailureException
                 {
-                    return listColumns(gridId);
+                    return listGridCustomColumns(gridId);
                 }
             });
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnDefinition.java
index 6a136c67b5ba1a320ad4c9d1a44e263d303c5e81..9e41640f0160526de088571786058360d3c1d0a0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnDefinition.java
@@ -25,7 +25,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
  * 
  * @author Franz-Josef Elmer
  */
-public class ColumnDefinition
+class ColumnDefinition
 {
     private final IColumnDefinition<?> definition;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnGroup.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnGroup.java
index ace1228476225c2b767c59c3de6606c6a07eee10..01f6832676e8c2d70674f16dfa0a5b513a9ddc05 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnGroup.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/ColumnGroup.java
@@ -26,7 +26,7 @@ import java.util.List;
  *
  * @author Franz-Josef Elmer
  */
-public class ColumnGroup
+class ColumnGroup
 {
     private final String propertyValue;
     private final List<Object> values;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..b00f5e97651cdea2da24cb6fc78bbe1661c47fe6
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.server.calculator;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.common.evaluator.EvaluatorException;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
+import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
+
+/**
+ * Utility class containing functions helpful with dealing with grid custom filters or columns.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class GridExpressionUtils
+{
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, GridExpressionUtils.class);
+
+    private static final String FILTER_EVALUATION_ERROR_MSG =
+            "Problem occured during applying the filter.<br><br>Check that all provided parameter values are correct. "
+                    + "If everything seems fine contact filter registrator or instance admin about a possible bug in the filter definition.";
+
+    private static final String EVALUATION_SERIOUS_ERROR_MSG = "Serious problem occured during ";
+
+    private static final String FILTER_EVALUATION_SERIOUS_ERROR_MSG =
+            EVALUATION_SERIOUS_ERROR_MSG + "applying the filter: ";
+
+    private static final String COLUMN_EVALUATION_SERIOUS_ERROR_TEMPLATE =
+            "Error: calculating the value of a custom column '%s' failed, conntact you administrator: ";
+
+    private static final String COLUMN_EVALUATION_ERROR_TEMPLATE =
+            COLUMN_EVALUATION_SERIOUS_ERROR_TEMPLATE + "invalid column definition. ";
+
+    /**
+     * Applies the filter described by <code>customFilterInfo</code> to
+     * <code>allRows<code> and returns the result.
+     */
+    public static <T> GridRowModels<T> applyCustomFilter(final GridRowModels<T> rows,
+            Set<IColumnDefinition<T>> availableColumns, CustomFilterInfo<T> customFilterInfo)
+    {
+        GridRowModels<T> filtered = new GridRowModels<T>(rows.getCustomColumnsMetadata());
+        String expression = StringEscapeUtils.unescapeHtml(customFilterInfo.getExpression());
+        Set<ParameterWithValue> parameters = customFilterInfo.getParameters();
+        try
+        {
+            RowCalculator<T> calculator =
+                    new RowCalculator<T>(availableColumns, expression, parameters);
+            for (GridRowModel<T> rowData : rows)
+            {
+                calculator.setRowData(rowData);
+                if (calculator.evalToBoolean())
+                {
+                    filtered.add(rowData);
+                }
+            }
+        } catch (Exception ex)
+        {
+            throw createInvalidFilterException(ex);
+        }
+        return filtered;
+    }
+
+    private static UserFailureException createInvalidFilterException(Exception ex)
+    {
+        String msg;
+        String details = null;
+        if (ex instanceof EvaluatorException)
+        {
+            msg = FILTER_EVALUATION_ERROR_MSG;
+            details = ex.getMessage();
+        } else
+        {
+            msg = FILTER_EVALUATION_SERIOUS_ERROR_MSG + ex;
+        }
+        logColumnCalculationError(ex, msg, details);
+        return new UserFailureException(msg, details);
+    }
+
+    public static <T> GridRowModels<T> evalCustomColumns(final List<T> allRows,
+            List<GridCustomColumn> customColumns, Set<IColumnDefinition<T>> availableColumns)
+    {
+        GridRowModels<T> result = new GridRowModels<T>(extractColumnInfos(customColumns));
+        for (T rowData : allRows)
+        {
+            HashMap<String, String> customColumnValues = new HashMap<String, String>();
+            for (GridCustomColumn customColumn : customColumns)
+            {
+                String columnId = customColumn.getCode();
+                String value = evalCustomColumn(rowData, customColumn, availableColumns);
+                customColumnValues.put(columnId, value);
+            }
+            result.add(new GridRowModel<T>(rowData, customColumnValues));
+        }
+        return result;
+    }
+
+    private static List<GridCustomColumnInfo> extractColumnInfos(List<GridCustomColumn> customColumns)
+    {
+        List<GridCustomColumnInfo> result = new ArrayList<GridCustomColumnInfo>();
+        for (GridCustomColumn column : customColumns)
+        {
+            GridCustomColumnInfo columnInfo =
+                    new GridCustomColumnInfo(column.getCode(), column.getName(), column
+                            .getDescription());
+            result.add(columnInfo);
+        }
+        return result;
+    }
+
+    private static <T> String evalCustomColumn(T rowData, GridCustomColumn customColumn,
+            Set<IColumnDefinition<T>> availableColumns)
+    {
+        String expression = StringEscapeUtils.unescapeHtml(customColumn.getExpression());
+        // NOTE: we do not allow a calculated column to reference other calculated columns. It's
+        // a simplest way to ensure that there are no cyclic dependencies between custom
+        // columns. To allow custom columns dependencies we would have to ensure that
+        // dependencies create a DAG. Then the columns should be evaluated in a topological
+        // order.
+        GridRowModel<T> rowDataWithEmptyCustomColumns =
+                new GridRowModel<T>(rowData, new HashMap<String, String>());
+        try
+        {
+            RowCalculator<T> calculator =
+                    new RowCalculator<T>(availableColumns, expression,
+                            new HashSet<ParameterWithValue>());
+            calculator.setRowData(rowDataWithEmptyCustomColumns);
+            return calculator.evalAsString();
+        } catch (Exception ex)
+        {
+            return createCustomColumnErrorMessage(customColumn, ex);
+        }
+    }
+
+    private static String createCustomColumnErrorMessage(GridCustomColumn customColumn, Exception ex)
+    {
+        String msg;
+        String details = null;
+        String columnDesc = customColumn.getName() + " (" + customColumn.getCode() + ")";
+        if (ex instanceof EvaluatorException)
+        {
+            msg = String.format(COLUMN_EVALUATION_ERROR_TEMPLATE, columnDesc);
+            details = ex.getMessage();
+        } else
+        {
+            msg = String.format(COLUMN_EVALUATION_SERIOUS_ERROR_TEMPLATE, columnDesc) + ex;
+        }
+        return msg + " DETAILS: " + details;
+    }
+
+    private static void logColumnCalculationError(Exception ex, String msg, String details)
+    {
+        if (operationLog.isInfoEnabled())
+        {
+            // we do not log this as an error, because it can be only user fault (wrong column
+            // definition)
+            operationLog.info(msg + " DETAILS: " + details, ex);
+        }
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/Row.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/Row.java
index 78e51adfe6bce8451a8c1a63c8d1307cc128efb3..879a4b06ce2c50e7c95a5f84f2b0075be1a00fe6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/Row.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/Row.java
@@ -25,23 +25,27 @@ import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
 /**
- * Row object used in jython expressions to access column values. 
+ * Row object used in jython expressions to access column values.
  * <p>
  * All public methods of this class are part of the Filter/Calculated Column API.
- *
+ * 
  * @author Franz-Josef Elmer
  */
-public final class Row<T>
+final class Row<T>
 {
-    
-    private final Map<String, IColumnDefinition<T>> definitionsByID = new LinkedHashMap<String, IColumnDefinition<T>>();
-    private final Map<String, List<ColumnDefinition>> definitionsByProperties = new HashMap<String, List<ColumnDefinition>>();
-    
-    private T row;
-    
+
+    private final Map<String, IColumnDefinition<T>> definitionsByID =
+            new LinkedHashMap<String, IColumnDefinition<T>>();
+
+    private final Map<String, List<ColumnDefinition>> definitionsByProperties =
+            new HashMap<String, List<ColumnDefinition>>();
+
+    private GridRowModel<T> row;
+
     Row(Set<IColumnDefinition<T>> availableColumns)
     {
         for (IColumnDefinition<T> columnDefinition : availableColumns)
@@ -49,8 +53,8 @@ public final class Row<T>
             definitionsByID.put(columnDefinition.getIdentifier(), columnDefinition);
         }
     }
-    
-    void setRowData(T row)
+
+    void setRowData(GridRowModel<T> row)
     {
         this.row = row;
     }
@@ -67,6 +71,7 @@ public final class Row<T>
         {
             throw new IllegalArgumentException("Undefined column: " + columnID);
         }
+
         return columnDefinition.getComparableValue(row);
     }
 
@@ -87,7 +92,8 @@ public final class Row<T>
             for (Entry<String, IColumnDefinition<T>> entry : entries)
             {
                 IColumnDefinition<T> columnDefinition = entry.getValue();
-                if (propertyKeyOrNull == null || columnDefinition.tryToGetProperty(propertyKeyOrNull) != null)
+                if (propertyKeyOrNull == null
+                        || columnDefinition.tryToGetProperty(propertyKeyOrNull) != null)
                 {
                     definitions.add(new ColumnDefinition(columnDefinition));
                 }
@@ -117,7 +123,7 @@ public final class Row<T>
         }
         return Collections.unmodifiableList(values);
     }
-    
+
     /**
      * Returns all column values grouped by the property value of the property specified by the key.
      * 
@@ -146,5 +152,5 @@ public final class Row<T>
         }
         return Collections.unmodifiableList(groups);
     }
-    
+
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java
index e5212ad662d0e502a98ceaec476c913c3a6ff205..c4abae0d4e8f1f0e43fe099839e234ce7f0f3366 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java
@@ -23,21 +23,18 @@ import java.util.regex.Pattern;
 
 import ch.systemsx.cisd.common.evaluator.Evaluator;
 import ch.systemsx.cisd.common.evaluator.EvaluatorException;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
-public class RowCalculator<T>
+class RowCalculator<T>
 {
     private static final String INITIAL_SCRIPT =
             "from " + StandardFunctions.class.getCanonicalName() + " import *\n"
-            + "def int(x):return toInt(x)\n"
-            + "def float(x):return toFloat(x)\n"
-            ;
+                    + "def int(x):return toInt(x)\n" + "def float(x):return toFloat(x)\n";
 
     private final Evaluator evaluator;
 
@@ -46,27 +43,28 @@ public class RowCalculator<T>
     public RowCalculator(Set<IColumnDefinition<T>> availableColumns, String expression,
             Set<ParameterWithValue> parameters)
     {
-        evaluator = new Evaluator(substitudeParameters(expression, parameters), Math.class,
-                INITIAL_SCRIPT);
+        evaluator =
+                new Evaluator(substitudeParameters(expression, parameters), Math.class,
+                        INITIAL_SCRIPT);
         row = new Row<T>(availableColumns);
         evaluator.set("row", row);
     }
-    
-    public void setRowData(T rowData)
+
+    public void setRowData(GridRowModel<T> rowData)
     {
         row.setRowData(rowData);
     }
-    
+
     public boolean evalToBoolean() throws EvaluatorException
     {
         return evaluator.evalToBoolean();
     }
-    
+
     public int evalToInt() throws EvaluatorException
     {
         return evaluator.evalToInt();
     }
-    
+
     public BigInteger evalToBigInt() throws EvaluatorException
     {
         return evaluator.evalToBigInt();
@@ -81,8 +79,9 @@ public class RowCalculator<T>
     {
         return evaluator.evalAsString();
     }
-    
-    private String substitudeParameters(String originalExpression, Set<ParameterWithValue> parameters)
+
+    private String substitudeParameters(String originalExpression,
+            Set<ParameterWithValue> parameters)
     {
         String expression = originalExpression;
         for (ParameterWithValue pw : parameters)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/StandardFunctions.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/StandardFunctions.java
index 5bd998bff61828f2e6ba280d30721968c09e98f9..2293c67e012a196f56de2170b9cac2a51c78e53b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/StandardFunctions.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/StandardFunctions.java
@@ -29,7 +29,7 @@ import org.apache.commons.lang.StringUtils;
  *
  * @author Franz-Josef Elmer
  */
-public final class StandardFunctions
+final class StandardFunctions
 {
     static final Double DOUBLE_DEFAULT_VALUE = new Double(-Double.MAX_VALUE);
     static final Integer INTEGER_DEFAULT_VALUE = new Integer(Integer.MIN_VALUE);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java
index ac66a01e4d826e605e170c6f891727d320213917..c16d29b7cec415069a1394e77c85759ce9bc31ce 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java
@@ -31,14 +31,15 @@ import org.apache.commons.lang.text.StrTokenizer;
 import org.apache.log4j.Logger;
 
 import ch.rinn.restrictions.Private;
-import ch.systemsx.cisd.common.evaluator.EvaluatorException;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
-import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException;
-import ch.systemsx.cisd.openbis.generic.client.web.server.util.FilterUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.server.calculator.GridExpressionUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridFilterInfo;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SortInfo;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SortInfo.SortDir;
@@ -56,27 +57,30 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
     private static final Logger operationLog =
             LogFactory.getLogger(LogCategory.OPERATION, CachedResultSetManager.class);
 
-    private static final String FILTER_EVALUATION_ERROR_MSG =
-            "Problem occured during applying the filter.<br><br>Check that all provided parameter values are correct. "
-                    + "If everything seems fine contact filter registrator or instance admin about a possible bug in the filter definition.";
-
-    private static final String FILTER_EVALUATION_SERIOUS_ERROR_MSG =
-            "Serious problem occured during applying the filter: ";
-
     private final IResultSetKeyGenerator<K> resultSetKeyProvider;
 
+    private final ICustomColumnsProvider customColumnsProvider;
+
     @Private
     final Map<K, List<?>> results = new HashMap<K, List<?>>();
 
-    public CachedResultSetManager(final IResultSetKeyGenerator<K> resultSetKeyProvider)
+    public interface ICustomColumnsProvider
+    {
+        // used to fetch grid custom columns definition for the specified grid id
+        List<GridCustomColumn> getGridCustomColumn(String sessionToken, String gridDisplayId);
+    }
+
+    public CachedResultSetManager(final IResultSetKeyGenerator<K> resultSetKeyProvider,
+            ICustomColumnsProvider customColumnsProvider)
     {
         this.resultSetKeyProvider = resultSetKeyProvider;
+        this.customColumnsProvider = customColumnsProvider;
     }
 
     @SuppressWarnings("unchecked")
-    private final <T> List<T> cast(final List<?> list)
+    private final <T> T cast(final Object object)
     {
-        return (List<T>) list;
+        return (T) object;
     }
 
     /**
@@ -118,58 +122,49 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         }
     }
 
-    private static final <T> List<T> filterData(final List<T> rows,
+    private static final <T> GridRowModels<T> filterData(final GridRowModels<T> rows,
             Set<IColumnDefinition<T>> availableColumns, final List<GridFilterInfo<T>> filterInfos,
             CustomFilterInfo<T> customFilterInfo)
     {
-        List<T> filtered = new ArrayList<T>();
         if (customFilterInfo != null)
         {
-            try
-            {
-                FilterUtils.applyCustomFilter(rows, availableColumns, customFilterInfo, filtered);
-            } catch (Exception ex)
-            {
-                String msg;
-                String details = null;
-                if (ex instanceof EvaluatorException)
-                {
-                    msg = FILTER_EVALUATION_ERROR_MSG;
-                    details = ex.getMessage();
-                } else
-                {
-                    msg = FILTER_EVALUATION_SERIOUS_ERROR_MSG + ex;
-                }
-                if (operationLog.isInfoEnabled())
-                {
-                    operationLog.info(msg + " DETAILS: " + details, ex);
-                }
-                throw new UserFailureException(msg, details);
-            }
+            return GridExpressionUtils.applyCustomFilter(rows, availableColumns, customFilterInfo);
         } else
         {
-            List<FilterInfo<T>> serverFilterInfos =
-                    new ArrayList<FilterInfo<T>>(filterInfos.size());
-            for (GridFilterInfo<T> info : filterInfos)
-            {
-                serverFilterInfos.add(FilterInfo.create(info));
+            return applyStandardColumnFilter(rows, filterInfos);
+        }
+    }
 
-            }
-            for (T row : rows)
+    private static <T> GridRowModels<T> applyStandardColumnFilter(final GridRowModels<T> rows,
+            final List<GridFilterInfo<T>> filterInfos)
+    {
+        GridRowModels<T> filtered = new GridRowModels<T>(rows.getCustomColumnsMetadata());
+        List<FilterInfo<T>> serverFilterInfos = processFilters(filterInfos);
+        for (GridRowModel<T> row : rows)
+        {
+            if (isMatching(row, serverFilterInfos))
             {
-                if (isMatching(row, serverFilterInfos))
-                {
-                    filtered.add(row);
-                }
+                filtered.add(row);
             }
         }
         return filtered;
     }
 
+    private static <T> List<FilterInfo<T>> processFilters(final List<GridFilterInfo<T>> filterInfos)
+    {
+        List<FilterInfo<T>> serverFilterInfos = new ArrayList<FilterInfo<T>>(filterInfos.size());
+        for (GridFilterInfo<T> info : filterInfos)
+        {
+            serverFilterInfos.add(FilterInfo.create(info));
+        }
+        return serverFilterInfos;
+    }
+
     // returns true if a row matches all the filters
-    private static final <T> boolean isMatching(final T row, final List<FilterInfo<T>> filterInfos)
+    private static final <T> boolean isMatching(final GridRowModel<T> row,
+            final List<FilterInfo<T>> serverFilterInfos)
     {
-        for (FilterInfo<T> filter : filterInfos)
+        for (FilterInfo<T> filter : serverFilterInfos)
         {
             if (isMatching(row, filter) == false)
             {
@@ -179,7 +174,8 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         return true;
     }
 
-    private static final <T> boolean isMatching(final T row, final FilterInfo<T> filterInfo)
+    private static final <T> boolean isMatching(final GridRowModel<T> row,
+            final FilterInfo<T> filterInfo)
     {
         IColumnDefinition<T> filteredField = filterInfo.getFilteredField();
         String value = filteredField.getValue(row).toLowerCase();
@@ -198,7 +194,7 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         return false;
     }
 
-    private final <T> void sortData(final List<T> data, final SortInfo<T> sortInfo)
+    private final <T> void sortData(final GridRowModels<T> data, final SortInfo<T> sortInfo)
     {
         assert data != null : "Unspecified data.";
         assert sortInfo != null : "Unspecified sort information.";
@@ -212,18 +208,18 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         {
             return;
         }
-        Comparator<T> comparator = createComparator(sortDir, sortField);
+        Comparator<GridRowModel<T>> comparator = createComparator(sortDir, sortField);
         Collections.sort(data, comparator);
     }
 
-    private static <T> Comparator<T> createComparator(final SortDir sortDir,
+    private static <T> Comparator<GridRowModel<T>> createComparator(final SortDir sortDir,
             final IColumnDefinition<T> sortField)
     {
-        Comparator<T> comparator = new Comparator<T>()
+        Comparator<GridRowModel<T>> comparator = new Comparator<GridRowModel<T>>()
             {
 
                 @SuppressWarnings("unchecked")
-                public int compare(T o1, T o2)
+                public int compare(GridRowModel<T> o1, GridRowModel<T> o2)
                 {
                     Comparable v1 = sortField.getComparableValue(o1);
                     Comparable v2 = sortField.getComparableValue(o2);
@@ -271,28 +267,30 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
      * Encapsulates list returned by {@link List#subList(int, int)} in a new <code>List</code> as
      * <i>GWT</i> complains because of a serialization concern.
      */
-    private final static <T> List<T> subList(final List<T> data, final int offset, final int limit)
+    private final static <T> GridRowModels<T> subList(final GridRowModels<T> data,
+            final int offset, final int limit)
     {
         final int toIndex = offset + limit;
-        return new ArrayList<T>(data.subList(offset, toIndex));
+        return new GridRowModels<T>(data.subList(offset, toIndex), data.getCustomColumnsMetadata());
     }
 
     //
     // IDataManager
     //
 
-    public final synchronized <T> IResultSet<K, T> getResultSet(
+    public final synchronized <T> IResultSet<K, T> getResultSet(final String sessionToken,
             final IResultSetConfig<K, T> resultConfig, final IOriginalDataProvider<T> dataProvider)
     {
         assert resultConfig != null : "Unspecified result configuration";
         assert dataProvider != null : "Unspecified data retriever";
-        List<T> data;
+        GridRowModels<T> data;
         K dataKey = resultConfig.getResultSetKey();
         if (dataKey == null)
         {
             debug("Unknown result set key: retrieving the data.");
             dataKey = resultSetKeyProvider.createKey();
-            data = dataProvider.getOriginalData();
+            List<T> rows = dataProvider.getOriginalData();
+            data = calculateCustomColumns(sessionToken, rows, resultConfig);
             results.put(dataKey, data);
         } else
         {
@@ -312,10 +310,26 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         final int limit = getLimit(size, resultConfig.getLimit(), offset);
         final SortInfo<T> sortInfo = resultConfig.getSortInfo();
         sortData(data, sortInfo);
-        final List<T> list = subList(data, offset, limit);
+        final GridRowModels<T> list = subList(data, offset, limit);
         return new DefaultResultSet<K, T>(dataKey, list, size);
     }
 
+    private <T> GridRowModels<T> calculateCustomColumns(String sessionToken, List<T> rows,
+            IResultSetConfig<?, T> resultConfig)
+    {
+        String gridId = resultConfig.tryGetGridDisplayId();
+        List<GridCustomColumn> customColumns;
+        if (gridId == null)
+        {
+            customColumns = new ArrayList<GridCustomColumn>();
+        } else
+        {
+            customColumns = customColumnsProvider.getGridCustomColumn(sessionToken, gridId);
+        }
+        return GridExpressionUtils.evalCustomColumns(rows, customColumns, resultConfig
+                .getAvailableColumns());
+    }
+
     public final synchronized void removeResultSet(final K resultSetKey)
     {
         assert resultSetKey != null : "Unspecified data key holder.";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/DefaultResultSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/DefaultResultSet.java
index 1bf05c3c7569f4c72414834d0dfabd5919fd9016..b5b0a200badf553d4092ab8fe874b0d8210cdd57 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/DefaultResultSet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/DefaultResultSet.java
@@ -16,7 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
-import java.util.List;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 
 /**
  * A default {@link IResultSet} implementation.
@@ -27,11 +27,11 @@ public final class DefaultResultSet<K, T> implements IResultSet<K, T>
 {
     private final K resultSetKey;
 
-    private final List<T> list;
+    private final GridRowModels<T> list;
 
     private final int totalLength;
 
-    public DefaultResultSet(final K resultSetKey, final List<T> list, final int totalLength)
+    public DefaultResultSet(final K resultSetKey, final GridRowModels<T> list, final int totalLength)
     {
         assert resultSetKey != null : "Unspecified result set key";
         assert list != null : "Unspecified list.";
@@ -50,7 +50,7 @@ public final class DefaultResultSet<K, T> implements IResultSet<K, T>
         return resultSetKey;
     }
 
-    public final List<T> getList()
+    public final GridRowModels<T> getList()
     {
         return list;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java
index 040277ce20491a68dddefb3a41431d8182997fed..bd6668553c3e0e744fc6b35d63800501f2c5f18e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java
@@ -16,8 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
-import java.util.List;
-
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetKeyHolder;
 
@@ -31,7 +30,7 @@ public interface IResultSet<K, T> extends IResultSetKeyHolder<K>
     /**
      * Returns the list produced by a given {@link IResultSetConfig}.
      */
-    public List<T> getList();
+    public GridRowModels<T> getList();
 
     /**
      * Returns the total count.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSetManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSetManager.java
index bbab868cdb9747385a08c6b02eb1687fb7eaf9db..f3e36314bb62ddc10613521a5721f3f893a0799c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSetManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSetManager.java
@@ -28,14 +28,16 @@ public interface IResultSetManager<K>
 {
 
     /**
-     * Produces a {@link IResultSet} from given <var>resultConfig</var> and given <var>dataProvider</var>.
+     * Produces a {@link IResultSet} from given <var>resultConfig</var> and given
+     * <var>dataProvider</var>.
      * <p>
      * In case of cached data, the {@link IOriginalDataProvider} implementation is only used in the
      * first call, when the full data are not already there.
      * </p>
      */
-    public <T> IResultSet<K, T> getResultSet(final IResultSetConfig<K, T> resultConfig,
-            final IOriginalDataProvider<T> dataProvider) throws UserFailureException;
+    public <T> IResultSet<K, T> getResultSet(final String sessionToken,
+            final IResultSetConfig<K, T> resultConfig, final IOriginalDataProvider<T> dataProvider)
+            throws UserFailureException;
 
     /**
      * Remove the data mapped to given <var>resultSetKey</var>.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtils.java
deleted file mode 100644
index a12809a47ccd7588fa9cd68e2c5543b08e26c1a4..0000000000000000000000000000000000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtils.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2009 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.generic.client.web.server.util;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang.StringEscapeUtils;
-
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
-import ch.systemsx.cisd.openbis.generic.client.web.server.calculator.RowCalculator;
-import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
-
-/**
- * Utility class containing functions helpful with dealing with filters.
- * 
- * @author Izabela Adamczyk
- */
-public class FilterUtils
-{
-    /**
-     * Applies the filter described by <code>customFilterInfo</code> to
-     * <code>allRows<code> and adds the result to the
-     * <code>filterdRows<code>.
-     */
-    public static <T> void applyCustomFilter(final List<T> allRows,
-            Set<IColumnDefinition<T>> availableColumns, CustomFilterInfo<T> customFilterInfo,
-            List<T> filterdRows)
-    {
-        String expression = StringEscapeUtils.unescapeHtml(customFilterInfo.getExpression());
-        Set<ParameterWithValue> parameters = customFilterInfo.getParameters();
-        RowCalculator<T> calculator =
-                new RowCalculator<T>(availableColumns, expression, parameters);
-        for (T rowData : allRows)
-        {
-            calculator.setRowData(rowData);
-            if (calculator.evalToBoolean())
-            {
-                filterdRows.add(rowData);
-            }
-        }
-    }
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRenderer.java
index 88bd1c05c584eaaf8ad7f07fdc5cde39055c513b..d8e8d876eeb8c5abf967935021e49159ee066671 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRenderer.java
@@ -20,6 +20,8 @@ import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
 /**
@@ -35,23 +37,23 @@ public class TSVRenderer
 
     /**
      * @param entities list of entities which will be exported
-     * @param columnDefs column definitions. Each definition know column's header and is able to
-     *            extract an appropriate value from the entity.
+     * @param list column definitions. Each definition know column's header and is able to extract
+     *            an appropriate value from the entity.
      * @param lineSeparator character used as a lineSeparator separator
      */
-    public static <T> String createTable(List<T> entities, List<IColumnDefinition<T>> columnDefs,
-            String lineSeparator)
+    public static <T> String createTable(GridRowModels<T> entities,
+            List<IColumnDefinition<T>> list, String lineSeparator)
     {
-        return new TSVRenderer(lineSeparator).createTable(entities, columnDefs);
+        return new TSVRenderer(lineSeparator).createTable(entities, list);
     }
 
-    private <T> String createTable(List<T> entities, List<IColumnDefinition<T>> columnDefs)
+    private <T> String createTable(GridRowModels<T> entities, List<IColumnDefinition<T>> list)
     {
         StringBuffer sb = new StringBuffer();
-        appendHeader(columnDefs, sb);
-        for (T entity : entities)
+        appendHeader(list, sb);
+        for (GridRowModel<T> entity : entities)
         {
-            appendEntity(entity, columnDefs, sb);
+            appendEntity(entity, list, sb);
         }
         return sb.toString();
     }
@@ -61,10 +63,11 @@ public class TSVRenderer
         this.lineSeparator = lineSeparator;
     }
 
-    private <T> void appendEntity(T entity, List<IColumnDefinition<T>> columnDefs, StringBuffer sb)
+    private <T> void appendEntity(GridRowModel<T> entity, List<IColumnDefinition<T>> list,
+            StringBuffer sb)
     {
         boolean isFirst = true;
-        for (IColumnDefinition<T> column : columnDefs)
+        for (IColumnDefinition<T> column : list)
         {
             if (isFirst == false)
             {
@@ -73,7 +76,8 @@ public class TSVRenderer
             {
                 isFirst = false;
             }
-            sb.append(cleanWhitespaces(column.getValue(entity)));
+            String value = column.getValue(entity);
+            sb.append(cleanWhitespaces(value));
         }
         sb.append(lineSeparator);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
index 834b2fc751e5bc148e59eda97cc4549c8ba17413..02c531d92cf44ec86c8595b14c329e37d89c66f3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
@@ -39,7 +39,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IDataStoreBaseURLProvider;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSession;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
@@ -48,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleSession;
+import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomColumnTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 
 /**
@@ -304,4 +307,12 @@ public abstract class AbstractServer<T extends IServer> extends AbstractServiceW
         final Session session = getSessionManager().getSession(sessionToken);
         session.setBaseIndexURL(baseIndexURL);
     }
+
+    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId)
+    {
+        checkSession(sessionToken);
+        List<GridCustomColumnPE> columns =
+                getDAOFactory().getGridCustomColumnDAO().listColumns(gridId);
+        return GridCustomColumnTranslator.translate(columns);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServerLogger.java
index 84963b306d8ffe9f31d948e301b8c95525cfcbd3..92fbeea621c5cdded03f4e19462b131af84ddf17 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServerLogger.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.server;
 
+import java.util.List;
+
 import org.apache.log4j.Logger;
 
 import ch.systemsx.cisd.authentication.ISessionManager;
@@ -26,6 +28,7 @@ import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSession;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 
@@ -163,6 +166,12 @@ public abstract class AbstractServerLogger implements IServer
         logTracking(sessionToken, "change_user_home_group (%s)", groupId);
     }
 
+    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId)
+    {
+        logAccess(sessionToken, "listGridCustomColumns GRID_ID(%s)", gridId);
+        return null;
+    }
+
     public void setBaseIndexURL(String sessionToken, String baseURL)
     {
         logAccess(sessionToken, "set_base_url", "BASE_URL(%s)", baseURL);
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 023528a78f16ba1d360d3bc22f51b77bc681da70..b92e955c3e05c6459cdffd099f685fb0a197fbbd 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
@@ -92,7 +92,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
@@ -136,7 +135,6 @@ 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.FileFormatTypePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IEntityInformationHolderDTO;
@@ -175,7 +173,6 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.RoleAssignmentTranslat
 import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.TypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTermTranslator;
-import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomColumnTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomFilterTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
@@ -1797,20 +1794,6 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
 
     // -- columns
 
-    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId)
-    {
-        checkSession(sessionToken);
-        try
-        {
-            List<GridCustomColumnPE> columns =
-                    getDAOFactory().getGridCustomColumnDAO().listColumns(gridId);
-            return GridCustomColumnTranslator.translate(columns);
-        } catch (final DataAccessException ex)
-        {
-            throw createUserFailureException(ex);
-        }
-    }
-
     public void registerGridCustomColumn(String sessionToken, NewColumnOrFilter column)
     {
         IGridCustomFilterOrColumnBO bo = createGridCustomColumnBO(sessionToken);
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 755b253bede0957c47a44a06806e7f5532a2c1e5..6acf193c75d7d43b8ecda6ae686b175ba384bcf9 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
@@ -46,7 +46,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
@@ -777,12 +776,6 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
 
     // -- columns
 
-    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId)
-    {
-        logAccess(sessionToken, "listGridCustomColumns", "GRID(%s)", gridId);
-        return null;
-    }
-
     public void registerGridCustomColumn(String sessionToken, NewColumnOrFilter column)
     {
         logTracking(sessionToken, "registerGridCustomColumn", "COLUMN(%s)", column);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java
index a5c5a0101e92c665f01591b81d98a9f0c0bc1f85..f6981a5efd3b209663a661362c2e1badc6d40972 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java
@@ -16,12 +16,15 @@
 
 package ch.systemsx.cisd.openbis.generic.shared;
 
+import java.util.List;
+
 import org.springframework.transaction.annotation.Transactional;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.ISessionProvider;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 
@@ -52,7 +55,8 @@ public interface IServer extends ISessionProvider
     public Session tryToAuthenticate(final String user, final String password);
 
     /**
-     * Sets the base URL (including "index.html") that the web server is reachable at for this client.
+     * Sets the base URL (including "index.html") that the web server is reachable at for this
+     * client.
      */
     @Transactional
     public void setBaseIndexURL(String sessionToken, String baseIndexURL);
@@ -60,6 +64,12 @@ public interface IServer extends ISessionProvider
     @Transactional
     public void saveDisplaySettings(String sessionToken, DisplaySettings displaySettings);
 
+    /**
+     * Lists grid custom columns for a given grid id.
+     */
+    @Transactional
+    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridDisplayId);
+
     /** Changes logged user home group to the one with given technical id. */
     @Transactional
     public void changeUserHomeGroup(String sessionToken, TechId groupIdOrNull);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IColumnDefinition.java
index e4e44ea22f272e46de1512d67af543238c63af4c..e31d5a73b68fd7f926693a5a2bd1e36798676326 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IColumnDefinition.java
@@ -18,6 +18,8 @@ package ch.systemsx.cisd.openbis.generic.shared.basic;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+
 /**
  * Describes table column's metadata. Has the ability to render cell values for the column given the
  * row model.
@@ -27,16 +29,16 @@ import com.google.gwt.user.client.rpc.IsSerializable;
 public interface IColumnDefinition<T> extends IsSerializable
 {
     /** extracts value for the cell of the represented column */
-    String getValue(T rowModel);
-    
-    Comparable<?> getComparableValue(T rowModel);
+    String getValue(GridRowModel<T> rowModel);
+
+    Comparable<?> getComparableValue(GridRowModel<T> rowModel);
 
     /** column's header */
     String getHeader();
 
     /** unique identifier of the column */
     String getIdentifier();
-    
+
     /** Tries to get specified property or <code>null</code> if not found. */
     String tryToGetProperty(String key);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IDataStoreBaseURLProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IDataStoreBaseURLProvider.java
index 8e58e15449e8e06c43560d08143ce4dc0163b321..29519840c0842d1cd52db7191d16b68714ffac6a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IDataStoreBaseURLProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/IDataStoreBaseURLProvider.java
@@ -1,5 +1,6 @@
 package ch.systemsx.cisd.openbis.generic.shared.basic;
 
+
 /**
  * Implementation of this interface provides a way to expose the data store base URL.
  * 
@@ -7,5 +8,5 @@ package ch.systemsx.cisd.openbis.generic.shared.basic;
  */
 public interface IDataStoreBaseURLProvider
 {
-    public String getDataStoreBaseURL();
+    String getDataStoreBaseURL();
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java
index 2430e399cd120ff82ecfb6c0e6a4fec360835590..eb233735edce70083efbbbf0f194aa324eea99f3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java
@@ -21,13 +21,15 @@ import java.util.Date;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
+import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
+
 /**
  * Stores information describing the common part of grid custom filter and column.
  * 
  * @author Izabela Adamczyk
  */
 public abstract class AbstractGridExpression extends AbstractRegistrationHolder implements
-        IsSerializable, Serializable, IFilterOrColumnUpdates
+        IsSerializable, Serializable, IIdHolder, IFilterOrColumnUpdates
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
index 31350abb78a42dfaded510a5753e28692b09a493..3a1632574d30583720b8ff0ff6d45deb83160744 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
@@ -349,7 +349,7 @@ public final class GenericDataSetEditForm extends
         @Override
         protected void process(ResultSetWithEntityTypes<ExternalData> result)
         {
-            parentsArea.setParents(result.getResultSet().getList());
+            parentsArea.setParents(result.getResultSet().getList().extractOriginalObjects());
             if (parentsArea.isVisible())
             {
                 parentsArea.setEnabled(true);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java
index 6ea70b872fc7b106cb0088d605b610e14eebcf3a..8d2e9fff03e7fda0e513ed741a8c17bfbdc2fafd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java
@@ -73,7 +73,7 @@ public final class GenericExperimentEditForm extends AbstractGenericExperimentRe
         @Override
         protected void process(ResultSetWithEntityTypes<Sample> result)
         {
-            samplesArea.setSamples(result.getResultSet().getList());
+            samplesArea.setSamples(result.getResultSet().getList().extractOriginalObjects());
             samplesArea.setEnabled(true);
         }
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientServiceTest.java
index a2bee682880245818729bee6b9d09c7aede8c646..6e8d275ea070a9b875956b839429480b7ea3b9ce 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientServiceTest.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.server;
 
 import static ch.systemsx.cisd.openbis.generic.shared.GenericSharedConstants.DATA_STORE_SERVER_WEB_APPLICATION_NAME;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -27,6 +28,8 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
@@ -36,8 +39,11 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CacheManager
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CachedResultSetManager;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.DefaultResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IOriginalDataProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IResultSetKeyGenerator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CacheManager.TokenBasedResultSetKeyGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CachedResultSetManager.ICustomColumnsProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.server.util.TSVRendererTest;
 import ch.systemsx.cisd.openbis.generic.server.SessionConstants;
 import ch.systemsx.cisd.openbis.generic.server.business.ManagerTestTool;
 import ch.systemsx.cisd.openbis.generic.shared.CommonTestUtils;
@@ -47,6 +53,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -154,9 +161,16 @@ public final class CommonClientServiceTest extends AbstractClientServiceTest
         context.checking(new Expectations()
             {
                 {
-                    one(resultSetManager).getResultSet(
+                    IResultSet<String, String> entityTypeResultMock =
+                            context.mock(IResultSet.class);
+                    one(entityTypeResultMock).getList();
+                    will(returnValue(new GridRowModels<String>(
+                            new ArrayList<GridCustomColumnInfo>())));
+
+                    one(resultSetManager).getResultSet(with(SESSION_TOKEN),
                             with(Expectations.any(IResultSetConfig.class)),
                             with(Expectations.any(IOriginalDataProvider.class)));
+                    will(returnValue(entityTypeResultMock));
                 }
             });
         final ResultSetWithEntityTypes<Sample> resultSet =
@@ -199,7 +213,8 @@ public final class CommonClientServiceTest extends AbstractClientServiceTest
     {
         final String resultSetKey = "131";
         final DefaultResultSet<String, T> defaultResultSet =
-                new DefaultResultSet<String, T>(resultSetKey, entities, entities.size());
+                new DefaultResultSet<String, T>(resultSetKey, TSVRendererTest.asRowModel(entities),
+                        entities.size());
         context.checking(new Expectations()
             {
                 {
@@ -216,14 +231,14 @@ public final class CommonClientServiceTest extends AbstractClientServiceTest
     @SuppressWarnings("unchecked")
     private <T> void prepareGetResultSet(Expectations exp, IResultSetConfig<String, T> criteria)
     {
-        exp.one(resultSetManager).getResultSet(exp.with(criteria),
+        exp.one(resultSetManager).getResultSet(exp.with(SESSION_TOKEN), exp.with(criteria),
                 exp.with(Expectations.any(IOriginalDataProvider.class)));
     }
 
     private <T> void assertEqualEntities(List<T> entities, final ResultSet<T> resultSet)
     {
         assertEquals(entities.size(), resultSet.getList().size());
-        assertEquals(entities.get(0), resultSet.getList().get(0));
+        assertEquals(entities.get(0), resultSet.getList().get(0).getOriginalObject());
         assertEquals(entities.size(), resultSet.getTotalLength());
     }
 
@@ -347,7 +362,15 @@ public final class CommonClientServiceTest extends AbstractClientServiceTest
                     prepareGetSessionToken(this);
                     allowing(httpSession).getAttribute(SessionConstants.OPENBIS_RESULT_SET_MANAGER);
                     will(returnValue(new CachedResultSetManager<String>(
-                            new TokenBasedResultSetKeyGenerator())));
+                            new TokenBasedResultSetKeyGenerator(), new ICustomColumnsProvider()
+                                {
+                                    public List<GridCustomColumn> getGridCustomColumn(
+                                            String sessionToken, String gridDisplayId)
+                                    {
+                                        return new ArrayList<GridCustomColumn>();
+                                    }
+
+                                })));
 
                     one(commonServer).listExperimentExternalData(SESSION_TOKEN, experimentId);
                     will(returnValue(Collections.singletonList(externalData)));
@@ -357,7 +380,7 @@ public final class CommonClientServiceTest extends AbstractClientServiceTest
         ResultSetWithEntityTypes<ExternalData> resultSet =
                 commonClientService.listExperimentDataSets(experimentId,
                         new DefaultResultSetConfig<String, ExternalData>());
-        List<ExternalData> list = resultSet.getResultSet().getList();
+        List<ExternalData> list = resultSet.getResultSet().getList().extractOriginalObjects();
         assertEquals(1, list.size());
         ExternalData data = list.get(0);
         assertEquals(DATA_STORE_BASE_URL + "/" + DATA_STORE_SERVER_WEB_APPLICATION_NAME, data
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java
index 6109ae91704daeea05fba1ef736fe851897a9713..6c573152d3ca62b7f9ea5a68d3e8c8e9b58cac1f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.server.calculator;
 
 import java.math.BigInteger;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
@@ -26,6 +27,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
@@ -70,9 +72,9 @@ public class RowCalculatorTest extends AssertJUnit
                 }
 
                 @Override
-                public Comparable<?> getComparableValue(Data rowModel)
+                public Comparable<?> getComparableValue(GridRowModel<Data> rowModel)
                 {
-                    return rowModel.getValue();
+                    return rowModel.getOriginalObject().getValue();
                 }
             });
     }
@@ -95,15 +97,16 @@ public class RowCalculatorTest extends AssertJUnit
     {
         Set<ParameterWithValue> parameters = createParameters("x", "10");
         parameters.addAll(createParameters("y", "1"));
-        RowCalculator<Data> calculator = createCalculator(parameters, "${x} * row.col('VALUE') + ${y}");
-        
+        RowCalculator<Data> calculator =
+                createCalculator(parameters, "${x} * row.col('VALUE') + ${y}");
+
         calculator.setRowData(createData(2.5));
         assertEquals(26.0, calculator.evalToDouble());
-        
+
         calculator.setRowData(createData(10));
         assertEquals(101.0, calculator.evalToDouble());
     }
-    
+
     @Test
     public void testEvalToBoolean()
     {
@@ -169,38 +172,38 @@ public class RowCalculatorTest extends AssertJUnit
         calculator.setRowData(createData(3.15));
         assertEquals(0.0, calculator.evalToDouble());
     }
-    
+
     @Test
     public void testIntFunctionOverloaded()
     {
         Set<ParameterWithValue> parameters = createParameters("x", "0.0");
         RowCalculator<Data> calculator =
                 createCalculator(parameters, "map(int, [${x},'  ',2,2.5,'3'])");
-        
+
         assertEquals("[0, -2147483648, 2, 2, 3]", calculator.evalAsString());
-        
+
     }
-    
+
     @Test
     public void testFloatFunctionOverloaded()
     {
         Set<ParameterWithValue> parameters = createParameters("x", "0.0");
         RowCalculator<Data> calculator =
-            createCalculator(parameters, "map(float, [${x},'  ',2,2.5,'3'])");
-        
+                createCalculator(parameters, "map(float, [${x},'  ',2,2.5,'3'])");
+
         assertEquals("[0.0, -1.7976931348623157E308, 2.0, 2.5, 3.0]", calculator.evalAsString());
-        
+
     }
-    
+
     @Test
     public void testMinFunctionOverloaded()
     {
         Set<ParameterWithValue> parameters = createParameters("x", "0.0");
         RowCalculator<Data> calculator =
-            createCalculator(parameters, "min([${x},None,'  ',-2,'-3'])");
-        
+                createCalculator(parameters, "min([${x},None,'  ',-2,'-3'])");
+
         assertEquals(-3.0, calculator.evalToDouble());
-        
+
     }
 
     @Test
@@ -208,12 +211,12 @@ public class RowCalculatorTest extends AssertJUnit
     {
         Set<ParameterWithValue> parameters = createParameters("x", "0.0");
         RowCalculator<Data> calculator =
-            createCalculator(parameters, "max([${x},None,'  ',-2,'-3'])");
-        
+                createCalculator(parameters, "max([${x},None,'  ',-2,'-3'])");
+
         assertEquals(0.0, calculator.evalToDouble());
-        
+
     }
-    
+
     private RowCalculator<Data> createCalculator(Set<ParameterWithValue> parameters,
             String expression)
     {
@@ -228,10 +231,10 @@ public class RowCalculatorTest extends AssertJUnit
         return new LinkedHashSet<ParameterWithValue>(Arrays.asList(parameter));
     }
 
-    private Data createData(double value)
+    private GridRowModel<Data> createData(double value)
     {
         Data data = new Data();
         data.setValue(value);
-        return data;
+        return new GridRowModel<Data>(data, new HashMap<String, String>());
     }
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java
index e23c84612de09f6aee8768ecb67c94775433d276..19dd5f4b942aaedde616cbccd02ebaf1406505a8 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.generic.client.web.server.calculator;
 
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 
@@ -27,23 +28,24 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class RowTest extends AssertJUnit
 {
     private static final String PROPERTY_KEY = "key";
+
     private static final String PROPERTY_VALUE = "value";
+
     private static final String PROPERTY_VALUE2 = "value2";
 
     private static final class Data
     {
         private final double value;
-        
+
         Data(double value)
         {
             this.value = value;
@@ -71,12 +73,15 @@ public class RowTest extends AssertJUnit
         {
             return Double.toString(value);
         }
-        
+
     }
 
     private Mockery context;
+
     private IColumnDefinition<Data> def1;
+
     private IColumnDefinition<Data> def2;
+
     private Row<Data> row;
 
     @SuppressWarnings("unchecked")
@@ -91,7 +96,7 @@ public class RowTest extends AssertJUnit
                 {
                     allowing(def1).getIdentifier();
                     will(returnValue("def1"));
-                    
+
                     allowing(def2).getIdentifier();
                     will(returnValue("def2"));
                 }
@@ -100,7 +105,7 @@ public class RowTest extends AssertJUnit
                 new Row<Data>(new LinkedHashSet<IColumnDefinition<Data>>(Arrays
                         .<IColumnDefinition<Data>> asList(def1, def2)));
     }
-    
+
     @AfterMethod
     public void tearDown()
     {
@@ -108,34 +113,39 @@ public class RowTest extends AssertJUnit
         // Otherwise one does not known which test failed.
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testCol()
     {
-        final Data data1 = new Data(42.25);
-        final Data data2 = new Data(4711.25);
+        final GridRowModel<Data> data1 = createData();
+        final GridRowModel<Data> data2 = createData(4711.25);
         context.checking(new Expectations()
             {
                 {
                     one(def1).getComparableValue(data1);
-                    will(returnValue(data1.getValue()));
-                    
+                    will(returnValue(getVal(data1)));
+
                     one(def2).getComparableValue(data2);
-                    will(returnValue(data2.getValue()));
+                    will(returnValue(getVal(data2)));
                 }
             });
-        
+
         row.setRowData(data1);
-        
-        assertEquals(data1.getValue(), ((Number) row.col("def1")).doubleValue());
-        
+
+        assertEquals(getVal(data1), ((Number) row.col("def1")).doubleValue());
+
         row.setRowData(data2);
-        
-        assertEquals(data2.getValue(), ((Number) row.col("def2")).doubleValue());
-        
+
+        assertEquals(getVal(data2), ((Number) row.col("def2")).doubleValue());
+
         context.assertIsSatisfied();
     }
-    
+
+    private double getVal(final GridRowModel<Data> data1)
+    {
+        return data1.getOriginalObject().getValue();
+    }
+
     @Test
     public void testColForUnknownID()
     {
@@ -147,18 +157,18 @@ public class RowTest extends AssertJUnit
         {
             assertEquals("Undefined column: unknown", ex.getMessage());
         }
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testColDefs()
     {
         prepareColDefs(null, PROPERTY_VALUE);
-        
+
         row.colDefs(PROPERTY_KEY);
         List<ColumnDefinition> defs = row.colDefs(PROPERTY_KEY); // second call tests caching
-        
+
         context.checking(new Expectations()
             {
                 {
@@ -166,66 +176,77 @@ public class RowTest extends AssertJUnit
                     will(returnValue(PROPERTY_VALUE));
                 }
             });
-        
+
         assertEquals(1, defs.size());
         assertEquals("def2", defs.get(0).id());
         assertEquals(PROPERTY_VALUE, defs.get(0).property(PROPERTY_KEY));
         assertUnmodifiable(defs);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testColDefsWithNullArgument()
     {
         List<ColumnDefinition> defs = row.colDefs(null);
-        
+
         assertEquals(2, defs.size());
         assertUnmodifiable(defs);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testCols()
     {
-        final Data data = new Data(42.25);
+        final GridRowModel<Data> data = createData();
         prepareColDefs(null, PROPERTY_VALUE);
         context.checking(new Expectations()
             {
                 {
                     one(def2).tryToGetProperty(PROPERTY_KEY);
                     will(returnValue(PROPERTY_VALUE));
-                    
+
                     one(def2).getComparableValue(data);
-                    will(returnValue(data.getValue()));
+                    will(returnValue(getVal(data)));
                 }
             });
         row.setRowData(data);
-        
+
         List<Object> values = row.cols(PROPERTY_KEY, PROPERTY_VALUE);
 
         assertEquals(1, values.size());
         assertEquals(42.25, ((Double) values.get(0)).doubleValue());
         assertUnmodifiable(values);
-        
+
         context.assertIsSatisfied();
     }
-    
+
+    private GridRowModel<Data> createData()
+    {
+        return createData(42.25);
+    }
+
+    private GridRowModel<Data> createData(double value)
+    {
+        Data originalObject = new Data(value);
+        return new GridRowModel<Data>(originalObject, new HashMap<String, String>());
+    }
+
     @Test
     public void testColsNoMatchingPropertyKey()
     {
         prepareColDefs(null, null);
-        row.setRowData(new Data(42.25));
-        
+        row.setRowData(createData());
+
         List<Object> values = row.cols(PROPERTY_KEY, "unknown");
-        
+
         assertEquals(0, values.size());
         assertUnmodifiable(values);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testColsNoMatchingPropertyValue()
     {
@@ -237,91 +258,91 @@ public class RowTest extends AssertJUnit
                     will(returnValue(PROPERTY_VALUE));
                 }
             });
-        row.setRowData(new Data(42.25));
+        row.setRowData(createData());
 
         List<Object> values = row.cols(PROPERTY_KEY, "unknown");
-        
+
         assertEquals(0, values.size());
         assertUnmodifiable(values);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testColsGroupedByNoMatchingPropertyKey()
     {
         prepareColDefs(null, null);
-        
+
         List<ColumnGroup> groups = row.colsGroupedBy(PROPERTY_KEY);
-        
+
         assertEquals(0, groups.size());
         assertUnmodifiable(groups);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testColsGroupedByWithOneGroup()
     {
         prepareColDefs(PROPERTY_VALUE, PROPERTY_VALUE);
         prepareColDefs(PROPERTY_VALUE, PROPERTY_VALUE);
-        final Data data = new Data(42.25);
+        final GridRowModel<Data> data = createData();
         context.checking(new Expectations()
             {
                 {
                     one(def1).getComparableValue(data);
-                    will(returnValue(data.getValue()));
-                    
+                    will(returnValue(getVal(data)));
+
                     one(def2).getComparableValue(data);
-                    will(returnValue(2 * data.getValue()));
+                    will(returnValue(2 * getVal(data)));
                 }
             });
-        
+
         row.setRowData(data);
         List<ColumnGroup> groups = row.colsGroupedBy(PROPERTY_KEY);
-        
+
         assertEquals(1, groups.size());
         assertEquals(PROPERTY_VALUE, groups.get(0).propertyValue());
         assertEquals(2, groups.get(0).values().size());
-        assertEquals(new Double(data.getValue()), groups.get(0).values().get(0));
-        assertEquals(new Double(2 * data.getValue()), groups.get(0).values().get(1));
+        assertEquals(new Double(getVal(data)), groups.get(0).values().get(0));
+        assertEquals(new Double(2 * getVal(data)), groups.get(0).values().get(1));
         assertUnmodifiable(groups);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testColsGroupedByWithTwoGroups()
     {
         prepareColDefs(PROPERTY_VALUE, PROPERTY_VALUE2);
         prepareColDefs(PROPERTY_VALUE, PROPERTY_VALUE2);
-        final Data data = new Data(42.25);
+        final GridRowModel<Data> data = createData();
         context.checking(new Expectations()
             {
                 {
                     one(def1).getComparableValue(data);
-                    will(returnValue(data.getValue()));
+                    will(returnValue(getVal(data)));
 
                     one(def2).getComparableValue(data);
-                    will(returnValue(2 * data.getValue()));
+                    will(returnValue(2 * getVal(data)));
                 }
             });
 
         row.setRowData(data);
         List<ColumnGroup> groups = row.colsGroupedBy(PROPERTY_KEY);
-        
+
         assertEquals(2, groups.size());
         assertEquals(PROPERTY_VALUE, groups.get(0).propertyValue());
         assertEquals(1, groups.get(0).values().size());
-        assertEquals(new Double(data.getValue()), groups.get(0).values().get(0));
+        assertEquals(new Double(getVal(data)), groups.get(0).values().get(0));
         assertEquals(PROPERTY_VALUE2, groups.get(1).propertyValue());
         assertEquals(1, groups.get(1).values().size());
-        assertEquals(new Double(2 * data.getValue()), groups.get(1).values().get(0));
+        assertEquals(new Double(2 * getVal(data)), groups.get(1).values().get(0));
         assertUnmodifiable(groups);
-        
+
         context.assertIsSatisfied();
     }
-    
+
     private void prepareColDefs(final String propertyValueOfFirstDefinition,
             final String propertyValueOfSecondDefinition)
     {
@@ -336,7 +357,7 @@ public class RowTest extends AssertJUnit
                 }
             });
     }
-    
+
     private void assertUnmodifiable(List<?> list)
     {
         try
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java
index a6199a50a984f0ea6f506a58d8e8db20c621bc15..fd512ad94fff65544f9fcb2c34ba9c92c2604c4a 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java
@@ -33,8 +33,12 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import ch.rinn.restrictions.Friend;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CacheManager.TokenBasedResultSetKeyGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CachedResultSetManager.ICustomColumnsProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.server.util.TSVRendererTest;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridFilterInfo;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SortInfo;
@@ -48,6 +52,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SortInfo.SortDir;
 @Friend(toClasses = CachedResultSetManager.class)
 public final class CachedResultSetManagerTest
 {
+    static private final String SESSION_TOKEN = "SESSION_TOKEN";
+
     private IResultSetConfig<String, String> resultSetConfig;
 
     private IOriginalDataProvider<String> originalDataProvider;
@@ -78,7 +84,7 @@ public final class CachedResultSetManagerTest
         expectations.will(Expectations.returnValue(null));
     }
 
-    private final static List<Sample> createSampleList()
+    private final static GridRowModels<Sample> createSampleList()
     {
         final int size = 3;
         final List<Sample> list = new ArrayList<Sample>(size);
@@ -88,7 +94,7 @@ public final class CachedResultSetManagerTest
             sample.setCode("code" + i);
             list.add(sample);
         }
-        return list;
+        return TSVRendererTest.asRowModel(list);
     }
 
     @SuppressWarnings("unchecked")
@@ -104,7 +110,16 @@ public final class CachedResultSetManagerTest
     private final static IResultSetManager<String> createResultSetManager()
     {
         final CachedResultSetManager<String> resultSetManager =
-                new CachedResultSetManager<String>(new TokenBasedResultSetKeyGenerator());
+                new CachedResultSetManager<String>(new TokenBasedResultSetKeyGenerator(),
+                        new ICustomColumnsProvider()
+                            {
+                                public List<GridCustomColumn> getGridCustomColumn(
+                                        String sessionToken, String gridDisplayId)
+                                {
+                                    return new ArrayList<GridCustomColumn>();
+                                }
+
+                            });
         resultSetManager.results.put("1", createSampleList());
         return resultSetManager;
     }
@@ -123,7 +138,7 @@ public final class CachedResultSetManagerTest
         boolean fail = true;
         try
         {
-            resultSetManager.getResultSet(null, null);
+            resultSetManager.getResultSet(null, null, null);
         } catch (final AssertionError e)
         {
             fail = false;
@@ -165,9 +180,12 @@ public final class CachedResultSetManagerTest
                     one(resultSetConfig).getResultSetKey();
                     will(returnValue(null));
 
-                    one(resultSetConfig).getAvailableColumns();
+                    allowing(resultSetConfig).getAvailableColumns();
                     will(returnValue(null));
-                    
+
+                    one(resultSetConfig).tryGetGridDisplayId();
+                    will(returnValue(null));
+
                     one(originalDataProvider).getOriginalData();
                     will(returnValue(Collections.emptyList()));
 
@@ -175,7 +193,7 @@ public final class CachedResultSetManagerTest
                 }
             });
         final IResultSet<String, String> resultSet =
-                resultSetManager.getResultSet(resultSetConfig, originalDataProvider);
+                resultSetManager.getResultSet(SESSION_TOKEN, resultSetConfig, originalDataProvider);
         assertEquals(0, resultSet.getList().size());
         assertEquals(0, resultSet.getTotalLength());
         assertTrue(StringUtils.isNotEmpty(resultSet.getResultSetKey()));
@@ -191,14 +209,14 @@ public final class CachedResultSetManagerTest
                     one(resultSetConfig).getResultSetKey();
                     will(returnValue("1"));
 
-                    one(resultSetConfig).getAvailableColumns();
+                    allowing(resultSetConfig).getAvailableColumns();
                     will(returnValue(null));
-                    
+
                     allowResultSetCreation(this);
                 }
             });
         final IResultSet<String, ?> resultSet =
-                resultSetManager.getResultSet(resultSetConfig, originalDataProvider);
+                resultSetManager.getResultSet(SESSION_TOKEN, resultSetConfig, originalDataProvider);
         assertEquals(2, resultSet.getList().size());
         assertEquals(3, resultSet.getTotalLength());
         assertEquals("1", resultSet.getResultSetKey());
@@ -215,9 +233,12 @@ public final class CachedResultSetManagerTest
                     one(resultSetConfig).getResultSetKey();
                     will(returnValue(null));
 
-                    one(resultSetConfig).getAvailableColumns();
+                    allowing(resultSetConfig).getAvailableColumns();
+                    will(returnValue(null));
+
+                    one(resultSetConfig).tryGetGridDisplayId();
                     will(returnValue(null));
-                    
+
                     one(originalDataProvider).getOriginalData();
                     will(returnValue(Collections.singletonList(value)));
 
@@ -225,11 +246,11 @@ public final class CachedResultSetManagerTest
                 }
             });
         final IResultSet<String, ?> resultSet =
-                resultSetManager.getResultSet(resultSetConfig, originalDataProvider);
+                resultSetManager.getResultSet(SESSION_TOKEN, resultSetConfig, originalDataProvider);
         assertEquals(1, resultSet.getList().size());
         assertEquals(1, resultSet.getTotalLength());
         assertNotNull(resultSet.getResultSetKey());
-        assertEquals(value, resultSet.getList().get(0));
+        assertEquals(value, resultSet.getList().get(0).getOriginalObject());
         context.assertIsSatisfied();
     }
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtilsTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtilsTest.java
index 829cdc9d382bec416846f4167efb41dc375bd0f3..bc80fe24a61ea79a8b1a0c365c60c18e93334c8a 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtilsTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/FilterUtilsTest.java
@@ -27,12 +27,13 @@ import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
+import ch.systemsx.cisd.openbis.generic.client.web.server.calculator.GridExpressionUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class FilterUtilsTest extends AssertJUnit
@@ -51,26 +52,26 @@ public class FilterUtilsTest extends AssertJUnit
             return value;
         }
     }
-    
+
     @Test
     public void test()
     {
-        List<Data> filterdList = new ArrayList<Data>();
         CustomFilterInfo<Data> filterInfo = new CustomFilterInfo<Data>();
         filterInfo.setExpression("row.col('VALUE') < ${threshold}");
         ParameterWithValue parameter = new ParameterWithValue();
         parameter.setParameter("threshold");
         parameter.setValue("42");
         filterInfo.setParameters(new LinkedHashSet<ParameterWithValue>(Arrays.asList(parameter)));
-        Set<IColumnDefinition<Data>> availableColumns = new LinkedHashSet<IColumnDefinition<Data>>();
+        Set<IColumnDefinition<Data>> availableColumns =
+                new LinkedHashSet<IColumnDefinition<Data>>();
         availableColumns.add(new AbstractColumnDefinition<Data>("header", 100, true)
             {
-                
+
                 public String getIdentifier()
                 {
                     return "VALUE";
                 }
-                
+
                 @Override
                 protected String tryGetValue(Data entity)
                 {
@@ -78,28 +79,30 @@ public class FilterUtilsTest extends AssertJUnit
                 }
 
                 @Override
-                public Comparable<?> getComparableValue(Data rowModel)
+                public Comparable<?> getComparableValue(GridRowModel<Data> rowModel)
                 {
-                    return rowModel.getValue();
+                    return rowModel.getOriginalObject().getValue();
                 }
             });
-        
-        FilterUtils.applyCustomFilter(createData(57, 34), availableColumns, filterInfo, filterdList);
-        
+
+        GridRowModels<Data> filterdList =
+                GridExpressionUtils.applyCustomFilter(createData(57, 34), availableColumns,
+                        filterInfo);
+
         assertEquals(1, filterdList.size());
-        assertEquals(34.0, filterdList.get(0).getValue());
+        assertEquals(34.0, filterdList.get(0).getOriginalObject().getValue());
     }
-    
-    private List<Data> createData(double... values)
+
+    private GridRowModels<Data> createData(double... values)
     {
-        ArrayList<Data> list = new ArrayList<Data>();
+        List<Data> list = new ArrayList<Data>();
         for (double value : values)
         {
             Data data = new Data();
             data.setValue(value);
             list.add(data);
         }
-        return list;
+        return TSVRendererTest.asRowModel(list);
     }
-    
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java
index 437f84cad7e857ea9a4522542e994c251e420321..fabfad91f2f0b69b68386a489b4f12a3cfb5fc36 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java
@@ -17,12 +17,16 @@
 package ch.systemsx.cisd.openbis.generic.client.web.server.util;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 import junit.framework.Assert;
 
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
 /**
@@ -41,10 +45,20 @@ public class TSVRendererTest
             { "x", "y" });
         entities.add(new String[]
             { "a", "b" });
-        String content = TSVRenderer.createTable(entities, columnDefs, "#");
+        String content = TSVRenderer.createTable(asRowModel(entities), columnDefs, "#");
         Assert.assertEquals("h0\th1#x\ty#a\tb#", content);
     }
 
+    public static <T> GridRowModels<T> asRowModel(List<T> entities)
+    {
+        List<GridRowModel<T>> list = new ArrayList<GridRowModel<T>>();
+        for (T entity : entities)
+        {
+            list.add(new GridRowModel<T>(entity, new HashMap<String, String>()));
+        }
+        return new GridRowModels<T>(list, new ArrayList<GridCustomColumnInfo>());
+    }
+
     private static List<IColumnDefinition<String[]>> createColumnDefs(int colNum)
     {
         List<IColumnDefinition<String[]>> columnDefs = new ArrayList<IColumnDefinition<String[]>>();
@@ -60,7 +74,7 @@ public class TSVRendererTest
     {
         List<IColumnDefinition<String[]>> columnDefs = createColumnDefs(2);
         List<String[]> entities = new ArrayList<String[]>();
-        String content = TSVRenderer.createTable(entities, columnDefs, "\n");
+        String content = TSVRenderer.createTable(asRowModel(entities), columnDefs, "\n");
         Assert.assertEquals("h0\th1\n", content);
     }
 
@@ -79,12 +93,12 @@ public class TSVRendererTest
                     return null;
                 }
 
-                public String getValue(String[] rowModel)
+                public String getValue(GridRowModel<String[]> rowModel)
                 {
-                    return rowModel[colIx];
+                    return rowModel.getOriginalObject()[colIx];
                 }
 
-                public Comparable<?> getComparableValue(String[] rowModel)
+                public Comparable<?> getComparableValue(GridRowModel<String[]> rowModel)
                 {
                     return getValue(rowModel);
                 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EventDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EventDAOTest.java
index a3186446c8bce7e372c6e9b5f723becf3fca14e6..c08d634c117ab714219af4656e68c5729b2d50e0 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EventDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EventDAOTest.java
@@ -154,7 +154,6 @@ public class EventDAOTest extends AbstractDAOTest
         String description = eventType.name() + " " + entityType.name();
         PersonPE person = getSystemPerson();
         Long personId = HibernateUtils.getId(person);
-        // TODO 2009-09-04, Tomasz Pylak: change to hibernate
         simpleJdbcTemplate
                 .update(
                         "insert into events "
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java
index e8dd4aa28eebb4ad556822c29c37aaa480f3f761..12356e46d42c65708f467b3b99ed7c9180d5aad1 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java
@@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Co
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ICellListener;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
@@ -142,7 +143,8 @@ class ProteinByExperimentBrowserGrid extends AbstractSimpleBrowserGrid<ProteinIn
                     properties.put(treatment.getTypeCode(), treatment.getValue());
                 }
             }
-            columns.add(new InternalAbundanceColumnDefinition(header, properties, 100, false, sampleID));
+            columns.add(new InternalAbundanceColumnDefinition(header, properties, 100, false,
+                    sampleID));
         }
         definitions.addColumns(columns);
         definitions.setGridCellRendererFor(ProteinColDefKind.ACCESSION_NUMBER.id(), LinkRenderer
@@ -151,7 +153,7 @@ class ProteinByExperimentBrowserGrid extends AbstractSimpleBrowserGrid<ProteinIn
     }
 
     @Override
-    protected BaseEntityModel<ProteinInfo> createModel(ProteinInfo entity)
+    protected BaseEntityModel<ProteinInfo> createModel(GridRowModel<ProteinInfo> entity)
     {
         Set<IColumnDefinition<ProteinInfo>> columnDefs = createColumnsDefinition().getColumnDefs();
         return new BaseEntityModel<ProteinInfo>(entity,
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/SampleAbundanceBrowserGrid.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/SampleAbundanceBrowserGrid.java
index 4b5f17e59fc135930fc54d5edaf77eeed7d6a52f..6a1ae0c847a19dd2112da26b3d7bc9730d787938 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/SampleAbundanceBrowserGrid.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/SampleAbundanceBrowserGrid.java
@@ -45,6 +45,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.en
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractDataListDeletionConfirmationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.IDataRefreshCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
@@ -275,7 +276,7 @@ public class SampleAbundanceBrowserGrid
 
     @Override
     protected BaseEntityModel<SampleWithPropertiesAndAbundance> createModel(
-            SampleWithPropertiesAndAbundance entity)
+            GridRowModel<SampleWithPropertiesAndAbundance> entity)
     {
         return SampleAbundanceModelFactory.createModel(entity);
     }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/DataSetProteinColDefKind.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/DataSetProteinColDefKind.java
index 2c80e1fe09fd060ee4518d570ef5f4c692deed48..4fd51eacad32572b89f425b52f3f57c3abccc3dd 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/DataSetProteinColDefKind.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/DataSetProteinColDefKind.java
@@ -18,12 +18,11 @@ package ch.systemsx.cisd.openbis.plugin.phosphonetx.client.web.client.applicatio
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.basic.dto.DataSetProtein;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public enum DataSetProteinColDefKind implements IColumnDefinitionKind<DataSetProtein>
@@ -35,8 +34,7 @@ public enum DataSetProteinColDefKind implements IColumnDefinitionKind<DataSetPro
             {
                 return entity.getDataSetPermID();
             }
-        }), 
-    SEQUENCE_NAME(new AbstractColumnDefinitionKind<DataSetProtein>(Dict.SEQUENCE_NAME, 80)
+        }), SEQUENCE_NAME(new AbstractColumnDefinitionKind<DataSetProtein>(Dict.SEQUENCE_NAME, 80)
         {
             @Override
             public String tryGetValue(DataSetProtein entity)
@@ -52,35 +50,36 @@ public enum DataSetProteinColDefKind implements IColumnDefinitionKind<DataSetPro
             {
                 return Integer.toString(entity.getPeptideCount());
             }
-            
+
             @Override
-            public Comparable<?> getComparableValue(DataSetProtein entity)
+            public Comparable<?> getComparableValue(GridRowModel<DataSetProtein> entity)
             {
-                return entity.getPeptideCount();
+                return entity.getOriginalObject().getPeptideCount();
             }
         }),
-                
+
     FDR(new AbstractColumnDefinitionKind<DataSetProtein>(Dict.FDR, 80)
+        {
+            @Override
+            public String tryGetValue(DataSetProtein entity)
+            {
+                int perMille = (int) (1000 * entity.getFalseDiscoveryRate() + 0.5);
+                return (perMille / 10) + "." + (perMille % 10) + " %";
+            }
+
+            @Override
+            public Comparable<?> getComparableValue(GridRowModel<DataSetProtein> entity)
             {
-                @Override
-                public String tryGetValue(DataSetProtein entity)
-                {
-                    int perMille = (int) (1000 * entity.getFalseDiscoveryRate() + 0.5);
-                    return (perMille / 10) + "." + (perMille % 10) + " %";
-                }
-                
-                @Override
-                public Comparable<?> getComparableValue(DataSetProtein entity)
-                {
-                    return entity.getFalseDiscoveryRate();
-                }
-            }),
-                        
+                return entity.getOriginalObject().getFalseDiscoveryRate();
+            }
+        }),
+
     ;
 
     private final AbstractColumnDefinitionKind<DataSetProtein> columnDefinitionKind;
 
-    private DataSetProteinColDefKind(AbstractColumnDefinitionKind<DataSetProtein> columnDefinitionKind)
+    private DataSetProteinColDefKind(
+            AbstractColumnDefinitionKind<DataSetProtein> columnDefinitionKind)
     {
         this.columnDefinitionKind = columnDefinitionKind;
     }
@@ -95,5 +94,4 @@ public enum DataSetProteinColDefKind implements IColumnDefinitionKind<DataSetPro
         return columnDefinitionKind;
     }
 
-
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/InternalAbundanceColumnDefinition.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/InternalAbundanceColumnDefinition.java
index 2818489f0e525dc1ebdbc7eeb48fd9c5a40bf46b..3e0d395a38eb52d1d6ccfe6ac8fc4e8411118fda 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/InternalAbundanceColumnDefinition.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/columns/InternalAbundanceColumnDefinition.java
@@ -19,13 +19,13 @@ package ch.systemsx.cisd.openbis.plugin.phosphonetx.client.web.client.applicatio
 import java.util.Map;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.basic.dto.ProteinInfo;
 
-public final class InternalAbundanceColumnDefinition extends
-        AbstractColumnDefinition<ProteinInfo>
+public final class InternalAbundanceColumnDefinition extends AbstractColumnDefinition<ProteinInfo>
 {
     private static final Double ZERO = new Double(1e-9);
-    
+
     private long sampleID;
 
     private Map<String, String> properties;
@@ -36,8 +36,8 @@ public final class InternalAbundanceColumnDefinition extends
         super();
     }
 
-    public InternalAbundanceColumnDefinition(String headerTextOrNull, Map<String, String> propertiesOrNull, int width,
-            boolean isHidden, long sampleID)
+    public InternalAbundanceColumnDefinition(String headerTextOrNull,
+            Map<String, String> propertiesOrNull, int width, boolean isHidden, long sampleID)
     {
         super(headerTextOrNull, width, isHidden);
         this.properties = propertiesOrNull;
@@ -48,7 +48,7 @@ public final class InternalAbundanceColumnDefinition extends
     {
         return "abundance-" + Long.toString(sampleID);
     }
-    
+
     @Override
     protected String tryGetValue(ProteinInfo entity)
     {
@@ -57,12 +57,12 @@ public final class InternalAbundanceColumnDefinition extends
     }
 
     @Override
-    public Comparable<?> getComparableValue(ProteinInfo rowModel)
+    public Comparable<?> getComparableValue(GridRowModel<ProteinInfo> rowModel)
     {
-        Double abundance = tryToGetAbundance(rowModel);
+        Double abundance = tryToGetAbundance(rowModel.getOriginalObject());
         return abundance == null ? ZERO : abundance;
     }
-    
+
     @Override
     public boolean isNumeric()
     {
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/model/SampleAbundanceModelFactory.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/model/SampleAbundanceModelFactory.java
index 51c53359dd9396f0907f067ce40b1def022199ca..fcb322961692a1a603e4333f021d574fc8cfeddd 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/model/SampleAbundanceModelFactory.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/model/SampleAbundanceModelFactory.java
@@ -16,7 +16,6 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.client.web.client.application.model;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import com.extjs.gxt.ui.client.data.ModelData;
@@ -26,6 +25,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Enti
 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.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.client.web.client.application.columns.SampleAbundanceColDefKind;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.basic.dto.SampleWithPropertiesAndAbundance;
@@ -46,7 +46,7 @@ public final class SampleAbundanceModelFactory
     }
 
     public static BaseEntityModel<SampleWithPropertiesAndAbundance> createModel(
-            SampleWithPropertiesAndAbundance entity)
+            GridRowModel<SampleWithPropertiesAndAbundance> entity)
     {
         List<IColumnDefinitionUI<SampleWithPropertiesAndAbundance>> allColumnsDefinition =
                 new SampleAbundanceModelFactory().createColumnsSchemaForRendering(entity);
@@ -65,7 +65,7 @@ public final class SampleAbundanceModelFactory
     }
 
     private List<IColumnDefinitionUI<SampleWithPropertiesAndAbundance>> createColumnsSchemaForRendering(
-            SampleWithPropertiesAndAbundance sample)
+            GridRowModel<SampleWithPropertiesAndAbundance> sample)
     {
         List<IColumnDefinitionUI<SampleWithPropertiesAndAbundance>> columns =
                 entityGridModelFactory.createColumnsSchemaForRendering(sample);
@@ -81,15 +81,4 @@ public final class SampleAbundanceModelFactory
                 entityGridModelFactory.createColumnsSchema(messageProvider, propertyTypes);
         return columns;
     }
-
-    public final static List<ModelData> asSampleModels(
-            final List<SampleWithPropertiesAndAbundance> samples)
-    {
-        final List<ModelData> sampleModels = new ArrayList<ModelData>(samples.size());
-        for (final SampleWithPropertiesAndAbundance sample : samples)
-        {
-            sampleModels.add(SampleAbundanceModelFactory.createModel(sample));
-        }
-        return sampleModels;
-    }
 }