From fad8735f64e88fab992ddb3d11599590592829bc Mon Sep 17 00:00:00 2001
From: tpylak <tpylak>
Date: Mon, 5 Oct 2009 14:12:48 +0000
Subject: [PATCH] LMS-1204 Calculated Columns: server side for
 adding/editing/deleting columns. Refactoring: Filter* -> GridCustomFilter*.

SVN: 12843
---
 .../web/client/ICommonClientService.java      |  20 +-
 .../web/client/ICommonClientServiceAsync.java |  22 +--
 .../ui/columns/specific/FilterColDefKind.java |  34 ++--
 ...idCustomExpressionEditRegisterDialog.java} |   7 +-
 .../ui/filter/AddFilterDialog.java            |   6 +-
 .../ui/filter/EditFilterDialog.java           |   8 +-
 .../application/ui/filter/FilterGrid.java     |  36 ++--
 .../application/ui/filter/FilterModel.java    |  16 +-
 .../ui/filter/FilterSelectionWidget.java      |  10 +-
 .../application/ui/filter/FilterToolbar.java  |  20 +-
 .../web/server/CommonClientService.java       |  24 +--
 .../generic/server/AbstractServer.java        |   4 +-
 .../server/CommonBusinessObjectFactory.java   |  14 +-
 .../openbis/generic/server/CommonServer.java  | 115 +++++++----
 .../generic/server/CommonServerLogger.java    |  40 +++-
 .../authorization/PredicateExecutor.java      |  12 +-
 .../business/bo/AbstractBusinessObject.java   |  13 +-
 .../business/bo/GridCustomColumnBO.java       | 121 ++++++++++++
 ...{FilterBO.java => GridCustomFilterBO.java} |  29 +--
 .../bo/ICommonBusinessObjectFactory.java      |   4 +-
 ....java => IGridCustomFilterOrColumnBO.java} |  23 +--
 .../dataaccess/IAuthorizationDAOFactory.java  |  46 +----
 .../dataaccess/IGridCustomColumnDAO.java      |  40 ++++
 ...lterDAO.java => IGridCustomFilterDAO.java} |  14 +-
 .../db/AuthorizationDAOFactory.java           |  21 +-
 .../dataaccess/db/GridCustomColumnDAO.java    |  75 ++++++++
 ...ilterDAO.java => GridCustomFilterDAO.java} |  23 +--
 .../openbis/generic/shared/ICommonServer.java |  73 +++++--
 .../IAuthorizationDataProvider.java           |  12 +-
 .../AbstractGridExpressionPredicate.java      | 181 ++++++++++++++++++
 .../predicate/FilterTechIdPredicate.java      | 133 -------------
 .../predicate/FilterUpdatesPredicate.java     |  51 -----
 ...ava => CustomGridExpressionValidator.java} |  13 +-
 ...ilter.java => AbstractGridExpression.java} |  36 +---
 .../basic/dto/DatabaseModificationKind.java   |   3 +-
 .../shared/basic/dto/GridCustomColumn.java    |  58 ++++++
 .../shared/basic/dto/GridCustomFilter.java    |  61 ++++++
 ...dates.java => IFilterOrColumnUpdates.java} |   6 +-
 ...{NewFilter.java => NewColumnOrFilter.java} |   6 +-
 ...rPE.java => AbstractGridExpressionPE.java} | 103 ++--------
 .../shared/dto/GridCustomColumnPE.java        | 110 +++++++++++
 .../shared/dto/GridCustomFilterPE.java        | 105 ++++++++++
 .../generic/shared/dto/TableNames.java        |   2 +
 .../shared/translator/FilterTranslator.java   |  90 ---------
 .../GridCustomExpressionTranslator.java       | 140 ++++++++++++++
 openbis/source/java/hibernateContext.xml      |   3 +-
 .../migration/migration-042-043.sql           |  14 ++
 .../server/business/bo/AbstractBOTest.java    |   8 +-
 ...OTest.java => GridCustomFilterBOTest.java} |  26 +--
 .../db/GridCustomColumnDAOTest.java           |  63 ++++++
 ...Test.java => GridCustomFilterDAOTest.java} |  56 +++---
 .../shared/ICommonServer.java.expected        |  71 +++++--
 .../authorization/AuthorizationTestCase.java  |   6 +-
 ...=> CustomGridExpressionValidatorTest.java} |  40 ++--
 ...va => GridCustomFilterTranslatorTest.java} |  14 +-
 55 files changed, 1529 insertions(+), 752 deletions(-)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/{AbstractFilterEditRegisterDialog.java => AbstractGridCustomExpressionEditRegisterDialog.java} (96%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomColumnBO.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/{FilterBO.java => GridCustomFilterBO.java} (75%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/{IFilterBO.java => IGridCustomFilterOrColumnBO.java} (60%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomColumnDAO.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/{IFilterDAO.java => IGridCustomFilterDAO.java} (63%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAO.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/{FilterDAO.java => GridCustomFilterDAO.java} (66%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractGridExpressionPredicate.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterTechIdPredicate.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterUpdatesPredicate.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/{FilterValidator.java => CustomGridExpressionValidator.java} (80%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/{Filter.java => AbstractGridExpression.java} (76%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomColumn.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomFilter.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/{IFilterUpdates.java => IFilterOrColumnUpdates.java} (80%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/{NewFilter.java => NewColumnOrFilter.java} (92%)
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/{FilterPE.java => AbstractGridExpressionPE.java} (61%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomColumnPE.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomFilterPE.java
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslator.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomExpressionTranslator.java
 create mode 100644 openbis/source/sql/postgresql/migration/migration-042-043.sql
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/{FilterBOTest.java => GridCustomFilterBOTest.java} (76%)
 create mode 100644 openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAOTest.java
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/{FilterDAOTest.java => GridCustomFilterDAOTest.java} (54%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/{FilterValidatorTest.java => CustomGridExpressionValidatorTest.java} (61%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/{FilterTranslatorTest.java => GridCustomFilterTranslatorTest.java} (68%)

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 f65147e240b..7def895059d 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
@@ -56,10 +56,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -69,7 +69,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -746,25 +746,25 @@ public interface ICommonClientService extends IClientService
     /**
      * Lists filters available for given grid.
      */
-    public List<Filter> listFilters(String gridId) throws UserFailureException;
+    public List<GridCustomFilter> listFilters(String gridId) throws UserFailureException;
 
     /**
-     * Returns {@link Filter}s for given criteria.
+     * Returns {@link GridCustomFilter}s for given criteria.
      */
-    public ResultSet<Filter> listFilters(String gridId,
-            DefaultResultSetConfig<String, Filter> resultSetConfig) throws UserFailureException;
+    public ResultSet<GridCustomFilter> listFilters(String gridId,
+            DefaultResultSetConfig<String, GridCustomFilter> resultSetConfig) throws UserFailureException;
 
     /**
      * Returns a key which can be used be the export servlet (and eventually
      * {@link #getExportTable(String, String)}) to reference the export criteria in an easy way.
      */
-    public String prepareExportFilters(final TableExportCriteria<Filter> criteria)
+    public String prepareExportFilters(final TableExportCriteria<GridCustomFilter> criteria)
             throws UserFailureException;
 
     /**
      * Registers a new filter.
      */
-    public void registerFilter(NewFilter filter) throws UserFailureException;
+    public void registerFilter(NewColumnOrFilter filter) throws UserFailureException;
 
     /** Deletes the specified filters. */
     public void deleteFilters(List<TechId> filterIds) throws UserFailureException;
@@ -772,5 +772,5 @@ public interface ICommonClientService extends IClientService
     /**
      * Updates filter.
      */
-    public void updateFilter(final IFilterUpdates updates) throws UserFailureException;
+    public void updateFilter(final IFilterOrColumnUpdates updates) 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 400d1b22850..b7a64c9e3e9 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
@@ -58,10 +58,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -71,7 +71,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -666,26 +666,26 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     /**
      * @see ICommonClientService#listFilters(String)
      */
-    public void listFilters(String gridId, AsyncCallback<List<Filter>> callback);
+    public void listFilters(String gridId, AsyncCallback<List<GridCustomFilter>> callback);
 
     /**
      * @see ICommonClientService#listFilters(String, DefaultResultSetConfig)
      */
-    public void listFilters(String gridId, DefaultResultSetConfig<String, Filter> resultSetConfig,
-            AsyncCallback<ResultSet<Filter>> callback);
+    public void listFilters(String gridId, DefaultResultSetConfig<String, GridCustomFilter> resultSetConfig,
+            AsyncCallback<ResultSet<GridCustomFilter>> callback);
 
     /**
      * @see ICommonClientService#prepareExportFilters(TableExportCriteria)
      */
-    public void prepareExportFilters(final TableExportCriteria<Filter> criteria,
+    public void prepareExportFilters(final TableExportCriteria<GridCustomFilter> criteria,
             AsyncCallback<String> asyncCallback);
 
-    /** @see ICommonClientService#registerFilter(NewFilter) */
-    public void registerFilter(NewFilter newFilter, AsyncCallback<Void> registrationCallback);
+    /** @see ICommonClientService#registerFilter(NewColumnOrFilter) */
+    public void registerFilter(NewColumnOrFilter newFilter, AsyncCallback<Void> registrationCallback);
 
     /** @see ICommonClientService#deleteFilters(List) */
     public void deleteFilters(List<TechId> filterIds, AsyncCallback<Void> asyncCallback);
 
-    /** @see ICommonClientService#updateFilter(IFilterUpdates) */
-    public void updateFilter(IFilterUpdates updates, AsyncCallback<Void> registrationCallback);
+    /** @see ICommonClientService#updateFilter(IFilterOrColumnUpdates) */
+    public void updateFilter(IFilterOrColumnUpdates updates, AsyncCallback<Void> registrationCallback);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/FilterColDefKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/FilterColDefKind.java
index e86ec0d6fa2..5e3de872978 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/FilterColDefKind.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/FilterColDefKind.java
@@ -20,73 +20,73 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 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.renderers.SimpleYesNoRenderer;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 
 /**
  * Column definitions for the filters.
  * 
  * @author Izabela Adamczyk
  */
-public enum FilterColDefKind implements IColumnDefinitionKind<Filter>
+public enum FilterColDefKind implements IColumnDefinitionKind<GridCustomFilter>
 {
-    NAME(new AbstractColumnDefinitionKind<Filter>(Dict.NAME)
+    NAME(new AbstractColumnDefinitionKind<GridCustomFilter>(Dict.NAME)
         {
             @Override
-            public String tryGetValue(Filter entity)
+            public String tryGetValue(GridCustomFilter entity)
             {
                 return entity.getName();
             }
         }),
 
-    DESCRIPTION(new AbstractColumnDefinitionKind<Filter>(Dict.DESCRIPTION)
+    DESCRIPTION(new AbstractColumnDefinitionKind<GridCustomFilter>(Dict.DESCRIPTION)
         {
             @Override
-            public String tryGetValue(Filter entity)
+            public String tryGetValue(GridCustomFilter entity)
             {
                 return entity.getDescription();
             }
         }),
 
-    EXPRESSION(new AbstractColumnDefinitionKind<Filter>(Dict.EXPRESSION, true)
+    EXPRESSION(new AbstractColumnDefinitionKind<GridCustomFilter>(Dict.EXPRESSION, true)
         {
             @Override
-            public String tryGetValue(Filter entity)
+            public String tryGetValue(GridCustomFilter entity)
             {
                 return entity.getExpression();
             }
         }),
 
-    PUBLIC(new AbstractColumnDefinitionKind<Filter>(Dict.IS_PUBLIC, true)
+    PUBLIC(new AbstractColumnDefinitionKind<GridCustomFilter>(Dict.IS_PUBLIC, true)
         {
             @Override
-            public String tryGetValue(Filter entity)
+            public String tryGetValue(GridCustomFilter entity)
             {
                 return SimpleYesNoRenderer.render(entity.isPublic());
             }
         }),
 
-    REGISTRATOR(new AbstractColumnDefinitionKind<Filter>(Dict.REGISTRATOR, true)
+    REGISTRATOR(new AbstractColumnDefinitionKind<GridCustomFilter>(Dict.REGISTRATOR, true)
         {
             @Override
-            public String tryGetValue(Filter entity)
+            public String tryGetValue(GridCustomFilter entity)
             {
                 return renderRegistrator(entity);
             }
         }),
 
-    REGISTRATION_DATE(new AbstractColumnDefinitionKind<Filter>(Dict.REGISTRATION_DATE,
+    REGISTRATION_DATE(new AbstractColumnDefinitionKind<GridCustomFilter>(Dict.REGISTRATION_DATE,
             AbstractColumnDefinitionKind.DATE_COLUMN_WIDTH, true)
         {
             @Override
-            public String tryGetValue(Filter entity)
+            public String tryGetValue(GridCustomFilter entity)
             {
                 return renderRegistrationDate(entity);
             }
         });
 
-    private final AbstractColumnDefinitionKind<Filter> columnDefinitionKind;
+    private final AbstractColumnDefinitionKind<GridCustomFilter> columnDefinitionKind;
 
-    private FilterColDefKind(AbstractColumnDefinitionKind<Filter> columnDefinitionKind)
+    private FilterColDefKind(AbstractColumnDefinitionKind<GridCustomFilter> columnDefinitionKind)
     {
         this.columnDefinitionKind = columnDefinitionKind;
     }
@@ -96,7 +96,7 @@ public enum FilterColDefKind implements IColumnDefinitionKind<Filter>
         return name();
     }
 
-    public AbstractColumnDefinitionKind<Filter> getDescriptor()
+    public AbstractColumnDefinitionKind<GridCustomFilter> getDescriptor()
     {
         return columnDefinitionKind;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AbstractFilterEditRegisterDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AbstractGridCustomExpressionEditRegisterDialog.java
similarity index 96%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AbstractFilterEditRegisterDialog.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AbstractGridCustomExpressionEditRegisterDialog.java
index 01fa9348a5f..23c38960dc7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AbstractFilterEditRegisterDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AbstractGridCustomExpressionEditRegisterDialog.java
@@ -39,12 +39,13 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDele
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
 
 /**
- * A {@link Window} extension for registering and editing filters.
+ * A {@link Window} extension for registering and editing grid custom filters or columns.
  * 
  * @author Izabela Adamczyk
  * @author Piotr Buczek
  */
-abstract public class AbstractFilterEditRegisterDialog extends AbstractRegistrationDialog
+abstract public class AbstractGridCustomExpressionEditRegisterDialog extends
+        AbstractRegistrationDialog
 {
 
     public static int FIELD_WIDTH = 400;
@@ -75,7 +76,7 @@ abstract public class AbstractFilterEditRegisterDialog extends AbstractRegistrat
 
     protected final String gridId;
 
-    public AbstractFilterEditRegisterDialog(
+    public AbstractGridCustomExpressionEditRegisterDialog(
             final IViewContext<ICommonClientServiceAsync> viewContext, final String title,
             final IDelegatedAction postRegistrationCallback, final String gridId,
             final List<ColumnDataModel> columnModels)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AddFilterDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AddFilterDialog.java
index 29c2ef24925..6d43588560b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AddFilterDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/AddFilterDialog.java
@@ -26,7 +26,7 @@ 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.util.IDelegatedAction;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 
 /**
  * {@link Window} containing filter registration form.
@@ -34,7 +34,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
  * @author Izabela Adamczyk
  * @author Piotr Buczek
  */
-public class AddFilterDialog extends AbstractFilterEditRegisterDialog
+public class AddFilterDialog extends AbstractGridCustomExpressionEditRegisterDialog
 {
     private final IViewContext<ICommonClientServiceAsync> viewContext;
 
@@ -50,7 +50,7 @@ public class AddFilterDialog extends AbstractFilterEditRegisterDialog
     @Override
     protected void register(AsyncCallback<Void> registrationCallback)
     {
-        NewFilter filter = new NewFilter();
+        NewColumnOrFilter filter = new NewColumnOrFilter();
         filter.setGridId(gridId);
         filter.setDescription(extractDescription());
         filter.setExpression(extractExpression());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/EditFilterDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/EditFilterDialog.java
index c383658faff..5506f46e621 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/EditFilterDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/EditFilterDialog.java
@@ -26,22 +26,22 @@ 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.util.IDelegatedAction;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 
 /**
  * {@link Window} containing filter edition form.
  * 
  * @author Piotr Buczek
  */
-public class EditFilterDialog extends AbstractFilterEditRegisterDialog
+public class EditFilterDialog extends AbstractGridCustomExpressionEditRegisterDialog
 {
     private final IViewContext<ICommonClientServiceAsync> viewContext;
 
-    private final Filter filter;
+    private final GridCustomFilter filter;
 
     public EditFilterDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
             final IDelegatedAction postRegistrationCallback, String gridId,
-            List<ColumnDataModel> columnModels, Filter filter)
+            List<ColumnDataModel> columnModels, GridCustomFilter filter)
     {
         super(viewContext, viewContext.getMessage(Dict.EDIT_TITLE, viewContext
                 .getMessage(Dict.FILTER), filter.getName()), postRegistrationCallback, gridId,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterGrid.java
index 7907bfe03f4..76831928a63 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterGrid.java
@@ -46,7 +46,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteri
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
@@ -54,7 +54,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKin
  * 
  * @author Izabela Adamczyk
  */
-public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
+public class FilterGrid extends AbstractSimpleBrowserGrid<GridCustomFilter>
 {
     // browser consists of the grid and the paging toolbar
     public static final String BROWSER_ID = GenericConstants.ID_PREFIX + "filter-browser";
@@ -116,11 +116,11 @@ public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
         addButton(addButton);
         final Button editButton =
                 createSelectedItemButton(viewContext.getMessage(Dict.BUTTON_EDIT),
-                        new ISelectedEntityInvoker<BaseEntityModel<Filter>>()
+                        new ISelectedEntityInvoker<BaseEntityModel<GridCustomFilter>>()
                             {
-                                public void invoke(BaseEntityModel<Filter> selectedItem)
+                                public void invoke(BaseEntityModel<GridCustomFilter> selectedItem)
                                 {
-                                    final Filter filter = selectedItem.getBaseObject();
+                                    final GridCustomFilter filter = selectedItem.getBaseObject();
                                     createEditDialog(filter).show();
                                 }
 
@@ -131,7 +131,7 @@ public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
                         new AbstractCreateDialogListener()
                             {
                                 @Override
-                                protected Dialog createDialog(List<Filter> filters,
+                                protected Dialog createDialog(List<GridCustomFilter> filters,
                                         IBrowserGridActionInvoker invoker)
                                 {
                                     return new FilterListDeletionConfirmationDialog(viewContext,
@@ -148,22 +148,22 @@ public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
         return new AddFilterDialog(viewContext, createRefreshGridAction(), gridId, columnModels);
     }
 
-    private Window createEditDialog(Filter filter)
+    private Window createEditDialog(GridCustomFilter filter)
     {
         return new EditFilterDialog(viewContext, createRefreshGridAction(), gridId, columnModels,
                 filter);
     }
 
     @Override
-    protected IColumnDefinitionKind<Filter>[] getStaticColumnsDefinition()
+    protected IColumnDefinitionKind<GridCustomFilter>[] getStaticColumnsDefinition()
     {
         return FilterColDefKind.values();
     }
 
     @Override
-    protected ColumnDefsAndConfigs<Filter> createColumnsDefinition()
+    protected ColumnDefsAndConfigs<GridCustomFilter> createColumnsDefinition()
     {
-        ColumnDefsAndConfigs<Filter> schema = super.createColumnsDefinition();
+        ColumnDefsAndConfigs<GridCustomFilter> schema = super.createColumnsDefinition();
         schema.setGridCellRendererFor(FilterColDefKind.DESCRIPTION.id(),
                 createMultilineStringCellRenderer());
         schema.setGridCellRendererFor(FilterColDefKind.EXPRESSION.id(),
@@ -172,21 +172,21 @@ public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
     }
 
     @Override
-    protected void listEntities(DefaultResultSetConfig<String, Filter> resultSetConfig,
-            AbstractAsyncCallback<ResultSet<Filter>> callback)
+    protected void listEntities(DefaultResultSetConfig<String, GridCustomFilter> resultSetConfig,
+            AbstractAsyncCallback<ResultSet<GridCustomFilter>> callback)
     {
         viewContext.getService().listFilters(gridId, resultSetConfig, callback);
     }
 
     @Override
-    protected void prepareExportEntities(TableExportCriteria<Filter> exportCriteria,
+    protected void prepareExportEntities(TableExportCriteria<GridCustomFilter> exportCriteria,
             AbstractAsyncCallback<String> callback)
     {
         viewContext.getService().prepareExportFilters(exportCriteria, callback);
     }
 
     @Override
-    protected List<IColumnDefinition<Filter>> getInitialFilters()
+    protected List<IColumnDefinition<GridCustomFilter>> getInitialFilters()
     {
         return asColumnFilters(new FilterColDefKind[]
             { FilterColDefKind.NAME, FilterColDefKind.PUBLIC });
@@ -195,13 +195,13 @@ public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
     public DatabaseModificationKind[] getRelevantModifications()
     {
         return new DatabaseModificationKind[]
-            { DatabaseModificationKind.createOrDelete(ObjectKind.FILTER),
-                    DatabaseModificationKind.edit(ObjectKind.FILTER) };
+            { DatabaseModificationKind.createOrDelete(ObjectKind.GRID_CUSTOM_FILTER),
+                    DatabaseModificationKind.edit(ObjectKind.GRID_CUSTOM_FILTER) };
     }
 
     // it would be better to implement AbstractDataListDeletionConfirmationDialog with 'reason'
     public class FilterListDeletionConfirmationDialog extends
-            AbstractDataConfirmationDialog<List<Filter>>
+            AbstractDataConfirmationDialog<List<GridCustomFilter>>
     {
         private static final int LABEL_WIDTH = 60;
 
@@ -210,7 +210,7 @@ public class FilterGrid extends AbstractSimpleBrowserGrid<Filter>
         private final AbstractAsyncCallback<Void> callback;
 
         public FilterListDeletionConfirmationDialog(IMessageProvider messageProvider,
-                List<Filter> data, AbstractAsyncCallback<Void> callback)
+                List<GridCustomFilter> data, AbstractAsyncCallback<Void> callback)
         {
             super(messageProvider, data, messageProvider.getMessage(Dict.DELETE_CONFIRMATION_TITLE));
             this.callback = callback;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterModel.java
index ec8f7fee2de..f7bc0253e03 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterModel.java
@@ -23,10 +23,10 @@ import com.extjs.gxt.ui.client.data.BaseModelData;
 import com.extjs.gxt.ui.client.data.ModelData;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 
 /**
- * {@link ModelData} for {@link Filter}.
+ * {@link ModelData} for {@link GridCustomFilter}.
  * 
  * @author Izabela Adamczyk
  */
@@ -35,19 +35,19 @@ public class FilterModel extends BaseModelData
 
     private static final long serialVersionUID = 1L;
 
-    public FilterModel(final Filter filter)
+    public FilterModel(final GridCustomFilter filter)
     {
         set(ModelDataPropertyNames.NAME, filter.getName());
         set(ModelDataPropertyNames.DESCRIPTION, filter.getDescription());
         set(ModelDataPropertyNames.OBJECT, filter);
     }
 
-    public final static List<FilterModel> convert(final List<Filter> filters,
+    public final static List<FilterModel> convert(final List<GridCustomFilter> filters,
             final boolean withColumnFilter)
     {
         final List<FilterModel> result = new ArrayList<FilterModel>();
 
-        for (final Filter filter : filters)
+        for (final GridCustomFilter filter : filters)
         {
             result.add(new FilterModel(filter));
         }
@@ -59,10 +59,10 @@ public class FilterModel extends BaseModelData
         return result;
     }
 
-    private static FilterModel createColumnFilter(List<Filter> basicTypes)
+    private static FilterModel createColumnFilter(List<GridCustomFilter> basicTypes)
     {
-        final Filter allSampleType = new Filter();
-        allSampleType.setName(Filter.COLUMN_FILTER);
+        final GridCustomFilter allSampleType = new GridCustomFilter();
+        allSampleType.setName(GridCustomFilter.COLUMN_FILTER);
         return new FilterModel(allSampleType);
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterSelectionWidget.java
index 9aaa72e551b..d06e6bc36a5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterSelectionWidget.java
@@ -28,7 +28,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.DropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
@@ -36,7 +36,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKin
  * 
  * @author Izabela Adamczyk
  */
-public final class FilterSelectionWidget extends DropDownList<FilterModel, Filter> implements
+public final class FilterSelectionWidget extends DropDownList<FilterModel, GridCustomFilter> implements
         IDelegatedAction
 {
     private static final String LIST_ITEMS_CALLBACK = "ListItemsCallback";
@@ -67,13 +67,13 @@ public final class FilterSelectionWidget extends DropDownList<FilterModel, Filte
     }
 
     @Override
-    protected List<FilterModel> convertItems(List<Filter> result)
+    protected List<FilterModel> convertItems(List<GridCustomFilter> result)
     {
         return FilterModel.convert(result, withStandard);
     }
 
     @Override
-    protected void loadData(AbstractAsyncCallback<List<Filter>> callback)
+    protected void loadData(AbstractAsyncCallback<List<GridCustomFilter>> callback)
     {
         viewContext.getCommonService().listFilters(displayTypeIDProvider.getGridDisplayTypeID(),
                 callback);
@@ -81,7 +81,7 @@ public final class FilterSelectionWidget extends DropDownList<FilterModel, Filte
 
     public DatabaseModificationKind[] getRelevantModifications()
     {
-        return DatabaseModificationKind.any(ObjectKind.FILTER);
+        return DatabaseModificationKind.any(ObjectKind.GRID_CUSTOM_FILTER);
     }
 
     public void execute()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterToolbar.java
index b3ea172fb96..06601dbf3aa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/filter/FilterToolbar.java
@@ -33,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDele
 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.shared.basic.dto.DatabaseModificationKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 
 /**
  * Toolbar with filters.
@@ -134,21 +134,27 @@ public class FilterToolbar<T> extends ToolBar implements IDatabaseModificationOb
 
     public boolean isColumnFilterSelected()
     {
-        Filter selected = filterSelectionWidget.tryGetSelected();
-        return (selected != null) && (selected.getName().equals(Filter.COLUMN_FILTER));
+        return getCustomFilterSelectedState(true);
     }
 
     public boolean isCustomFilterSelected()
     {
-        Filter selected = filterSelectionWidget.tryGetSelected();
-        return (selected != null) && (selected.getName().equals(Filter.COLUMN_FILTER) == false);
+        return getCustomFilterSelectedState(false);
+    }
+
+    // requiredState - true for column filter, false for custom filters
+    private boolean getCustomFilterSelectedState(boolean requiredState)
+    {
+        GridCustomFilter selected = filterSelectionWidget.tryGetSelected();
+        return (selected != null)
+                && (selected.getName().equals(GridCustomFilter.COLUMN_FILTER) == requiredState);
     }
 
     public CustomFilterInfo<T> tryGetCustomFilter()
     {
         if (isCustomFilterSelected() && isValid())
         {
-            Filter selected = filterSelectionWidget.tryGetSelected();
+            GridCustomFilter selected = filterSelectionWidget.tryGetSelected();
             CustomFilterInfo<T> info = new CustomFilterInfo<T>();
             info.setExpression(selected.getExpression());
             Set<ParameterWithValue> parameters = new HashSet<ParameterWithValue>();
@@ -174,7 +180,7 @@ public class FilterToolbar<T> extends ToolBar implements IDatabaseModificationOb
 
     private void updateFilterFields()
     {
-        Filter filter = filterSelectionWidget.tryGetSelected();
+        GridCustomFilter filter = filterSelectionWidget.tryGetSelected();
         if (filter != null)
         {
             filterContainer.removeAll();
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 a8c033d5d75..074aaa2310c 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
@@ -96,10 +96,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentTypePropertyType;
 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.Filter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -111,7 +111,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -2131,14 +2131,14 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
-    public List<Filter> listFilters(String gridId)
+    public List<GridCustomFilter> listFilters(String gridId)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
 
         try
         {
             final String sessionToken = getSessionToken();
-            final List<Filter> types = commonServer.listFilters(sessionToken, gridId);
+            final List<GridCustomFilter> types = commonServer.listFilters(sessionToken, gridId);
             return types;
         } catch (final UserFailureException e)
         {
@@ -2146,26 +2146,26 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
-    public ResultSet<Filter> listFilters(final String gridId,
-            DefaultResultSetConfig<String, Filter> resultSetConfig)
+    public ResultSet<GridCustomFilter> listFilters(final String gridId,
+            DefaultResultSetConfig<String, GridCustomFilter> resultSetConfig)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
-        return listEntities(resultSetConfig, new IOriginalDataProvider<Filter>()
+        return listEntities(resultSetConfig, new IOriginalDataProvider<GridCustomFilter>()
             {
-                public List<Filter> getOriginalData() throws UserFailureException
+                public List<GridCustomFilter> getOriginalData() throws UserFailureException
                 {
                     return listFilters(gridId);
                 }
             });
     }
 
-    public String prepareExportFilters(TableExportCriteria<Filter> criteria)
+    public String prepareExportFilters(TableExportCriteria<GridCustomFilter> criteria)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         return prepareExportEntities(criteria);
     }
 
-    public void registerFilter(NewFilter filter)
+    public void registerFilter(NewColumnOrFilter filter)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         assert filter != null : "Unspecified filter.";
@@ -2192,7 +2192,7 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
-    public final void updateFilter(final IFilterUpdates updates)
+    public final void updateFilter(final IFilterOrColumnUpdates updates)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         assert updates != null : "Unspecified updates.";
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 2098ed4b80f..2a1b87e56a1 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
@@ -197,9 +197,11 @@ public abstract class AbstractServer<T extends IServer> extends AbstractServiceW
 
     protected Session getSession(final String sessionToken)
     {
+        assert sessionToken != null : "Unspecified session token";
+
         return getSessionManager().getSession(sessionToken);
     }
-    
+
     //
     // IServer
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
index 8e9d9f09a35..c3fe29e589a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
@@ -26,7 +26,8 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.ExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ExternalDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ExternalDataTable;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.FilterBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.GridCustomColumnBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.GridCustomFilterBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.GroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IAttachmentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IAuthorizationGroupBO;
@@ -37,7 +38,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.IFilterBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IGridCustomFilterOrColumnBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable;
@@ -188,8 +189,13 @@ public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFac
         return new AuthorizationGroupBO(getDaoFactory(), session);
     }
 
-    public IFilterBO createFilterBO(Session session)
+    public IGridCustomFilterOrColumnBO createGridCustomFilterBO(Session session)
     {
-        return new FilterBO(getDaoFactory(), session);
+        return new GridCustomFilterBO(getDaoFactory(), session);
+    }
+
+    public IGridCustomFilterOrColumnBO createGridCustomColumnBO(Session session)
+    {
+        return new GridCustomColumnBO(getDaoFactory(), session);
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index b7a20486adc..8553a37c78a 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
@@ -48,7 +48,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IEntityTypePropertyTy
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.IFilterBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IGridCustomFilterOrColumnBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO;
@@ -91,10 +91,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.Filter;
 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.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -107,7 +108,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewMaterial;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
@@ -135,7 +136,8 @@ 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.FilterPE;
+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;
 import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE;
@@ -163,7 +165,6 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.DataSetTypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.DtoConverters;
 import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.ExternalDataTranslator;
-import ch.systemsx.cisd.openbis.generic.shared.translator.FilterTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.GroupTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTypeTranslator;
@@ -174,14 +175,11 @@ 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;
 
-/**
- * Implementation of client-server interface.
- * 
- * @author Franz-Josef Elmer
- */
 public final class CommonServer extends AbstractServer<ICommonServer> implements ICommonServer
 {
     private final IAuthenticationService authenticationService;
@@ -1724,25 +1722,24 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         return getDAOFactory().getEventDAO().listDeletedDataSets(lastSeenDeletionEventIdOrNull);
     }
 
-    public List<Filter> listFilters(String sessionToken, String gridId)
+    // --- grid custom filters and columns
+
+    private IGridCustomFilterOrColumnBO createGridCustomColumnBO(String sessionToken)
     {
-        checkSession(sessionToken);
-        try
-        {
-            List<FilterPE> filters = getDAOFactory().getFilterDAO().listFilters(gridId);
-            return FilterTranslator.translate(filters);
-        } catch (final DataAccessException ex)
-        {
-            throw createUserFailureException(ex);
-        }
+        final Session session = getSession(sessionToken);
+        return businessObjectFactory.createGridCustomColumnBO(session);
     }
 
-    public void registerFilter(String sessionToken, NewFilter filter)
+    private IGridCustomFilterOrColumnBO createGridCustomFilterBO(String sessionToken)
     {
         final Session session = getSession(sessionToken);
+        return businessObjectFactory.createGridCustomFilterBO(session);
+    }
+
+    private void registerFilterOrColumn(NewColumnOrFilter filter, IGridCustomFilterOrColumnBO bo)
+    {
         try
         {
-            IFilterBO bo = businessObjectFactory.createFilterBO(session);
             bo.define(filter);
             bo.save();
         } catch (final DataAccessException ex)
@@ -1751,15 +1748,13 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         }
     }
 
-    public void deleteFilters(String sessionToken, List<TechId> filterIds)
+    private void deleteFiltersOrColumns(List<TechId> filterIds, IGridCustomFilterOrColumnBO bo)
     {
-        Session session = getSession(sessionToken);
         try
         {
-            IFilterBO filterBO = businessObjectFactory.createFilterBO(session);
             for (TechId id : filterIds)
             {
-                filterBO.deleteByTechId(id);
+                bo.deleteByTechId(id);
             }
         } catch (final DataAccessException ex)
         {
@@ -1767,14 +1762,70 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         }
     }
 
-    public void updateFilter(String sessionToken, IFilterUpdates updates)
+    public List<GridCustomFilter> listFilters(String sessionToken, String gridId)
+    {
+        checkSession(sessionToken);
+        try
+        {
+            List<GridCustomFilterPE> filters =
+                    getDAOFactory().getGridCustomFilterDAO().listFilters(gridId);
+            return GridCustomFilterTranslator.translate(filters);
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
+
+    public void registerFilter(String sessionToken, NewColumnOrFilter filter)
+    {
+        IGridCustomFilterOrColumnBO bo = createGridCustomFilterBO(sessionToken);
+        registerFilterOrColumn(filter, bo);
+    }
+
+    public void deleteFilters(String sessionToken, List<TechId> filterIds)
+    {
+        IGridCustomFilterOrColumnBO bo = createGridCustomFilterBO(sessionToken);
+        deleteFiltersOrColumns(filterIds, bo);
+    }
+
+    public void updateFilter(String sessionToken, IFilterOrColumnUpdates updates)
     {
-        assert sessionToken != null : "Unspecified session token";
         assert updates != null : "Unspecified updates";
+        createGridCustomFilterBO(sessionToken).update(updates);
+    }
 
-        final Session session = getSession(sessionToken);
-        final IFilterBO filterBO = businessObjectFactory.createFilterBO(session);
-        filterBO.update(updates);
+    // -- 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);
+        registerFilterOrColumn(column, bo);
+    }
+
+    public void deleteGridCustomColumns(String sessionToken, List<TechId> columnIds)
+    {
+        IGridCustomFilterOrColumnBO bo = createGridCustomColumnBO(sessionToken);
+        deleteFiltersOrColumns(columnIds, bo);
+    }
+
+    public void updateGridCustomColumn(String sessionToken, IFilterOrColumnUpdates updates)
+    {
+        assert updates != null : "Unspecified updates";
+        createGridCustomColumnBO(sessionToken).update(updates);
     }
 
 }
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 0728383fad7..178f783efd8 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
@@ -45,10 +45,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.Filter;
+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.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Group;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -60,7 +61,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
@@ -91,7 +92,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 /**
  * Logger class for {@link CommonServer} which creates readable logs of method invocations.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 final class CommonServerLogger extends AbstractServerLogger implements ICommonServer
 {
@@ -750,13 +751,13 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 authorizationGroupId, StringUtils.join(personsCodes.toArray(new String[0]), ","));
     }
 
-    public List<Filter> listFilters(String sessionToken, String gridId)
+    public List<GridCustomFilter> listFilters(String sessionToken, String gridId)
     {
         logAccess(sessionToken, "listFilters", "GRID(%s)", gridId);
         return null;
     }
 
-    public void registerFilter(String sessionToken, NewFilter filter)
+    public void registerFilter(String sessionToken, NewColumnOrFilter filter)
     {
         logTracking(sessionToken, "registerFilter", "FILTER(%s)", filter);
     }
@@ -767,10 +768,35 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 .toArray(new TechId[0]), ","));
     }
 
-    public void updateFilter(String sessionToken, IFilterUpdates updates)
+    public void updateFilter(String sessionToken, IFilterOrColumnUpdates updates)
     {
         logTracking(sessionToken, "updateFilters", "ID(%s) NAME(%s)", updates.getId(), updates
                 .getName());
     }
 
+    // -- 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);
+    }
+
+    public void deleteGridCustomColumns(String sessionToken, List<TechId> columnIds)
+    {
+        logTracking(sessionToken, "deleteGridCustomColumns", "TECH_IDS(%s)", StringUtils.join(
+                columnIds.toArray(new TechId[0]), ","));
+    }
+
+    public void updateGridCustomColumn(String sessionToken, IFilterOrColumnUpdates updates)
+    {
+        logTracking(sessionToken, "updateGridCustomColumn", "ID(%s) NAME(%s)", updates.getId(),
+                updates.getName());
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java
index 372bdbdcd1f..34ed6d4ee3c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java
@@ -34,7 +34,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+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.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
@@ -243,9 +244,14 @@ public final class PredicateExecutor
             return daoFactory.getSampleDAO().getByTechId(techId);
         }
 
-        public FilterPE getFilter(TechId techId)
+        public GridCustomFilterPE getGridCustomFilter(TechId techId)
         {
-            return daoFactory.getFilterDAO().getByTechId(techId);
+            return daoFactory.getGridCustomFilterDAO().getByTechId(techId);
+        }
+
+        public GridCustomColumnPE getGridCustomColumn(TechId techId)
+        {
+            return daoFactory.getGridCustomColumnDAO().getByTechId(techId);
         }
 
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
index a908ff1d4f5..b66dc484a24 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
@@ -32,7 +32,8 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEventDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFileFormatTypeDAO;
-import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFilterDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomColumnDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomFilterDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGroupDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ILocatorTypeDAO;
@@ -59,7 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 /**
  * An <code>abstract</code> <i>Business Object</i>.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 abstract class AbstractBusinessObject implements IDAOFactory
 {
@@ -289,9 +290,13 @@ abstract class AbstractBusinessObject implements IDAOFactory
         return daoFactory.getPersistencyResources();
     }
 
-    public IFilterDAO getFilterDAO()
+    public IGridCustomFilterDAO getGridCustomFilterDAO()
     {
-        return daoFactory.getFilterDAO();
+        return daoFactory.getGridCustomFilterDAO();
     }
 
+    public IGridCustomColumnDAO getGridCustomColumnDAO()
+    {
+        return daoFactory.getGridCustomColumnDAO();
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomColumnBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomColumnBO.java
new file mode 100644
index 00000000000..7094a2b86df
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomColumnBO.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.business.bo;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataRetrievalFailureException;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+
+/**
+ * Operations on grid custom columns.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridCustomColumnBO extends AbstractBusinessObject implements
+        IGridCustomFilterOrColumnBO
+{
+    private static final String CUSTOM_COLUMN_ID_PREFIX = "$";
+
+    private GridCustomColumnPE column;
+
+    public GridCustomColumnBO(IDAOFactory daoFactory, Session session)
+    {
+        super(daoFactory, session);
+    }
+
+    public void define(NewColumnOrFilter newColumn) throws UserFailureException
+    {
+        column = new GridCustomColumnPE();
+        column.setCode(createUniqueCode(newColumn));
+        column.setLabel(newColumn.getName());
+
+        column.setDescription(newColumn.getDescription());
+        column.setExpression(newColumn.getExpression());
+        column.setGridId(newColumn.getGridId());
+        column.setPublic(newColumn.isPublic());
+        column.setRegistrator(findRegistrator());
+    }
+
+    private static String createUniqueCode(NewColumnOrFilter newColumn)
+    {
+        String name = newColumn.getName();
+        String code = name.replace(" ", "_");
+        code = code.toLowerCase();
+        return CUSTOM_COLUMN_ID_PREFIX + code;
+    }
+
+    public void loadDataByTechId(TechId id)
+    {
+        try
+        {
+            column = getGridCustomColumnDAO().getByTechId(id);
+        } catch (DataRetrievalFailureException exception)
+        {
+            throw new UserFailureException(exception.getMessage());
+        }
+
+    }
+
+    public void deleteByTechId(TechId groupId) throws UserFailureException
+    {
+        loadDataByTechId(groupId);
+        try
+        {
+            getGridCustomColumnDAO().delete(column);
+        } catch (final DataAccessException ex)
+        {
+            throwException(ex, String.format("Column '%s'", column));
+        }
+    }
+
+    public void save() throws UserFailureException
+    {
+        assert column != null : "Column not defined";
+        try
+        {
+            getGridCustomColumnDAO().createColumn(column);
+        } catch (final DataAccessException e)
+        {
+            throwException(e, "Column '" + column + "'");
+        }
+    }
+
+    public void update(IFilterOrColumnUpdates updates)
+    {
+        loadDataByTechId(TechId.create(updates));
+
+        column.setLabel(updates.getName());
+        column.setDescription(updates.getDescription());
+        column.setExpression(updates.getExpression());
+        column.setPublic(updates.isPublic());
+
+        validateAndSave();
+    }
+
+    private void validateAndSave()
+    {
+        getGridCustomColumnDAO().validateAndSaveUpdatedEntity(column);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/FilterBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomFilterBO.java
similarity index 75%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/FilterBO.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomFilterBO.java
index 39de61298bd..d2e86239635 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/FilterBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomFilterBO.java
@@ -22,28 +22,29 @@ import org.springframework.dao.DataRetrievalFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 
 /**
- * {@link IFilterBO} implementation.
+ * Operations on grid custom filters.
  * 
  * @author Izabela Adamczyk
  */
-public class FilterBO extends AbstractBusinessObject implements IFilterBO
+public class GridCustomFilterBO extends AbstractBusinessObject implements
+        IGridCustomFilterOrColumnBO
 {
-    private FilterPE filter;
+    private GridCustomFilterPE filter;
 
-    public FilterBO(IDAOFactory daoFactory, Session session)
+    public GridCustomFilterBO(IDAOFactory daoFactory, Session session)
     {
         super(daoFactory, session);
     }
 
-    public void define(NewFilter newFilter) throws UserFailureException
+    public void define(NewColumnOrFilter newFilter) throws UserFailureException
     {
-        filter = new FilterPE();
+        filter = new GridCustomFilterPE();
         filter.setDescription(newFilter.getDescription());
         filter.setExpression(newFilter.getExpression());
         filter.setGridId(newFilter.getGridId());
@@ -56,7 +57,7 @@ public class FilterBO extends AbstractBusinessObject implements IFilterBO
     {
         try
         {
-            filter = getFilterDAO().getByTechId(id);
+            filter = getGridCustomFilterDAO().getByTechId(id);
         } catch (DataRetrievalFailureException exception)
         {
             throw new UserFailureException(exception.getMessage());
@@ -69,7 +70,7 @@ public class FilterBO extends AbstractBusinessObject implements IFilterBO
         loadDataByTechId(groupId);
         try
         {
-            getFilterDAO().delete(filter);
+            getGridCustomFilterDAO().delete(filter);
         } catch (final DataAccessException ex)
         {
             throwException(ex, String.format("Filter '%s'", filter.getName()));
@@ -81,14 +82,14 @@ public class FilterBO extends AbstractBusinessObject implements IFilterBO
         assert filter != null : "Filter not defined";
         try
         {
-            getFilterDAO().createFilter(filter);
+            getGridCustomFilterDAO().createFilter(filter);
         } catch (final DataAccessException e)
         {
             throwException(e, "Filter '" + filter + "'");
         }
     }
 
-    public void update(IFilterUpdates updates)
+    public void update(IFilterOrColumnUpdates updates)
     {
         loadDataByTechId(TechId.create(updates));
 
@@ -102,7 +103,7 @@ public class FilterBO extends AbstractBusinessObject implements IFilterBO
 
     private void validateAndSave()
     {
-        getFilterDAO().validateAndSaveUpdatedEntity(filter);
+        getGridCustomFilterDAO().validateAndSaveUpdatedEntity(filter);
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
index f74166c0896..c858f413aaf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
@@ -68,7 +68,9 @@ public interface ICommonBusinessObjectFactory
 
     public IAuthorizationGroupBO createAuthorizationGroupBO(Session session);
 
-    public IFilterBO createFilterBO(final Session session);
+    public IGridCustomFilterOrColumnBO createGridCustomFilterBO(final Session session);
+
+    public IGridCustomFilterOrColumnBO createGridCustomColumnBO(final Session session);
 
     // Fast listing operations
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IFilterBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IGridCustomFilterOrColumnBO.java
similarity index 60%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IFilterBO.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IGridCustomFilterOrColumnBO.java
index b6671503445..02f6c1a09d2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IFilterBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IGridCustomFilterOrColumnBO.java
@@ -18,26 +18,27 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 
 /**
- * Business object of a filter. Holds an instance of {@link FilterPE}.
+ * Business object of a filter. Holds an instance of {@link GridCustomFilterPE}.
  * 
  * @author Izabela Adamczyk
  */
-public interface IFilterBO extends IEntityBusinessObject
+public interface IGridCustomFilterOrColumnBO extends IEntityBusinessObject
 {
 
     /**
-     * Defines a new filter. After invocation of this method {@link IBusinessObject#save()} should
-     * be invoked to store the new group in the <i>Data Access Layer</i>.
+     * Defines a new grid custom filter or column. After invocation of this method
+     * {@link IBusinessObject#save()} should be invoked to store the new group in the <i>Data Access
+     * Layer</i>.
      */
-    public void define(NewFilter filter) throws UserFailureException;
+    public void define(NewColumnOrFilter filterOrColumn) throws UserFailureException;
 
     /**
-     * Deletes filter.
+     * Deletes grid custom filter or column.
      * 
      * @param groupId group technical identifier
      * @throws UserFailureException if filter with given technical identifier is not found.
@@ -45,8 +46,8 @@ public interface IFilterBO extends IEntityBusinessObject
     public void deleteByTechId(TechId groupId);
 
     /**
-     * Updates the filter.
+     * Updates the grid custom filter or column.
      */
-    public void update(IFilterUpdates updates);
+    public void update(IFilterOrColumnUpdates updates);
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java
index f474261a1ec..733d7dea280 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java
@@ -23,7 +23,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 /**
  * Factory definition for all Data Access Objects which are needed for managing authorization.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public interface IAuthorizationDAOFactory
 {
@@ -36,58 +36,32 @@ public interface IAuthorizationDAOFactory
     public DatabaseInstancePE getHomeDatabaseInstance();
 
     /**
-     * Returns the <code>IPersonDAO</code> implementation.
+     * Disables interaction with the second level cache for the current Hibernate session.
      */
-    public IPersonDAO getPersonDAO();
+    public void disableSecondLevelCacheForSession();
 
     /**
-     * @return The implementation of the {@link IGroupDAO}.
+     * Returns the Hibernate session factory.
      */
+    public SessionFactory getSessionFactory();
+
+    public IPersonDAO getPersonDAO();
+
     public IGroupDAO getGroupDAO();
 
-    /**
-     * @return The implementation of the {@link IDatabaseInstanceDAO}.
-     */
     public IDatabaseInstanceDAO getDatabaseInstanceDAO();
 
-    /**
-     * @return The implementation of the {@link IRoleAssignmentDAO}.
-     */
     public IRoleAssignmentDAO getRoleAssignmentDAO();
 
-    /**
-     * Returns the {@link IExternalDataDAO} implementation.
-     */
     public IExternalDataDAO getExternalDataDAO();
 
-    /**
-     * Returns the implementation of {@link IExperimentDAO}.
-     */
     public IExperimentDAO getExperimentDAO();
 
-    /**
-     * Returns the implementation of {@link IProjectDAO}.
-     */
     public IProjectDAO getProjectDAO();
 
-    /**
-     * Returns the implementation of {@link ISampleDAO}.
-     */
     public ISampleDAO getSampleDAO();
 
-    /**
-     * Returns an implementation of {@link IFilterDAO}.
-     */
-    public IFilterDAO getFilterDAO();
-
-    /**
-     * Disables interaction with the second level cache for the current Hibernate session.
-     */
-    public void disableSecondLevelCacheForSession();
-
-    /**
-     * Returns the Hibernate session factory.
-     */
-    public SessionFactory getSessionFactory();
+    public IGridCustomFilterDAO getGridCustomFilterDAO();
 
+    public IGridCustomColumnDAO getGridCustomColumnDAO();
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomColumnDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomColumnDAO.java
new file mode 100644
index 00000000000..c0a5adc242d
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomColumnDAO.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE;
+
+/**
+ * <i>Data Access Object</i> for {@link GridCustomColumnPE}.
+ * 
+ * @author Tomasz Pylak
+ */
+public interface IGridCustomColumnDAO extends IGenericDAO<GridCustomColumnPE>
+{
+
+    /**
+     * Lists columns for given grid and home database instance.
+     */
+    public List<GridCustomColumnPE> listColumns(String gridId);
+
+    /**
+     * Creates a new column in home database instance.
+     */
+    public void createColumn(GridCustomColumnPE filter);
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IFilterDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomFilterDAO.java
similarity index 63%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IFilterDAO.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomFilterDAO.java
index b96b4e4eb69..34d1611a41a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IFilterDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IGridCustomFilterDAO.java
@@ -18,23 +18,23 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess;
 
 import java.util.List;
 
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 
 /**
- * <i>Data Access Object</i> for {@link FilterPE}.
+ * <i>Data Access Object</i> for {@link GridCustomFilterPE}.
  * 
  * @author Izabela Adamczyk
  */
-public interface IFilterDAO extends IGenericDAO<FilterPE>
+public interface IGridCustomFilterDAO extends IGenericDAO<GridCustomFilterPE>
 {
 
     /**
-     * Lists filters for given grid and home database instance.
+     * Lists columns for given grid and home database instance.
      */
-    public List<FilterPE> listFilters(String gridId);
+    public List<GridCustomFilterPE> listFilters(String gridId);
 
     /**
-     * Creates a new filter in home database instance.
+     * Creates a new column in home database instance.
      */
-    public void createFilter(FilterPE filter);
+    public void createFilter(GridCustomFilterPE filter);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java
index d38115cd13d..9dc65786413 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java
@@ -31,7 +31,8 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAuthorizationDAOFacto
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDatabaseInstanceDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
-import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFilterDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomColumnDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomFilterDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGroupDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPersonDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO;
@@ -44,7 +45,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.UuidUtil;
 /**
  * Super class of all DAO factories which extend {@link IAuthorizationDAOFactory}.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public class AuthorizationDAOFactory implements IAuthorizationDAOFactory
 {
@@ -69,7 +70,9 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory
 
     private final ISampleDAO sampleDAO;
 
-    private final IFilterDAO filterDAO;
+    private final IGridCustomFilterDAO gridCustomFilterDAO;
+
+    private final IGridCustomColumnDAO gridCustomColumnDAO;
 
     private final PersistencyResources persistencyResources;
 
@@ -86,7 +89,8 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory
         experimentDAO = new ExperimentDAO(sessionFactory, homeDatabaseInstance);
         projectDAO = new ProjectDAO(sessionFactory, homeDatabaseInstance);
         sampleDAO = new SampleDAO(sessionFactory, homeDatabaseInstance);
-        filterDAO = new FilterDAO(sessionFactory, homeDatabaseInstance);
+        gridCustomFilterDAO = new GridCustomFilterDAO(sessionFactory, homeDatabaseInstance);
+        gridCustomColumnDAO = new GridCustomColumnDAO(sessionFactory, homeDatabaseInstance);
     }
 
     public final PersistencyResources getPersistencyResources()
@@ -203,9 +207,14 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory
         return sampleDAO;
     }
 
-    public IFilterDAO getFilterDAO()
+    public IGridCustomFilterDAO getGridCustomFilterDAO()
+    {
+        return gridCustomFilterDAO;
+    }
+
+    public IGridCustomColumnDAO getGridCustomColumnDAO()
     {
-        return filterDAO;
+        return gridCustomColumnDAO;
     }
 
     public void disableSecondLevelCacheForSession()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAO.java
new file mode 100644
index 00000000000..a233b779523
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAO.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Restrictions;
+
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.utilities.MethodUtils;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomColumnDAO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE;
+
+/**
+ * Hibernate-based implementation of {@link IGridCustomColumnDAO}.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridCustomColumnDAO extends AbstractGenericEntityDAO<GridCustomColumnPE> implements
+        IGridCustomColumnDAO
+{
+
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, GridCustomColumnDAO.class);
+
+    public GridCustomColumnDAO(SessionFactory sessionFactory, DatabaseInstancePE databaseInstance)
+    {
+        super(sessionFactory, databaseInstance, GridCustomColumnPE.class);
+    }
+
+    public void createColumn(GridCustomColumnPE column)
+    {
+        assert column != null : "Unspecified column";
+        assert column.getDatabaseInstance() == null;
+        column.setDatabaseInstance(getDatabaseInstance());
+
+        persist(column);
+    }
+
+    public List<GridCustomColumnPE> listColumns(String gridId)
+    {
+        assert gridId != null : "Unspecified grid ID.";
+
+        final DetachedCriteria criteria = DetachedCriteria.forClass(getEntityClass());
+        criteria.add(Restrictions.eq("databaseInstance", getDatabaseInstance()));
+        criteria.add(Restrictions.eq("gridId", gridId));
+        final List<GridCustomColumnPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format("%s(%s): %d column(s) have been found.", MethodUtils
+                    .getCurrentMethod().getName(), gridId, list.size()));
+        }
+        return list;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/FilterDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomFilterDAO.java
similarity index 66%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/FilterDAO.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomFilterDAO.java
index 2c08c39fb59..f62c8f28588 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/FilterDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomFilterDAO.java
@@ -26,27 +26,28 @@ import org.hibernate.criterion.Restrictions;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.utilities.MethodUtils;
-import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFilterDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomFilterDAO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 
 /**
- * Hibernate-based implementation of {@link IFilterDAO}.
+ * Hibernate-based implementation of {@link IGridCustomFilterDAO}.
  * 
  * @author Izabela Adamczyk
  */
-public class FilterDAO extends AbstractGenericEntityDAO<FilterPE> implements IFilterDAO
+public class GridCustomFilterDAO extends AbstractGenericEntityDAO<GridCustomFilterPE> implements
+        IGridCustomFilterDAO
 {
 
     private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, FilterDAO.class);
+            LogFactory.getLogger(LogCategory.OPERATION, GridCustomFilterDAO.class);
 
-    public FilterDAO(SessionFactory sessionFactory, DatabaseInstancePE databaseInstance)
+    public GridCustomFilterDAO(SessionFactory sessionFactory, DatabaseInstancePE databaseInstance)
     {
-        super(sessionFactory, databaseInstance, FilterPE.class);
+        super(sessionFactory, databaseInstance, GridCustomFilterPE.class);
     }
 
-    public void createFilter(FilterPE filter)
+    public void createFilter(GridCustomFilterPE filter)
     {
         assert filter != null : "Unspecified filter";
         assert filter.getDatabaseInstance() == null;
@@ -55,17 +56,17 @@ public class FilterDAO extends AbstractGenericEntityDAO<FilterPE> implements IFi
         persist(filter);
     }
 
-    public List<FilterPE> listFilters(String gridId)
+    public List<GridCustomFilterPE> listFilters(String gridId)
     {
         assert gridId != null : "Unspecified grid ID.";
 
         final DetachedCriteria criteria = DetachedCriteria.forClass(getEntityClass());
         criteria.add(Restrictions.eq("databaseInstance", getDatabaseInstance()));
         criteria.add(Restrictions.eq("gridId", gridId));
-        final List<FilterPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
+        final List<GridCustomFilterPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
         if (operationLog.isDebugEnabled())
         {
-            operationLog.debug(String.format("%s(%s): %d filters(s) have been found.", MethodUtils
+            operationLog.debug(String.format("%s(%s): %d filter(s) have been found.", MethodUtils
                     .getCurrentMethod().getName(), gridId, list.size()));
         }
         return list;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 7fa0099ce43..55bb2ec537d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -28,18 +28,20 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ReturnVa
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.DataSetCodePredicate;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.FilterUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.GroupIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSampleCriteriaPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ProjectUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleTechIdPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.DeleteGridCustomColumnPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.DeleteGridCustomFilterPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.UpdateGridCustomColumnPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.UpdateGridCustomFilterPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.DataSetTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.ExperimentTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.GroupTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.ProjectTechIdPredicate;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.FilterTechIdPredicate.DeleteFilterTechIdPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.CustomGridExpressionValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.ExternalDataValidator;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.FilterValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.GroupValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.MatchingEntityValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.ProjectValidator;
@@ -63,10 +65,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.Filter;
 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.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -78,7 +81,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -103,7 +106,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 /**
  * Definition of the client-server interface.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public interface ICommonServer extends IServer
 {
@@ -913,34 +916,72 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleSet.OBSERVER)
-    @ReturnValueFilter(validatorClass = FilterValidator.class)
-    public List<Filter> listFilters(String sessionToken, String gridId);
+    @ReturnValueFilter(validatorClass = CustomGridExpressionValidator.class)
+    public List<GridCustomFilter> listFilters(String sessionToken, String gridId);
 
     /**
      * Creates a new filter.
      */
     @Transactional
     @RolesAllowed(RoleSet.POWER_USER)
-    @DatabaseCreateOrDeleteModification(value = ObjectKind.FILTER)
-    public void registerFilter(String sessionToken, NewFilter filter);
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_FILTER)
+    public void registerFilter(String sessionToken, NewColumnOrFilter filter);
 
     /**
      * Deletes specified filters.
      */
     @Transactional
     @RolesAllowed(RoleSet.POWER_USER)
-    @DatabaseCreateOrDeleteModification(value = ObjectKind.FILTER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_FILTER)
     public void deleteFilters(
             String sessionToken,
-            @AuthorizationGuard(guardClass = DeleteFilterTechIdPredicate.class) List<TechId> filterIds);
+            @AuthorizationGuard(guardClass = DeleteGridCustomFilterPredicate.class) List<TechId> filterIds);
 
     /**
      * Updates a filter.
      */
     @Transactional
     @RolesAllowed(RoleSet.POWER_USER)
-    @DatabaseUpdateModification(value = ObjectKind.FILTER)
-    public void updateFilter(String sessionToken,
-            @AuthorizationGuard(guardClass = FilterUpdatesPredicate.class) IFilterUpdates updates);
+    @DatabaseUpdateModification(value = ObjectKind.GRID_CUSTOM_FILTER)
+    public void updateFilter(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = UpdateGridCustomFilterPredicate.class) IFilterOrColumnUpdates updates);
+
+    // columns
+
+    /**
+     * Lists columns available for selected grid.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.OBSERVER)
+    @ReturnValueFilter(validatorClass = CustomGridExpressionValidator.class)
+    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId);
+
+    /**
+     * Creates a new column.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_COLUMN)
+    public void registerGridCustomColumn(String sessionToken, NewColumnOrFilter column);
 
+    /**
+     * Deletes specified columns.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_COLUMN)
+    public void deleteGridCustomColumns(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = DeleteGridCustomColumnPredicate.class) List<TechId> columnIds);
+
+    /**
+     * Updates a column.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseUpdateModification(value = ObjectKind.GRID_CUSTOM_COLUMN)
+    public void updateGridCustomColumn(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = UpdateGridCustomColumnPredicate.class) IFilterOrColumnUpdates updates);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java
index 5ae13508d5f..252d85f7b3a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java
@@ -20,7 +20,8 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.IDatabaseInstanceFinder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+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.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
@@ -28,7 +29,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 /**
  * Interface of providers of data needed for authorization.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public interface IAuthorizationDataProvider extends IDatabaseInstanceFinder
 {
@@ -59,6 +60,11 @@ public interface IAuthorizationDataProvider extends IDatabaseInstanceFinder
     /**
      * Returns the filter with given <var>techId</var>
      */
-    public FilterPE getFilter(TechId techId);
+    public GridCustomFilterPE getGridCustomFilter(TechId techId);
+
+    /**
+     * Returns the grid custom column with given <var>techId</var>
+     */
+    public GridCustomColumnPE getGridCustomColumn(TechId techId);
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractGridExpressionPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractGridExpressionPredicate.java
new file mode 100644
index 00000000000..b71fc3e00f9
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractGridExpressionPredicate.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.authorization.predicate;
+
+import java.util.List;
+import java.util.Set;
+
+import ch.systemsx.cisd.common.exceptions.Status;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationDataProvider;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.RoleWithIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.dto.AbstractGridExpressionPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
+
+/**
+ * An <code>IPredicate</code> implementation based on {@link AbstractGridExpressionPE} of a grid
+ * custom filter or column. Public internal class provide predicates for deletions based on
+ * {@link TechId} and updates base on {@link IFilterOrColumnUpdates}.
+ * 
+ * @author Piotr Buczek
+ * @author Tomasz Pylak
+ */
+
+abstract public class AbstractGridExpressionPredicate<T> extends AbstractPredicate<T>
+{
+
+    public static class DeleteGridCustomFilterPredicate extends
+            AbstractGridExpressionPredicate<TechId>
+    {
+        public DeleteGridCustomFilterPredicate()
+        {
+            super("delete grid custom filter");
+        }
+
+        @Override
+        public AbstractGridExpressionPE<?> convert(TechId techId)
+        {
+            return authorizationDataProvider.getGridCustomFilter(techId);
+        }
+    }
+
+    public static class DeleteGridCustomColumnPredicate extends
+            AbstractGridExpressionPredicate<TechId>
+    {
+        public DeleteGridCustomColumnPredicate()
+        {
+            super("delete grid custom column");
+        }
+
+        @Override
+        public AbstractGridExpressionPE<?> convert(TechId techId)
+        {
+            return authorizationDataProvider.getGridCustomColumn(techId);
+        }
+    }
+
+    public static class UpdateGridCustomFilterPredicate extends
+            AbstractGridExpressionPredicate<IFilterOrColumnUpdates>
+    {
+        public UpdateGridCustomFilterPredicate()
+        {
+            super("update grid custom filter");
+        }
+
+        @Override
+        public AbstractGridExpressionPE<?> convert(IFilterOrColumnUpdates criteria)
+        {
+            TechId techId = TechId.create(criteria);
+            return authorizationDataProvider.getGridCustomFilter(techId);
+        }
+    }
+
+    public static class UpdateGridCustomColumnPredicate extends
+            AbstractGridExpressionPredicate<IFilterOrColumnUpdates>
+    {
+        public UpdateGridCustomColumnPredicate()
+        {
+            super("update grid custom column");
+        }
+
+        @Override
+        public AbstractGridExpressionPE<?> convert(IFilterOrColumnUpdates criteria)
+        {
+            TechId techId = TechId.create(criteria);
+            return authorizationDataProvider.getGridCustomColumn(techId);
+        }
+    }
+
+    abstract protected AbstractGridExpressionPE<?> convert(T value);
+
+    private final String description;
+
+    protected IAuthorizationDataProvider authorizationDataProvider;
+
+    public AbstractGridExpressionPredicate(String description)
+    {
+        this.description = description;
+    }
+
+    //
+    // AbstractPredicate
+    //
+
+    @Override
+    public final String getCandidateDescription()
+    {
+        return description;
+    }
+
+    public void init(IAuthorizationDataProvider provider)
+    {
+        this.authorizationDataProvider = provider;
+    }
+
+    @Override
+    final Status doEvaluation(final PersonPE person, final List<RoleWithIdentifier> allowedRoles,
+            final T value)
+    {
+        AbstractGridExpressionPE<?> gridExpression = convert(value);
+        final boolean matching = isMatching(person, gridExpression);
+        if (matching)
+        {
+            return Status.OK;
+        }
+        String userId = person.getUserId();
+        return Status.createError(createErrorMsg(gridExpression, userId));
+    }
+
+    private static boolean isMatching(PersonPE person, AbstractGridExpressionPE<?> gridExpression)
+    {
+        // needs to be an instance admin in filter database instance or registrator of a filter
+        return isRegistrator(person, gridExpression)
+                || isInstanceAdmin(person, gridExpression.getDatabaseInstance());
+    }
+
+    private String createErrorMsg(AbstractGridExpressionPE<?> gridExpression, String userId)
+    {
+        return String.format("User '%s' does not have enough privileges to"
+                + " perform update/delete operation on custom grid filter/column "
+                + " '%s'. One needs to be either registrator or database instance admin.", userId,
+                gridExpression);
+    }
+
+    private static boolean isRegistrator(final PersonPE person,
+            final AbstractGridExpressionPE<?> gridExpression)
+    {
+        return person.equals(gridExpression.getRegistrator());
+    }
+
+    private static boolean isInstanceAdmin(final PersonPE person,
+            final DatabaseInstancePE databaseInstance)
+    {
+        final Set<RoleAssignmentPE> roleAssignments = person.getAllPersonRoles();
+        for (final RoleAssignmentPE roleAssignment : roleAssignments)
+        {
+            final DatabaseInstancePE roleInstance = roleAssignment.getDatabaseInstance();
+            if (databaseInstance.equals(roleInstance))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterTechIdPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterTechIdPredicate.java
deleted file mode 100644
index c14d43a8870..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterTechIdPredicate.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2009 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.generic.shared.authorization.predicate;
-
-import java.util.List;
-import java.util.Set;
-
-import ch.systemsx.cisd.common.exceptions.Status;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.RoleWithIdentifier;
-import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
-
-/**
- * An <code>IPredicate</code> implementation based on {@link TechId} of a filter.
- * 
- * @author Piotr Buczek
- */
-
-public abstract class FilterTechIdPredicate extends AbstractDatabaseInstancePredicate<TechId>
-{
-
-    public static class UpdateFilterTechIdPredicate extends FilterTechIdPredicate
-    {
-        public UpdateFilterTechIdPredicate()
-        {
-            super(OperationKind.MODIFY);
-        }
-    }
-
-    public static class DeleteFilterTechIdPredicate extends FilterTechIdPredicate
-    {
-        public DeleteFilterTechIdPredicate()
-        {
-            super(OperationKind.DELETE);
-        }
-    }
-
-    private static enum OperationKind
-    {
-        MODIFY, DELETE;
-
-        public String getDescription()
-        {
-            return name().toLowerCase();
-        }
-    }
-
-    private final OperationKind operationKind;
-
-    public FilterTechIdPredicate(OperationKind operationKind)
-    {
-        this.operationKind = operationKind;
-    }
-
-    //
-    // AbstractPredicate
-    //
-
-    @Override
-    public final String getCandidateDescription()
-    {
-        return "filter technical id";
-    }
-
-    @Override
-    final Status doEvaluation(final PersonPE person, final List<RoleWithIdentifier> allowedRoles,
-            final TechId techId)
-    {
-
-        final FilterPE filter = authorizationDataProvider.getFilter(techId);
-        final boolean matching = isMatching(person, filter);
-        if (matching)
-        {
-            return Status.OK;
-        }
-        String userId = person.getUserId();
-        return Status.createError(createErrorMsg(filter, userId));
-    }
-
-    private static boolean isMatching(PersonPE person, FilterPE filter)
-    {
-        // needs to be an instance admin in filter database instance or registrator of a filter
-        return isRegistrator(person, filter)
-                || isInstanceAdmin(person, filter.getDatabaseInstance());
-    }
-
-    private String createErrorMsg(FilterPE filter, String userId)
-    {
-        return String
-                .format(
-                        STATUS_MESSAGE_PREFIX_FORMAT
-                                + operationKind.getDescription()
-                                + " filter '%s'. One needs to be either filter registrator or database instance admin.",
-                        userId, filter.getName());
-    }
-
-    private static boolean isRegistrator(final PersonPE person, final FilterPE filter)
-    {
-        return person.equals(filter.getRegistrator());
-    }
-
-    private static boolean isInstanceAdmin(final PersonPE person,
-            final DatabaseInstancePE databaseInstance)
-    {
-        final Set<RoleAssignmentPE> roleAssignments = person.getAllPersonRoles();
-        for (final RoleAssignmentPE roleAssignment : roleAssignments)
-        {
-            final DatabaseInstancePE roleInstance = roleAssignment.getDatabaseInstance();
-            if (databaseInstance.equals(roleInstance))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterUpdatesPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterUpdatesPredicate.java
deleted file mode 100644
index 8c58723fe4f..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/FilterUpdatesPredicate.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2008 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.generic.shared.authorization.predicate;
-
-import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.FilterTechIdPredicate.UpdateFilterTechIdPredicate;
-import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
-
-/**
- * An <code>IPredicate</code> implementation for {@link IFilterUpdates}.
- * 
- * @author Piotr Buczek
- */
-public class FilterUpdatesPredicate extends DelegatedPredicate<TechId, IFilterUpdates>
-{
-    public FilterUpdatesPredicate()
-    {
-        super(new UpdateFilterTechIdPredicate());
-    }
-
-    //
-    // DelegatedPredicate
-    //
-
-    @Override
-    public final TechId convert(final IFilterUpdates value)
-    {
-        TechId filterId = TechId.create(value);
-        return filterId;
-    }
-
-    @Override
-    public final String getCandidateDescription()
-    {
-        return "filter updates";
-    }
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/FilterValidator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/CustomGridExpressionValidator.java
similarity index 80%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/FilterValidator.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/CustomGridExpressionValidator.java
index 838782b9891..479ef6726c0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/FilterValidator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/CustomGridExpressionValidator.java
@@ -18,8 +18,9 @@ package ch.systemsx.cisd.openbis.generic.shared.authorization.validator;
 
 import java.util.Set;
 
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractGridExpression;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
@@ -27,25 +28,27 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 
 /**
- * A {@link IValidator} implementation suitable for {@link Filter}.
+ * A {@link IValidator} implementation for grid custom filter or column. Public internal class
+ * provide predicates for updates and deletions based on {@link TechId}.
  * 
  * @author Izabela Adamczyk
  */
-public final class FilterValidator extends AbstractValidator<Filter>
+public final class CustomGridExpressionValidator extends
+        AbstractValidator<AbstractGridExpression>
 {
     //
     // IValidator
     //
 
     @Override
-    public final boolean doValidation(final PersonPE person, final Filter value)
+    public final boolean doValidation(final PersonPE person, final AbstractGridExpression value)
     {
         return value.isPublic() || isRegistrator(person, value)
                 || isInstanceAdmin(person, value.getDatabaseInstance());
 
     }
 
-    private boolean isRegistrator(final PersonPE person, final Filter value)
+    private boolean isRegistrator(final PersonPE person, final AbstractGridExpression value)
     {
         Person registrator = value.getRegistrator();
         return person.getUserId().equals(registrator.getUserId())
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Filter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java
similarity index 76%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Filter.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java
index 3038286aa66..dcc243931ef 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Filter.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractGridExpression.java
@@ -18,24 +18,19 @@ package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
 import java.io.Serializable;
 import java.util.Date;
-import java.util.Set;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
- * Stores information describing the filter.
+ * Stores information describing the common part of grid custom filter and column.
  * 
  * @author Izabela Adamczyk
  */
-public class Filter extends AbstractRegistrationHolder implements IsSerializable, Serializable,
-        IFilterUpdates
+public abstract class AbstractGridExpression extends AbstractRegistrationHolder implements
+        IsSerializable, Serializable, IFilterOrColumnUpdates
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
-    public static final String COLUMN_FILTER = "Column Filter";
-
-    private String name;
-
     private String expression;
 
     private boolean isPublic;
@@ -48,20 +43,8 @@ public class Filter extends AbstractRegistrationHolder implements IsSerializable
 
     private DatabaseInstance databaseInstance;
 
-    private Set<String> parameters;
-
-    public Filter()
-    {
-    }
-
-    public String getName()
-    {
-        return name;
-    }
-
-    public void setName(String name)
+    public AbstractGridExpression()
     {
-        this.name = name;
     }
 
     public String getExpression()
@@ -123,15 +106,4 @@ public class Filter extends AbstractRegistrationHolder implements IsSerializable
     {
         this.databaseInstance = databaseInstance;
     }
-
-    public Set<String> getParameters()
-    {
-        return parameters;
-    }
-
-    public void setParameters(Set<String> parameters)
-    {
-        this.parameters = parameters;
-    }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java
index d952f918451..a2648932dfe 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java
@@ -34,7 +34,8 @@ public class DatabaseModificationKind implements IsSerializable
     {
         AUTHORIZATION_GROUP, SAMPLE, EXPERIMENT, MATERIAL, DATA_SET, SAMPLE_TYPE, EXPERIMENT_TYPE,
         MATERIAL_TYPE, DATASET_TYPE, FILE_FORMAT_TYPE, PROJECT, GROUP, PROPERTY_TYPE,
-        PROPERTY_TYPE_ASSIGNMENT, VOCABULARY, VOCABULARY_TERM, ROLE_ASSIGNMENT, PERSON, FILTER
+        PROPERTY_TYPE_ASSIGNMENT, VOCABULARY, VOCABULARY_TERM, ROLE_ASSIGNMENT, PERSON,
+        GRID_CUSTOM_FILTER, GRID_CUSTOM_COLUMN
     }
 
     public enum OperationKind implements IsSerializable
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomColumn.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomColumn.java
new file mode 100644
index 00000000000..8fa78f6f997
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomColumn.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+/**
+ * Stores information describing the grid custom column.
+ * 
+ * @author Tomasz Pylak
+ */
+public class GridCustomColumn extends AbstractGridExpression
+{
+
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private String code;
+
+    private String label;
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getLabel()
+    {
+        return label;
+    }
+
+    public void setLabel(String label)
+    {
+        this.label = label;
+    }
+
+    public String getName()
+    {
+        return label;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomFilter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomFilter.java
new file mode 100644
index 00000000000..d7365f6f940
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/GridCustomFilter.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import java.util.Set;
+
+/**
+ * Stores information describing the grid custom filter.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class GridCustomFilter extends AbstractGridExpression
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    /** Name of the standard filter kind which is available for all grids */
+    public static final String COLUMN_FILTER = "Column Filter";
+
+    private String name;
+
+    private Set<String> parameters;
+
+    public GridCustomFilter()
+    {
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public Set<String> getParameters()
+    {
+        return parameters;
+    }
+
+    public void setParameters(Set<String> parameters)
+    {
+        this.parameters = parameters;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IFilterUpdates.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IFilterOrColumnUpdates.java
similarity index 80%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IFilterUpdates.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IFilterOrColumnUpdates.java
index 29632f6eb99..55de852339b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IFilterUpdates.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IFilterOrColumnUpdates.java
@@ -19,17 +19,17 @@ package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 
 /**
- * Description of the updates which should be performed on a filter.
+ * Description of the updates which should be performed on a grid custom filter or column.
  * 
  * @author Piotr Buczek
  */
-public interface IFilterUpdates extends IIdHolder
+public interface IFilterOrColumnUpdates extends IIdHolder
 {
     String getDescription();
 
     String getExpression();
 
-    String getName();
+    String getName(); // filter name or column label
 
     boolean isPublic();
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewFilter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewColumnOrFilter.java
similarity index 92%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewFilter.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewColumnOrFilter.java
index 04007e658df..611b1e084ed 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewFilter.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewColumnOrFilter.java
@@ -21,11 +21,11 @@ import java.io.Serializable;
 import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
- * A filter to register.
+ * A custom grid filter or column to register.
  * 
  * @author Izabela Adamczyk
  */
-public class NewFilter implements IsSerializable, Serializable
+public class NewColumnOrFilter implements IsSerializable, Serializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
@@ -39,7 +39,7 @@ public class NewFilter implements IsSerializable, Serializable
 
     private String gridId;
 
-    public NewFilter()
+    public NewColumnOrFilter()
     {
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/FilterPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AbstractGridExpressionPE.java
similarity index 61%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/FilterPE.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AbstractGridExpressionPE.java
index a495d6194b7..a7253595a3c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/FilterPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AbstractGridExpressionPE.java
@@ -20,43 +20,37 @@ import java.io.Serializable;
 import java.util.Date;
 
 import javax.persistence.Column;
-import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
 import javax.persistence.SequenceGenerator;
-import javax.persistence.Table;
 import javax.persistence.Version;
 
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.apache.commons.lang.builder.ToStringBuilder;
 import org.hibernate.validator.Length;
 import org.hibernate.validator.NotNull;
 
-import ch.systemsx.cisd.common.utilities.ModifiedShortPrefixToStringStyle;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
- * Persistence Entity describing the filter.
+ * Persistence Entity describing the grid custom filter or column.
  * 
- * @author Izabela Adamczyk
+ * @author Tomasz Pylak
  */
-@Entity
-@Table(name = TableNames.FILTERS_TABLE)
-public class FilterPE extends HibernateAbstractRegistrationHolder implements IIdHolder,
-        Comparable<FilterPE>, Serializable
+@MappedSuperclass
+public abstract class AbstractGridExpressionPE<T> extends HibernateAbstractRegistrationHolder
+        implements IIdHolder, Comparable<T>, Serializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
     private String gridId;
 
-    private String name;
+    private String description;
 
     private String expression;
 
@@ -64,23 +58,20 @@ public class FilterPE extends HibernateAbstractRegistrationHolder implements IId
 
     private Date modificationDate;
 
-    private String description;
-
     private DatabaseInstancePE databaseInstance;
 
     private Long id;
 
-    @Column(name = ColumnNames.NAME_COLUMN)
-    @NotNull(message = ValidationMessages.NAME_NOT_NULL_MESSAGE)
-    @Length(min = 1, max = 100, message = ValidationMessages.NAME_LENGTH_MESSAGE)
-    public String getName()
+    @Column(name = ColumnNames.DESCRIPTION_COLUMN)
+    @Length(max = GenericConstants.DESCRIPTION_1000, message = ValidationMessages.DESCRIPTION_LENGTH_MESSAGE)
+    public String getDescription()
     {
-        return name;
+        return description;
     }
 
-    public void setName(String name)
+    public void setDescription(final String description)
     {
-        this.name = name;
+        this.description = description;
     }
 
     @Column(name = ColumnNames.EXPRESSION_COLUMN)
@@ -119,18 +110,6 @@ public class FilterPE extends HibernateAbstractRegistrationHolder implements IId
         this.modificationDate = versionDate;
     }
 
-    @Column(name = ColumnNames.DESCRIPTION_COLUMN)
-    @Length(max = GenericConstants.DESCRIPTION_1000, message = ValidationMessages.DESCRIPTION_LENGTH_MESSAGE)
-    public String getDescription()
-    {
-        return description;
-    }
-
-    public void setDescription(final String description)
-    {
-        this.description = description;
-    }
-
     @ManyToOne(fetch = FetchType.EAGER)
     @NotNull(message = ValidationMessages.DATABASE_INSTANCE_NOT_NULL_MESSAGE)
     @JoinColumn(name = ColumnNames.DATABASE_INSTANCE_COLUMN, updatable = false)
@@ -169,60 +148,4 @@ public class FilterPE extends HibernateAbstractRegistrationHolder implements IId
     {
         this.gridId = gridId;
     }
-
-    @Override
-    public final boolean equals(final Object obj)
-    {
-        if (obj == this)
-        {
-            return true;
-        }
-        if (obj instanceof FilterPE == false)
-        {
-            return false;
-        }
-        final FilterPE that = (FilterPE) obj;
-        final EqualsBuilder builder = new EqualsBuilder();
-        builder.append(getName(), that.getName());
-        builder.append(getGridId(), that.getGridId());
-        builder.append(getDatabaseInstance(), that.getDatabaseInstance());
-        return builder.isEquals();
-    }
-
-    @Override
-    public final int hashCode()
-    {
-        final HashCodeBuilder builder = new HashCodeBuilder();
-        builder.append(getName());
-        builder.append(getGridId());
-        builder.append(getDatabaseInstance());
-        return builder.toHashCode();
-    }
-
-    @Override
-    public final String toString()
-    {
-        final ToStringBuilder builder =
-                new ToStringBuilder(this,
-                        ModifiedShortPrefixToStringStyle.MODIFIED_SHORT_PREFIX_STYLE);
-        builder.append("name", getName());
-        builder.append("grid", getGridId());
-        builder.append("database", getDatabaseInstance());
-        return builder.toString();
-    }
-
-    public int compareTo(FilterPE that)
-    {
-        final String thatName = that.getName();
-        final String thisName = getName();
-        if (thisName == null)
-        {
-            return thatName == null ? 0 : -1;
-        }
-        if (thatName == null)
-        {
-            return 1;
-        }
-        return thisName.compareTo(thatName);
-    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomColumnPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomColumnPE.java
new file mode 100644
index 00000000000..e2a41a94390
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomColumnPE.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.hibernate.validator.Length;
+import org.hibernate.validator.NotNull;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
+
+/**
+ * Persistence Entity describing the grid custom column.
+ * 
+ * @author Tomasz Pylak
+ */
+@Entity
+@Table(name = TableNames.GRID_CUSTOM_COLUMNS_TABLE)
+public class GridCustomColumnPE extends AbstractGridExpressionPE<GridCustomColumnPE>
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private String code;
+
+    private String label;
+
+    @Column(name = ColumnNames.CODE_COLUMN)
+    @NotNull(message = ValidationMessages.CODE_NOT_NULL_MESSAGE)
+    @Length(min = 1, max = 200, message = ValidationMessages.CODE_LENGTH_MESSAGE)
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    @Column(name = ColumnNames.LABEL_COLUMN)
+    @Length(max = GenericConstants.COLUMN_LABEL, message = ValidationMessages.LABEL_LENGTH_MESSAGE)
+    public String getLabel()
+    {
+        return label;
+    }
+
+    public void setLabel(final String label)
+    {
+        this.label = label;
+    }
+
+    @Override
+    public final boolean equals(final Object obj)
+    {
+        if (obj == this)
+        {
+            return true;
+        }
+        if (obj instanceof GridCustomColumnPE == false)
+        {
+            return false;
+        }
+        final GridCustomColumnPE that = (GridCustomColumnPE) obj;
+        final EqualsBuilder builder = new EqualsBuilder();
+        builder.append(getCode(), that.getCode());
+        builder.append(getGridId(), that.getGridId());
+        builder.append(getDatabaseInstance(), that.getDatabaseInstance());
+        return builder.isEquals();
+    }
+
+    @Override
+    public final int hashCode()
+    {
+        final HashCodeBuilder builder = new HashCodeBuilder();
+        builder.append(getCode());
+        builder.append(getGridId());
+        builder.append(getDatabaseInstance());
+        return builder.toHashCode();
+    }
+
+    @Override
+    public final String toString()
+    {
+        return getLabel();
+    }
+
+    public int compareTo(GridCustomColumnPE that)
+    {
+        return getCode().compareTo(that.getCode());
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomFilterPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomFilterPE.java
new file mode 100644
index 00000000000..ecd315b20f9
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/GridCustomFilterPE.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.hibernate.validator.Length;
+import org.hibernate.validator.NotNull;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
+
+/**
+ * Persistence Entity describing the grid custom filter.
+ * 
+ * @author Izabela Adamczyk
+ */
+@Entity
+@Table(name = TableNames.FILTERS_TABLE)
+public class GridCustomFilterPE extends AbstractGridExpressionPE<GridCustomFilterPE>
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private String name;
+
+    @Column(name = ColumnNames.NAME_COLUMN)
+    @NotNull(message = ValidationMessages.NAME_NOT_NULL_MESSAGE)
+    @Length(min = 1, max = 200, message = ValidationMessages.NAME_LENGTH_MESSAGE)
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    @Override
+    public final boolean equals(final Object obj)
+    {
+        if (obj == this)
+        {
+            return true;
+        }
+        if (obj instanceof GridCustomFilterPE == false)
+        {
+            return false;
+        }
+        final GridCustomFilterPE that = (GridCustomFilterPE) obj;
+        final EqualsBuilder builder = new EqualsBuilder();
+        builder.append(getName(), that.getName());
+        builder.append(getGridId(), that.getGridId());
+        builder.append(getDatabaseInstance(), that.getDatabaseInstance());
+        return builder.isEquals();
+    }
+
+    @Override
+    public final int hashCode()
+    {
+        final HashCodeBuilder builder = new HashCodeBuilder();
+        builder.append(getName());
+        builder.append(getGridId());
+        builder.append(getDatabaseInstance());
+        return builder.toHashCode();
+    }
+
+    @Override
+    public final String toString()
+    {
+        return getName();
+    }
+
+    public int compareTo(GridCustomFilterPE that)
+    {
+        final String thatName = that.getName();
+        final String thisName = getName();
+        if (thisName == null)
+        {
+            return thatName == null ? 0 : -1;
+        }
+        if (thatName == null)
+        {
+            return 1;
+        }
+        return thisName.compareTo(thatName);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/TableNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/TableNames.java
index d54fd572ee4..dc496d40c0a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/TableNames.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/TableNames.java
@@ -53,6 +53,8 @@ public final class TableNames
 
     public static final String FILTERS_TABLE = "filters";
 
+    public static final String GRID_CUSTOM_COLUMNS_TABLE = "grid_custom_columns";
+
     public static final String ATTACHMENT_CONTENT_TABLE = "attachment_contents";
 
     public static final String ATTACHMENTS_TABLE = "attachments";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslator.java
deleted file mode 100644
index 0b2d30c1152..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslator.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2008 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.generic.shared.translator;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.commons.lang.StringEscapeUtils;
-
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
-import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
-
-/**
- * A {@link Filter} &lt;---&gt; {@link FilterPE} translator.
- * 
- * @author Izabela Adamczyk
- */
-public final class FilterTranslator
-{
-    private static final String PARAMETER_PATTERN = "\\$\\{.*?\\}";
-
-    private FilterTranslator()
-    {
-        // Can not be instantiated.
-    }
-
-    public final static List<Filter> translate(final List<FilterPE> filters)
-    {
-        final List<Filter> result = new ArrayList<Filter>();
-        for (final FilterPE filter : filters)
-        {
-            result.add(FilterTranslator.translate(filter));
-        }
-        return result;
-    }
-
-    public final static Filter translate(final FilterPE filter)
-    {
-        if (filter == null)
-        {
-            return null;
-        }
-        final Filter result = new Filter();
-        result.setId(HibernateUtils.getId(filter));
-        result.setModificationDate(filter.getModificationDate());
-        result.setExpression(StringEscapeUtils.escapeHtml(filter.getExpression()));
-        result.setName(StringEscapeUtils.escapeHtml(filter.getName()));
-        result.setDescription(StringEscapeUtils.escapeHtml(filter.getDescription()));
-        result.setRegistrator(PersonTranslator.translate(filter.getRegistrator()));
-        result.setRegistrationDate(filter.getRegistrationDate());
-        result.setDatabaseInstance(DatabaseInstanceTranslator.translate(filter
-                .getDatabaseInstance()));
-        result.setPublic(filter.isPublic());
-        result.setParameters(extractParameters(filter.getExpression()));
-        return result;
-    }
-
-    static Set<String> extractParameters(String expression)
-    {
-        Pattern parameterPattern = Pattern.compile(PARAMETER_PATTERN);
-        Set<String> list = new HashSet<String>();
-        Matcher matcher = parameterPattern.matcher(expression);
-        while (matcher.find())
-        {
-            String group = matcher.group();
-            list.add(group.substring(2, group.length() - 1));
-        }
-        return list;
-    }
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomExpressionTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomExpressionTranslator.java
new file mode 100644
index 00000000000..004e0080748
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomExpressionTranslator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.translator;
+
+import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractGridExpression;
+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.dto.AbstractGridExpressionPE;
+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.util.HibernateUtils;
+
+/**
+ * Grid custom filter or column translator.
+ * 
+ * @author Tomasz Pylak
+ */
+public final class GridCustomExpressionTranslator
+{
+    private GridCustomExpressionTranslator()
+    {
+        // Can not be instantiated.
+    }
+
+    /** A {@link GridCustomColumn} &lt;---&gt; {@link GridCustomColumnPE} translator. */
+    public static class GridCustomColumnTranslator
+    {
+        public final static List<GridCustomColumn> translate(final List<GridCustomColumnPE> columns)
+        {
+            final List<GridCustomColumn> result = new ArrayList<GridCustomColumn>();
+            for (final GridCustomColumnPE column : columns)
+            {
+                result.add(translate(column));
+            }
+            return result;
+        }
+
+        private final static GridCustomColumn translate(final GridCustomColumnPE original)
+        {
+            if (original == null)
+            {
+                return null;
+            }
+            final GridCustomColumn result = new GridCustomColumn();
+            result.setCode(escapeHtml(original.getCode()));
+            result.setLabel(escapeHtml(original.getLabel()));
+
+            translateGridExpression(original, result);
+            return result;
+        }
+    }
+
+    /**
+     * A {@link GridCustomFilter} &lt;---&gt; {@link GridCustomFilterPE} translator.
+     * 
+     * @author Izabela Adamczyk
+     */
+    public static final class GridCustomFilterTranslator
+    {
+        private static final String PARAMETER_PATTERN = "\\$\\{.*?\\}";
+
+        public final static List<GridCustomFilter> translate(final List<GridCustomFilterPE> filters)
+        {
+            final List<GridCustomFilter> result = new ArrayList<GridCustomFilter>();
+            for (final GridCustomFilterPE filter : filters)
+            {
+                result.add(GridCustomFilterTranslator.translate(filter));
+            }
+            return result;
+        }
+
+        public final static GridCustomFilter translate(final GridCustomFilterPE original)
+        {
+            if (original == null)
+            {
+                return null;
+            }
+            final GridCustomFilter result = new GridCustomFilter();
+            result.setName(escapeHtml(original.getName()));
+            result.setParameters(extractParameters(original.getExpression()));
+
+            translateGridExpression(original, result);
+            return result;
+        }
+
+        static Set<String> extractParameters(String expression)
+        {
+            Pattern parameterPattern = Pattern.compile(PARAMETER_PATTERN);
+            Set<String> list = new HashSet<String>();
+            Matcher matcher = parameterPattern.matcher(expression);
+            while (matcher.find())
+            {
+                String group = matcher.group();
+                list.add(group.substring(2, group.length() - 1));
+            }
+            return list;
+        }
+
+    }
+
+    private static void translateGridExpression(final AbstractGridExpressionPE<?> gridExpression,
+            final AbstractGridExpression result)
+    {
+        result.setId(HibernateUtils.getId(gridExpression));
+        result.setModificationDate(gridExpression.getModificationDate());
+        result.setExpression(escapeHtml(gridExpression.getExpression()));
+        result.setDescription(StringEscapeUtils.escapeHtml(gridExpression.getDescription()));
+        result.setRegistrator(PersonTranslator.translate(gridExpression.getRegistrator()));
+        result.setRegistrationDate(gridExpression.getRegistrationDate());
+        result.setDatabaseInstance(DatabaseInstanceTranslator.translate(gridExpression
+                .getDatabaseInstance()));
+        result.setPublic(gridExpression.isPublic());
+    }
+
+}
diff --git a/openbis/source/java/hibernateContext.xml b/openbis/source/java/hibernateContext.xml
index 72e74f66e42..8b5cfb2e572 100644
--- a/openbis/source/java/hibernateContext.xml
+++ b/openbis/source/java/hibernateContext.xml
@@ -74,7 +74,8 @@
                 
                 <value>ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentHolderPE</value>
                 <value>ch.systemsx.cisd.openbis.generic.shared.dto.AuthorizationGroupPE</value>
-                <value>ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE</value>
+                <value>ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE</value>
+                <value>ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE</value>
             </list>
         </property>
         <!-- 
diff --git a/openbis/source/sql/postgresql/migration/migration-042-043.sql b/openbis/source/sql/postgresql/migration/migration-042-043.sql
new file mode 100644
index 00000000000..227f22eafb0
--- /dev/null
+++ b/openbis/source/sql/postgresql/migration/migration-042-043.sql
@@ -0,0 +1,14 @@
+-- Migration from 042 to 043
+CREATE DOMAIN GRID_EXPRESSION AS VARCHAR(2000);
+CREATE DOMAIN GRID_ID AS VARCHAR(200);
+
+CREATE TABLE GRID_CUSTOM_COLUMNS (ID TECH_ID NOT NULL, DBIN_ID TECH_ID NOT NULL, CODE VARCHAR(200) NOT NULL, LABEL column_label NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_REGISTERER TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, EXPRESSION GRID_EXPRESSION NOT NULL, IS_PUBLIC BOOLEAN NOT NULL, GRID_ID GRID_ID NOT NULL);
+CREATE SEQUENCE GRID_CUSTOM_COLUMNS_ID_SEQ;
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_PK PRIMARY KEY(ID);
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_BK_UK UNIQUE(CODE, DBIN_ID, GRID_ID);
+
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID);
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_DBIN_FK FOREIGN KEY (DBIN_ID) REFERENCES DATABASE_INSTANCES(ID);
+
+CREATE INDEX GRID_CUSTOM_COLUMNS_PERS_FK_I ON FILTERS (PERS_ID_REGISTERER);
+CREATE INDEX GRID_CUSTOM_COLUMNS_DBIN_FK_I ON FILTERS (DBIN_ID);
\ No newline at end of file
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java
index 0de3f4cec19..0d5cf3a9685 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java
@@ -33,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEventDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFileFormatTypeDAO;
-import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFilterDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomFilterDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGroupDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ILocatorTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IMaterialDAO;
@@ -101,7 +101,7 @@ public abstract class AbstractBOTest extends AssertJUnit
 
     IAuthorizationGroupDAO authorizationGroupDAO;
 
-    IFilterDAO filterDAO;
+    IGridCustomFilterDAO filterDAO;
 
     @BeforeMethod
     public void beforeMethod()
@@ -130,7 +130,7 @@ public abstract class AbstractBOTest extends AssertJUnit
         permIdDAO = context.mock(IPermIdDAO.class);
         eventDAO = context.mock(IEventDAO.class);
         authorizationGroupDAO = context.mock(IAuthorizationGroupDAO.class);
-        filterDAO = context.mock(IFilterDAO.class);
+        filterDAO = context.mock(IGridCustomFilterDAO.class);
         context.checking(new Expectations()
             {
                 {
@@ -162,7 +162,7 @@ public abstract class AbstractBOTest extends AssertJUnit
                     will(returnValue(eventDAO));
                     allowing(daoFactory).getAuthorizationGroupDAO();
                     will(returnValue(authorizationGroupDAO));
-                    allowing(daoFactory).getFilterDAO();
+                    allowing(daoFactory).getGridCustomFilterDAO();
                     will(returnValue(filterDAO));
                 }
             });
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/FilterBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomFilterBOTest.java
similarity index 76%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/FilterBOTest.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomFilterBOTest.java
index 41b23eb3cb4..6c1386ac760 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/FilterBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/GridCustomFilterBOTest.java
@@ -22,14 +22,14 @@ import org.jmock.Expectations;
 import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Filter;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 
 /**
  * @author Piotr Buczek
  */
-public class FilterBOTest extends AbstractBOTest
+public class GridCustomFilterBOTest extends AbstractBOTest
 {
 
     private static final String NAME = "name";
@@ -47,8 +47,8 @@ public class FilterBOTest extends AbstractBOTest
     @Test
     public void testUpdate()
     {
-        final FilterPE filter = createFilter();
-        final IFilterUpdates updates = createFilterUpdates(filter);
+        final GridCustomFilterPE filter = createFilter();
+        final IFilterOrColumnUpdates updates = createFilterUpdates(filter);
         context.checking(new Expectations()
             {
                 {
@@ -64,15 +64,15 @@ public class FilterBOTest extends AbstractBOTest
                 }
             });
 
-        IFilterBO filterBO = createFilterBO();
+        IGridCustomFilterOrColumnBO filterBO = createFilterBO();
         filterBO.update(updates);
 
         context.assertIsSatisfied();
     }
 
-    private FilterPE createFilter()
+    private GridCustomFilterPE createFilter()
     {
-        final FilterPE filter = new FilterPE();
+        final GridCustomFilterPE filter = new GridCustomFilterPE();
         filter.setId(TECH_ID.getId());
         filter.setGridId(GRID_ID);
         filter.setName(NAME);
@@ -82,9 +82,9 @@ public class FilterBOTest extends AbstractBOTest
         return filter;
     }
 
-    private IFilterUpdates createFilterUpdates(final FilterPE filter)
+    private IFilterOrColumnUpdates createFilterUpdates(final GridCustomFilterPE filter)
     {
-        final Filter updates = new Filter();
+        final GridCustomFilter updates = new GridCustomFilter();
         updates.setId(filter.getId());
         updates.setName(filter.getName() + " modified");
         updates.setDescription(filter.getDescription() + " modified");
@@ -93,9 +93,9 @@ public class FilterBOTest extends AbstractBOTest
         return updates;
     }
 
-    private final IFilterBO createFilterBO()
+    private final IGridCustomFilterOrColumnBO createFilterBO()
     {
-        return new FilterBO(daoFactory, EXAMPLE_SESSION);
+        return new GridCustomFilterBO(daoFactory, EXAMPLE_SESSION);
     }
 
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAOTest.java
new file mode 100644
index 00000000000..3054b3ae0f6
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomColumnDAOTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
+
+import java.util.List;
+
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IGridCustomColumnDAO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+
+/**
+ * Test cases for corresponding {@link GridCustomColumnDAO} class.
+ * 
+ * @author Tomasz Pylak
+ */
+@Test(groups =
+    { "db", "column" })
+public final class GridCustomColumnDAOTest extends AbstractDAOTest
+{
+    public void testCreateAndListColumn() throws Exception
+    {
+        IGridCustomColumnDAO dao = daoFactory.getGridCustomColumnDAO();
+        AssertJUnit.assertEquals(0, dao.listAllEntities().size());
+        GridCustomColumnPE column =
+                create("NAME", "GRID", "DESCRIPTION", "EXPRESSION", true, getSystemPerson());
+        dao.createColumn(column);
+        List<GridCustomColumnPE> columns = dao.listAllEntities();
+        AssertJUnit.assertEquals(1, columns.size());
+        AssertJUnit.assertEquals(column, columns.get(0));
+    }
+
+    private static final GridCustomColumnPE create(String name, String grid, String desc,
+            String expr, boolean isPublic, PersonPE registrator)
+    {
+        GridCustomColumnPE record = new GridCustomColumnPE();
+        record.setCode(name + "_xxx");
+        record.setLabel(name);
+        record.setDescription(desc);
+        record.setExpression(expr);
+        record.setGridId(grid);
+        record.setPublic(isPublic);
+        record.setRegistrator(registrator);
+        return record;
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/FilterDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomFilterDAOTest.java
similarity index 54%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/FilterDAOTest.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomFilterDAOTest.java
index 72caf292307..6ec4cf8ccea 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/FilterDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/GridCustomFilterDAOTest.java
@@ -21,17 +21,17 @@ import java.util.List;
 import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
 
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 
 /**
- * Test cases for corresponding {@link FilterDAO} class.
+ * Test cases for corresponding {@link GridCustomFilterDAO} class.
  * 
  * @author Izabela Adamczyk
  */
 @Test(groups =
     { "db", "filter" })
-public final class FilterDAOTest extends AbstractDAOTest
+public final class GridCustomFilterDAOTest extends AbstractDAOTest
 {
     private static final boolean PUBLIC = true;
 
@@ -48,11 +48,11 @@ public final class FilterDAOTest extends AbstractDAOTest
     @Test
     public void testCreateFilter() throws Exception
     {
-        AssertJUnit.assertEquals(0, daoFactory.getFilterDAO().listAllEntities().size());
-        FilterPE filter =
+        AssertJUnit.assertEquals(0, daoFactory.getGridCustomFilterDAO().listAllEntities().size());
+        GridCustomFilterPE filter =
                 createFilter(NAME, GRID, DESCRIPTION, EXPRESSION, PUBLIC, getSystemPerson());
-        daoFactory.getFilterDAO().createFilter(filter);
-        List<FilterPE> filters = daoFactory.getFilterDAO().listAllEntities();
+        daoFactory.getGridCustomFilterDAO().createFilter(filter);
+        List<GridCustomFilterPE> filters = daoFactory.getGridCustomFilterDAO().listAllEntities();
         AssertJUnit.assertEquals(1, filters.size());
         AssertJUnit.assertEquals(filter, filters.get(0));
     }
@@ -60,44 +60,44 @@ public final class FilterDAOTest extends AbstractDAOTest
     @Test
     public void testListFilters() throws Exception
     {
-        AssertJUnit.assertEquals(0, daoFactory.getFilterDAO().listFilters(GRID2).size());
-        AssertJUnit.assertEquals(0, daoFactory.getFilterDAO().listFilters(GRID).size());
-        FilterPE filter =
+        AssertJUnit.assertEquals(0, daoFactory.getGridCustomFilterDAO().listFilters(GRID2).size());
+        AssertJUnit.assertEquals(0, daoFactory.getGridCustomFilterDAO().listFilters(GRID).size());
+        GridCustomFilterPE filter =
                 createFilter(NAME, GRID, DESCRIPTION, EXPRESSION, PUBLIC, getSystemPerson());
-        daoFactory.getFilterDAO().createFilter(filter);
-        List<FilterPE> filters = daoFactory.getFilterDAO().listFilters(GRID);
+        daoFactory.getGridCustomFilterDAO().createFilter(filter);
+        List<GridCustomFilterPE> filters = daoFactory.getGridCustomFilterDAO().listFilters(GRID);
         AssertJUnit.assertEquals(1, filters.size());
         AssertJUnit.assertEquals(filter, filters.get(0));
-        AssertJUnit.assertEquals(0, daoFactory.getFilterDAO().listFilters(GRID2).size());
+        AssertJUnit.assertEquals(0, daoFactory.getGridCustomFilterDAO().listFilters(GRID2).size());
     }
 
     @Test
     public final void testDeleteFilters()
     {
-        AssertJUnit.assertEquals(0, daoFactory.getFilterDAO().listFilters(GRID2).size());
-        AssertJUnit.assertEquals(0, daoFactory.getFilterDAO().listFilters(GRID).size());
-        FilterPE filter1 =
+        AssertJUnit.assertEquals(0, daoFactory.getGridCustomFilterDAO().listFilters(GRID2).size());
+        AssertJUnit.assertEquals(0, daoFactory.getGridCustomFilterDAO().listFilters(GRID).size());
+        GridCustomFilterPE filter1 =
                 createFilter(NAME + "1", GRID, DESCRIPTION, EXPRESSION, PUBLIC, getSystemPerson());
-        FilterPE filter2 =
+        GridCustomFilterPE filter2 =
                 createFilter(NAME + "2", GRID, DESCRIPTION, EXPRESSION, PUBLIC, getSystemPerson());
-        FilterPE filter3 =
+        GridCustomFilterPE filter3 =
                 createFilter(NAME + "3", GRID2, DESCRIPTION, EXPRESSION, PUBLIC, getSystemPerson());
-        daoFactory.getFilterDAO().createFilter(filter1);
-        daoFactory.getFilterDAO().createFilter(filter2);
-        daoFactory.getFilterDAO().createFilter(filter3);
-        AssertJUnit.assertEquals(2, daoFactory.getFilterDAO().listFilters(GRID).size());
-        AssertJUnit.assertEquals(1, daoFactory.getFilterDAO().listFilters(GRID2).size());
-        daoFactory.getFilterDAO().delete(filter1);
-        List<FilterPE> remainingFilters = daoFactory.getFilterDAO().listFilters(GRID);
+        daoFactory.getGridCustomFilterDAO().createFilter(filter1);
+        daoFactory.getGridCustomFilterDAO().createFilter(filter2);
+        daoFactory.getGridCustomFilterDAO().createFilter(filter3);
+        AssertJUnit.assertEquals(2, daoFactory.getGridCustomFilterDAO().listFilters(GRID).size());
+        AssertJUnit.assertEquals(1, daoFactory.getGridCustomFilterDAO().listFilters(GRID2).size());
+        daoFactory.getGridCustomFilterDAO().delete(filter1);
+        List<GridCustomFilterPE> remainingFilters = daoFactory.getGridCustomFilterDAO().listFilters(GRID);
         AssertJUnit.assertEquals(1, remainingFilters.size());
         AssertJUnit.assertEquals(filter2, remainingFilters.get(0));
-        AssertJUnit.assertEquals(1, daoFactory.getFilterDAO().listFilters(GRID2).size());
+        AssertJUnit.assertEquals(1, daoFactory.getGridCustomFilterDAO().listFilters(GRID2).size());
     }
 
-    private static final FilterPE createFilter(String name, String grid, String desc, String expr,
+    private static final GridCustomFilterPE createFilter(String name, String grid, String desc, String expr,
             boolean isPublic, PersonPE registrator)
     {
-        FilterPE filter = new FilterPE();
+        GridCustomFilterPE filter = new GridCustomFilterPE();
         filter.setDescription(desc);
         filter.setExpression(expr);
         filter.setGridId(grid);
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
index dd04ea1d6fb..55bb2ec537d 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
@@ -28,18 +28,20 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ReturnVa
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.DataSetCodePredicate;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.FilterUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.GroupIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSampleCriteriaPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ProjectUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleTechIdPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.DeleteGridCustomColumnPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.DeleteGridCustomFilterPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.UpdateGridCustomColumnPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractGridExpressionPredicate.UpdateGridCustomFilterPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.DataSetTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.ExperimentTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.GroupTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.ProjectTechIdPredicate;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.FilterTechIdPredicate.DeleteFilterTechIdPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.CustomGridExpressionValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.ExternalDataValidator;
-import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.FilterValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.GroupValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.MatchingEntityValidator;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.ProjectValidator;
@@ -63,10 +65,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.Filter;
 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.IFilterUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IFilterOrColumnUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IGroupUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
@@ -78,7 +81,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -913,34 +916,72 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleSet.OBSERVER)
-    @ReturnValueFilter(validatorClass = FilterValidator.class)
-    public List<Filter> listFilters(String sessionToken, String gridId);
+    @ReturnValueFilter(validatorClass = CustomGridExpressionValidator.class)
+    public List<GridCustomFilter> listFilters(String sessionToken, String gridId);
 
     /**
      * Creates a new filter.
      */
     @Transactional
     @RolesAllowed(RoleSet.POWER_USER)
-    @DatabaseCreateOrDeleteModification(value = ObjectKind.FILTER)
-    public void registerFilter(String sessionToken, NewFilter filter);
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_FILTER)
+    public void registerFilter(String sessionToken, NewColumnOrFilter filter);
 
     /**
      * Deletes specified filters.
      */
     @Transactional
     @RolesAllowed(RoleSet.POWER_USER)
-    @DatabaseCreateOrDeleteModification(value = ObjectKind.FILTER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_FILTER)
     public void deleteFilters(
             String sessionToken,
-            @AuthorizationGuard(guardClass = DeleteFilterTechIdPredicate.class) List<TechId> filterIds);
+            @AuthorizationGuard(guardClass = DeleteGridCustomFilterPredicate.class) List<TechId> filterIds);
 
     /**
      * Updates a filter.
      */
     @Transactional
     @RolesAllowed(RoleSet.POWER_USER)
-    @DatabaseUpdateModification(value = ObjectKind.FILTER)
-    public void updateFilter(String sessionToken,
-            @AuthorizationGuard(guardClass = FilterUpdatesPredicate.class) IFilterUpdates updates);
+    @DatabaseUpdateModification(value = ObjectKind.GRID_CUSTOM_FILTER)
+    public void updateFilter(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = UpdateGridCustomFilterPredicate.class) IFilterOrColumnUpdates updates);
+
+    // columns
+
+    /**
+     * Lists columns available for selected grid.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.OBSERVER)
+    @ReturnValueFilter(validatorClass = CustomGridExpressionValidator.class)
+    public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId);
+
+    /**
+     * Creates a new column.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_COLUMN)
+    public void registerGridCustomColumn(String sessionToken, NewColumnOrFilter column);
 
+    /**
+     * Deletes specified columns.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.GRID_CUSTOM_COLUMN)
+    public void deleteGridCustomColumns(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = DeleteGridCustomColumnPredicate.class) List<TechId> columnIds);
+
+    /**
+     * Updates a column.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.POWER_USER)
+    @DatabaseUpdateModification(value = ObjectKind.GRID_CUSTOM_COLUMN)
+    public void updateGridCustomColumn(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = UpdateGridCustomColumnPredicate.class) IFilterOrColumnUpdates updates);
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationTestCase.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationTestCase.java
index d275c5ec6bb..994e102fe62 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationTestCase.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationTestCase.java
@@ -33,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+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.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
@@ -298,10 +298,10 @@ public class AuthorizationTestCase extends AssertJUnit
     /**
      * Creates a filter in the specified database instance and registrator and ownership flag.
      */
-    protected FilterPE createFilter(DatabaseInstancePE databaseInstance, PersonPE registrator,
+    protected GridCustomFilterPE createFilter(DatabaseInstancePE databaseInstance, PersonPE registrator,
             boolean isPublic)
     {
-        final FilterPE filter = new FilterPE();
+        final GridCustomFilterPE filter = new GridCustomFilterPE();
         filter.setDatabaseInstance(databaseInstance);
         filter.setRegistrator(registrator);
         filter.setPublic(isPublic);
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/FilterValidatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/CustomGridExpressionValidatorTest.java
similarity index 61%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/FilterValidatorTest.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/CustomGridExpressionValidatorTest.java
index 341f60674ff..f25f7bcd3bc 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/FilterValidatorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/authorization/validator/CustomGridExpressionValidatorTest.java
@@ -21,17 +21,17 @@ import org.testng.annotations.Test;
 import ch.rinn.restrictions.Friend;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.AuthorizationTestCase;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.FilterPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
-import ch.systemsx.cisd.openbis.generic.shared.translator.FilterTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomFilterTranslator;
 
 /**
- * Test cases for corresponding {@link FilterValidator} class.
+ * Test cases for corresponding {@link CustomGridExpressionValidator} class.
  * 
  * @author Piotr Buczek
  */
-@Friend(toClasses = FilterValidator.class)
-public final class FilterValidatorTest extends AuthorizationTestCase
+@Friend(toClasses = CustomGridExpressionValidator.class)
+public final class CustomGridExpressionValidatorTest extends AuthorizationTestCase
 {
     @Test
     public final void testWithPublicFilter()
@@ -40,9 +40,9 @@ public final class FilterValidatorTest extends AuthorizationTestCase
         final PersonPE person = createPerson("A", instance);
         final PersonPE registrator = createPerson("B", instance);
         final boolean isPublic = true;
-        final FilterPE filter = createFilter(instance, registrator, isPublic);
-        final FilterValidator validator = new FilterValidator();
-        assertEquals(true, validator.isValid(person, FilterTranslator.translate(filter)));
+        final GridCustomFilterPE filter = createFilter(instance, registrator, isPublic);
+        final CustomGridExpressionValidator validator = new CustomGridExpressionValidator();
+        assertEquals(true, validator.isValid(person, GridCustomFilterTranslator.translate(filter)));
     }
 
     @Test
@@ -53,9 +53,9 @@ public final class FilterValidatorTest extends AuthorizationTestCase
         final PersonPE person = createPerson("A", instance);
         final PersonPE registrator = person;
         final boolean isPublic = false;
-        final FilterPE filter = createFilter(instance, registrator, isPublic);
-        final FilterValidator validator = new FilterValidator();
-        assertEquals(true, validator.isValid(person, FilterTranslator.translate(filter)));
+        final GridCustomFilterPE filter = createFilter(instance, registrator, isPublic);
+        final CustomGridExpressionValidator validator = new CustomGridExpressionValidator();
+        assertEquals(true, validator.isValid(person, GridCustomFilterTranslator.translate(filter)));
     }
 
     @Test
@@ -67,9 +67,9 @@ public final class FilterValidatorTest extends AuthorizationTestCase
         final PersonPE person = createPerson("A", anotherInstance);
         final PersonPE registrator = createPerson("A", instance);
         final boolean isPublic = false;
-        final FilterPE filter = createFilter(instance, registrator, isPublic);
-        final FilterValidator validator = new FilterValidator();
-        assertEquals(false, validator.isValid(person, FilterTranslator.translate(filter)));
+        final GridCustomFilterPE filter = createFilter(instance, registrator, isPublic);
+        final CustomGridExpressionValidator validator = new CustomGridExpressionValidator();
+        assertEquals(false, validator.isValid(person, GridCustomFilterTranslator.translate(filter)));
     }
 
     @Test
@@ -80,9 +80,9 @@ public final class FilterValidatorTest extends AuthorizationTestCase
         assignRoles(person);
         final PersonPE registrator = createPerson("B", instance);
         final boolean isPublic = false;
-        final FilterPE filter = createFilter(instance, registrator, isPublic);
-        final FilterValidator validator = new FilterValidator();
-        assertEquals(true, validator.isValid(person, FilterTranslator.translate(filter)));
+        final GridCustomFilterPE filter = createFilter(instance, registrator, isPublic);
+        final CustomGridExpressionValidator validator = new CustomGridExpressionValidator();
+        assertEquals(true, validator.isValid(person, GridCustomFilterTranslator.translate(filter)));
     }
 
     @Test
@@ -94,9 +94,9 @@ public final class FilterValidatorTest extends AuthorizationTestCase
         assignRoles(person);
         final PersonPE registrator = createPerson("B", anotherInstance);
         final boolean isPublic = false;
-        final FilterPE filter = createFilter(anotherInstance, registrator, isPublic);
-        final FilterValidator validator = new FilterValidator();
-        assertEquals(false, validator.isValid(person, FilterTranslator.translate(filter)));
+        final GridCustomFilterPE filter = createFilter(anotherInstance, registrator, isPublic);
+        final CustomGridExpressionValidator validator = new CustomGridExpressionValidator();
+        assertEquals(false, validator.isValid(person, GridCustomFilterTranslator.translate(filter)));
     }
 
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomFilterTranslatorTest.java
similarity index 68%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslatorTest.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomFilterTranslatorTest.java
index 7203bb7df29..fd2af6e8605 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/FilterTranslatorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/GridCustomFilterTranslatorTest.java
@@ -19,39 +19,41 @@ package ch.systemsx.cisd.openbis.generic.shared.translator;
 import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomFilterTranslator;
+
 /**
- * Test cases for {@link FilterTranslator}.
+ * Test cases for {@link GridCustomFilterTranslator}.
  * 
  * @author Izabela Adamczyk
  */
-public class FilterTranslatorTest extends AssertJUnit
+public class GridCustomFilterTranslatorTest extends AssertJUnit
 {
     @Test
     public void testExtractNoParameters() throws Exception
     {
         String expression = "";
-        assertEquals(0, FilterTranslator.extractParameters(expression).size());
+        assertEquals(0, GridCustomFilterTranslator.extractParameters(expression).size());
     }
 
     @Test
     public void testExtractOneParameter() throws Exception
     {
         String expression = "${abc}";
-        assertEquals(1, FilterTranslator.extractParameters(expression).size());
+        assertEquals(1, GridCustomFilterTranslator.extractParameters(expression).size());
     }
 
     @Test
     public void testExtractOneDuplicatedParameter() throws Exception
     {
         String expression = "${abc} ${abc}";
-        assertEquals(1, FilterTranslator.extractParameters(expression).size());
+        assertEquals(1, GridCustomFilterTranslator.extractParameters(expression).size());
     }
 
     @Test
     public void testExtractManyParameters() throws Exception
     {
         String expression = "${abc} ${abc} ${def} ${ghi}";
-        assertEquals(3, FilterTranslator.extractParameters(expression).size());
+        assertEquals(3, GridCustomFilterTranslator.extractParameters(expression).size());
     }
 
 }
-- 
GitLab