From e57f7f76e2febf756471bf4c5e9855e87c2c6b4f Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Thu, 17 Mar 2011 07:15:08 +0000
Subject: [PATCH] TypedTableGrid refactoring: PersonGrid

SVN: 20384
---
 .../web/client/ICommonClientService.java      |   4 +-
 .../web/client/ICommonClientServiceAsync.java |   5 +-
 .../web/client/application/ui/PersonGrid.java |  68 +++++++-----
 .../ui/columns/specific/PersonColDefKind.java | 100 ------------------
 .../web/client/dto/ListPersonsCriteria.java   |   3 +-
 .../web/client/dto/PersonGridColumnIDs.java   |  34 ++++++
 .../web/server/CommonClientService.java       |  20 ++--
 .../web/server/resultset/PersonsProvider.java |  82 ++++++++++++++
 .../application/AuthorizationGroupsTest.java  |   6 +-
 .../AuthorizationManagementConsolTest.java    |   4 +-
 .../application/ui/amc/RemovePerson.java      |   4 +-
 .../server/resultset/PersonsProviderTest.java | 100 ++++++++++++++++++
 .../basic/dto/builders/PersonBuilder.java     |  20 ++++
 13 files changed, 301 insertions(+), 149 deletions(-)
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/PersonColDefKind.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/PersonGridColumnIDs.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProvider.java
 create mode 100644 openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProviderTest.java

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 ea0a4d68d30..d41d546fb64 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
@@ -171,7 +171,7 @@ public interface ICommonClientService extends IClientService
     /**
      * Returns a list of all persons which belong to the current database instance.
      */
-    public ResultSet<Person> listPersons(ListPersonsCriteria criteria) throws UserFailureException;
+    public TypedTableResultSet<Person> listPersons(ListPersonsCriteria criteria) throws UserFailureException;
 
     /**
      * Returns a list of persons registered in given database instance.
@@ -181,7 +181,7 @@ public interface ICommonClientService extends IClientService
     /**
      * Like {@link #prepareExportSamples(TableExportCriteria)}, but for persons.
      */
-    public String prepareExportPersons(final TableExportCriteria<Person> criteria)
+    public String prepareExportPersons(final TableExportCriteria<TableModelRowWithObject<Person>> criteria)
             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 86d5da075a3..4b3f344c607 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
@@ -151,10 +151,11 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
 
     /** @see ICommonClientService#listPersons(ListPersonsCriteria) */
     public void listPersons(ListPersonsCriteria criteria,
-            AsyncCallback<ResultSet<Person>> asyncCallback);
+            AsyncCallback<TypedTableResultSet<Person>> asyncCallback);
 
     /** @see ICommonClientService#prepareExportPersons(TableExportCriteria) */
-    public void prepareExportPersons(TableExportCriteria<Person> exportCriteria,
+    public void prepareExportPersons(
+            TableExportCriteria<TableModelRowWithObject<Person>> exportCriteria,
             AsyncCallback<String> callback);
 
     /** @see ICommonClientService#registerPerson(String) */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonGrid.java
index 119dccf50dc..d27a0aebcc3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonGrid.java
@@ -17,12 +17,14 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import com.extjs.gxt.ui.client.event.ButtonEvent;
 import com.extjs.gxt.ui.client.event.SelectionListener;
 import com.extjs.gxt.ui.client.widget.Dialog;
 import com.extjs.gxt.ui.client.widget.button.Button;
+import com.google.gwt.user.client.rpc.AsyncCallback;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
@@ -30,37 +32,37 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplayTypeIDGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.PersonRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.AddPersonDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.AddPersonToAuthorizationGroupDialog;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.PersonColDefKind;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractSimpleBrowserGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IBrowserGridActionInvoker;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractRegistrationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListPersonsCriteria;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TypedTableResultSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 
 /**
  * Grid displaying persons.
  * 
  * @author Piotr Buczek
  */
-public class PersonGrid extends AbstractSimpleBrowserGrid<Person>
+public class PersonGrid extends TypedTableGrid<Person>
 {
 
     // browser consists of the grid and the paging toolbar
     private static final String BROWSER_ID = GenericConstants.ID_PREFIX + "person-browser";
 
-    private static final String GRID_SUFFIX = "_grid";
+    private static final String GRID_SUFFIX = TypedTableGrid.GRID_POSTFIX;
 
     private static final String ADD_BUTTON_SUFFIX = "_add-button";
 
@@ -88,7 +90,7 @@ public class PersonGrid extends AbstractSimpleBrowserGrid<Person>
     private PersonGrid(IViewContext<ICommonClientServiceAsync> viewContext,
             AuthorizationGroup groupOrNull)
     {
-        super(viewContext, createBrowserId(groupOrNull), createGridId(groupOrNull),
+        super(viewContext, createBrowserId(groupOrNull), true,
                 DisplayTypeIDGenerator.PERSON_BROWSER_GRID);
         this.authorizationGroupOrNull = groupOrNull;
     }
@@ -151,11 +153,18 @@ public class PersonGrid extends AbstractSimpleBrowserGrid<Person>
                             new AbstractCreateDialogListener()
                                 {
                                     @Override
-                                    protected Dialog createDialog(List<Person> selected,
+                                    protected Dialog createDialog(
+                                            List<TableModelRowWithObject<Person>> selected,
                                             IBrowserGridActionInvoker invoker)
                                     {
+                                        ArrayList<Person> selectedPersons = new ArrayList<Person>();
+                                        for (TableModelRowWithObject<Person> row : selected)
+                                        {
+                                            selectedPersons.add(row.getObjectOrNull());
+                                        }
                                         return new PersonListDeletionConfirmationDialog(
-                                                viewContext, selected, authorizationGroupOrNull,
+                                                viewContext, selectedPersons,
+                                                authorizationGroupOrNull,
                                                 createRefreshCallback(invoker));
                                     }
                                 });
@@ -178,14 +187,9 @@ public class PersonGrid extends AbstractSimpleBrowserGrid<Person>
     }
 
     @Override
-    protected IColumnDefinitionKind<Person>[] getStaticColumnsDefinition()
-    {
-        return PersonColDefKind.values();
-    }
-
-    @Override
-    protected void listEntities(DefaultResultSetConfig<String, Person> resultSetConfig,
-            AbstractAsyncCallback<ResultSet<Person>> callback)
+    protected void listTableRows(
+            DefaultResultSetConfig<String, TableModelRowWithObject<Person>> resultSetConfig,
+            AsyncCallback<TypedTableResultSet<Person>> callback)
     {
         ListPersonsCriteria criteria = new ListPersonsCriteria(authorizationGroupOrNull);
         criteria.copyPagingConfig(resultSetConfig);
@@ -193,25 +197,41 @@ public class PersonGrid extends AbstractSimpleBrowserGrid<Person>
     }
 
     @Override
-    protected void prepareExportEntities(TableExportCriteria<Person> exportCriteria,
+    protected void prepareExportEntities(TableExportCriteria<TableModelRowWithObject<Person>> exportCriteria,
             AbstractAsyncCallback<String> callback)
     {
         viewContext.getService().prepareExportPersons(exportCriteria, callback);
     }
 
     @Override
-    protected List<IColumnDefinition<Person>> getInitialFilters()
+    protected List<String> getColumnIdsOfFilters()
+    {
+        return Arrays.asList(PersonGridColumnIDs.USER_ID);
+    }
+    
+    @Override
+    protected ColumnDefsAndConfigs<TableModelRowWithObject<Person>> createColumnsDefinition()
+    {
+        ColumnDefsAndConfigs<TableModelRowWithObject<Person>> schema =
+                super.createColumnsDefinition();
+        schema.setGridCellRendererFor(PersonGridColumnIDs.REGISTRATOR,
+                PersonRenderer.REGISTRATOR_RENDERER);
+        return schema;
+    }
+
+    @Override
+    protected String translateColumnIdToDictionaryKey(String columnID)
     {
-        return asColumnFilters(new PersonColDefKind[]
-            { PersonColDefKind.USER_ID });
+        return columnID.toLowerCase();
     }
 
     @Override
-    protected void showEntityViewer(final Person person, boolean editMode, boolean inBackground)
+    protected void showEntityViewer(final TableModelRowWithObject<Person> person, boolean editMode, boolean inBackground)
     {
         assert false : "not implemented";
     }
 
+    @Override
     public DatabaseModificationKind[] getRelevantModifications()
     {
         List<DatabaseModificationKind> databaseModificationKinds =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/PersonColDefKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/PersonColDefKind.java
deleted file mode 100644
index 401207ac078..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/PersonColDefKind.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2009 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific;
-
-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.shared.basic.dto.Person;
-
-/**
- * @author Piotr Buczek
- */
-public enum PersonColDefKind implements IColumnDefinitionKind<Person>
-{
-    USER_ID(new AbstractColumnDefinitionKind<Person>(Dict.USER_ID)
-        {
-            @Override
-            public String tryGetValue(Person entity)
-            {
-                return entity.getUserId();
-            }
-        }),
-
-    FIRST_NAME(new AbstractColumnDefinitionKind<Person>(Dict.FIRST_NAME)
-        {
-            @Override
-            public String tryGetValue(Person entity)
-            {
-                return entity.getFirstName();
-            }
-        }),
-
-    LAST_NAME(new AbstractColumnDefinitionKind<Person>(Dict.LAST_NAME)
-        {
-            @Override
-            public String tryGetValue(Person entity)
-            {
-                return entity.getLastName();
-            }
-        }),
-
-    EMAIL(new AbstractColumnDefinitionKind<Person>(Dict.EMAIL, 200)
-        {
-            @Override
-            public String tryGetValue(Person entity)
-            {
-                return entity.getEmail();
-            }
-        }),
-
-    REGISTRATOR(new AbstractColumnDefinitionKind<Person>(Dict.REGISTRATOR)
-        {
-            @Override
-            public String tryGetValue(Person entity)
-            {
-                return (entity.getRegistrator() == null) ? null : renderRegistrator(entity);
-            }
-        }),
-
-    REGISTRATION_DATE(new AbstractColumnDefinitionKind<Person>(Dict.REGISTRATION_DATE,
-            AbstractColumnDefinitionKind.DATE_COLUMN_WIDTH, false)
-        {
-            @Override
-            public String tryGetValue(Person entity)
-            {
-                return renderRegistrationDate(entity);
-            }
-        });
-
-    private final AbstractColumnDefinitionKind<Person> columnDefinitionKind;
-
-    private PersonColDefKind(AbstractColumnDefinitionKind<Person> columnDefinitionKind)
-    {
-        this.columnDefinitionKind = columnDefinitionKind;
-    }
-
-    public String id()
-    {
-        return name();
-    }
-
-    public AbstractColumnDefinitionKind<Person> getDescriptor()
-    {
-        return columnDefinitionKind;
-    }
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListPersonsCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListPersonsCriteria.java
index 903f0133a9b..57f9b8c5c6b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListPersonsCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ListPersonsCriteria.java
@@ -20,13 +20,14 @@ import com.google.gwt.user.client.rpc.IsSerializable;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 
 /**
  * Criteria for listing persons.
  * 
  * @author Izabela Adamczyk
  */
-public final class ListPersonsCriteria extends DefaultResultSetConfig<String, Person> implements
+public final class ListPersonsCriteria extends DefaultResultSetConfig<String, TableModelRowWithObject<Person>> implements
         IsSerializable
 {
     // If not null, persons form the authorization group will be listed.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/PersonGridColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/PersonGridColumnIDs.java
new file mode 100644
index 00000000000..b6958448227
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/PersonGridColumnIDs.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PersonGrid;
+
+/**
+ * IDs of column of {@link PersonGrid}.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class PersonGridColumnIDs
+{
+    public static final String USER_ID = "USER_ID";
+    public static final String FIRST_NAME = "FIRST_NAME";
+    public static final String LAST_NAME = "LAST_NAME";
+    public static final String EMAIL = "EMAIL";
+    public static final String REGISTRATOR = "REGISTRATOR";
+    public static final String REGISTRATION_DATE = "REGISTRATION_DATE";
+}
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 b8c9ab5e4b9..92348400101 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
@@ -70,6 +70,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.FileFormatTy
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IOriginalDataProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.IResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.MatchingEntitiesProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.PersonsProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.ProjectsProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.RoleAssignmentProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.SampleProvider;
@@ -506,7 +507,7 @@ public final class CommonClientService extends AbstractClientService implements
         return prepareExportEntities(criteria);
     }
 
-    public String prepareExportPersons(TableExportCriteria<Person> criteria)
+    public String prepareExportPersons(TableExportCriteria<TableModelRowWithObject<Person>> criteria)
     {
         return prepareExportEntities(criteria);
     }
@@ -682,20 +683,13 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
-    public ResultSet<Person> listPersons(final ListPersonsCriteria criteria)
+    public TypedTableResultSet<Person> listPersons(final ListPersonsCriteria criteria)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
-        return listEntities(criteria, new AbstractOriginalDataProviderWithoutHeaders<Person>()
-            {
-                @Override
-                public List<Person> getFullOriginalData() throws UserFailureException
-                {
-                    if (criteria.getAuthorizationGroupId() == null)
-                        return listPersons();
-                    else
-                        return listPersonsInAuthorizationGroup(criteria.getAuthorizationGroupId());
-                }
-            });
+        String sessionToken = getSessionToken();
+        TechId authorizationGroupId = criteria.getAuthorizationGroupId();
+        return listEntities(new PersonsProvider(commonServer, sessionToken, authorizationGroupId),
+                criteria);
     }
 
     public final List<Person> listPersons()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProvider.java
new file mode 100644
index 00000000000..5f692d8030b
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProvider.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
+
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs.EMAIL;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs.FIRST_NAME;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs.LAST_NAME;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs.REGISTRATION_DATE;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs.REGISTRATOR;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs.USER_ID;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
+import ch.systemsx.cisd.openbis.generic.shared.util.TypedTableModelBuilder;
+
+/**
+ * Provider of {@link Person} instances.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class PersonsProvider extends AbstractCommonTableModelProvider<Person>
+{
+
+    private final TechId authorizationGroupIdOrNull;
+
+    public PersonsProvider(ICommonServer commonServer, String sessionToken, TechId authorizationGroupIdOrNull)
+    {
+        super(commonServer, sessionToken);
+        this.authorizationGroupIdOrNull = authorizationGroupIdOrNull;
+    }
+
+    @Override
+    protected TypedTableModel<Person> createTableModel(int maxSize)
+    {
+        List<Person> persons;
+        if (authorizationGroupIdOrNull == null)
+        {
+            persons = commonServer.listPersons(sessionToken);
+        } else
+        {
+            persons = commonServer.listPersonInAuthorizationGroup(sessionToken, authorizationGroupIdOrNull);
+        }
+
+        TypedTableModelBuilder<Person> builder = new TypedTableModelBuilder<Person>();
+        builder.addColumn(USER_ID);
+        builder.addColumn(FIRST_NAME);
+        builder.addColumn(LAST_NAME);
+        builder.addColumn(EMAIL).withDefaultWidth(200);
+        builder.addColumn(REGISTRATOR);
+        builder.addColumn(REGISTRATION_DATE).withDefaultWidth(300);
+        for (Person person : persons)
+        {
+            builder.addRow(person);
+            builder.column(USER_ID).addString(person.getUserId());
+            builder.column(FIRST_NAME).addString(person.getFirstName());
+            builder.column(LAST_NAME).addString(person.getLastName());
+            builder.column(EMAIL).addString(person.getEmail());
+            builder.column(REGISTRATOR).addPerson(person.getRegistrator());
+            builder.column(REGISTRATION_DATE).addDate(person.getRegistrationDate());
+        }
+        return builder.getModel();
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationGroupsTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationGroupsTest.java
index 1c9742363c1..952302c8ba0 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationGroupsTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationGroupsTest.java
@@ -27,7 +27,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.Fil
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.OpenAddPersonDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.ShowAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.GroupColDefKind;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.PersonColDefKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractGWTTestCase;
 import ch.systemsx.cisd.openbis.generic.shared.basic.Row;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
@@ -68,7 +68,7 @@ public class AuthorizationGroupsTest extends AbstractGWTTestCase
         remoteConsole.prepare(new OpenAddPersonDialog(authGroup));
         remoteConsole.prepare(FillAddPersonForm.singleUser(userId, authGroup));
         final CheckPersonTable table = new CheckPersonTable(authGroup);
-        table.expectedRow(new Row().withCell(PersonColDefKind.USER_ID.id(), userId));
+        table.expectedRow(new Row().withCell(PersonGridColumnIDs.USER_ID, userId));
         remoteConsole.prepare(table);
 
         launchTest();
@@ -86,7 +86,7 @@ public class AuthorizationGroupsTest extends AbstractGWTTestCase
         final CheckPersonTable table = new CheckPersonTable(authGroup);
         for (String userId : codes)
         {
-            table.expectedRow(new Row().withCell(PersonColDefKind.USER_ID.id(), userId));
+            table.expectedRow(new Row().withCell(PersonGridColumnIDs.USER_ID, userId));
         }
         remoteConsole.prepare(FillAddPersonForm.multipleUsers(codes, authGroup));
         remoteConsole.prepare(table);
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java
index 19dc3ecbcf7..500d9398e68 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java
@@ -28,8 +28,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.Fil
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.OpenRoleAssignmentDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.RoleAssignmentRow;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.GroupColDefKind;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.PersonColDefKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractBrowserGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractGWTTestCase;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.FailureExpectation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.Row;
@@ -70,7 +70,7 @@ public class AuthorizationManagementConsolTest extends AbstractGWTTestCase
         CreatePerson command = new CreatePerson(userId);
         remoteConsole.prepare(command);
         final CheckPersonTable table = new CheckPersonTable();
-        table.expectedRow(new Row().withCell(PersonColDefKind.USER_ID.id(), userId));
+        table.expectedRow(new Row().withCell(PersonGridColumnIDs.USER_ID, userId));
         remoteConsole.prepare(table);
 
         launchTest();
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RemovePerson.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RemovePerson.java
index b5d2a12cde9..810ab47eb9b 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RemovePerson.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RemovePerson.java
@@ -21,8 +21,8 @@ import com.google.gwt.user.client.ui.Widget;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PersonGrid;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.PersonColDefKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.util.GridTestUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractDefaultTestCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.GWTTestUtil;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
@@ -52,7 +52,7 @@ public class RemovePerson extends AbstractDefaultTestCommand
         final Widget widget = GWTTestUtil.getWidgetWithID(PersonGrid.createGridId(authGroup));
         assertTrue(widget instanceof Grid);
         final Grid<BaseEntityModel<Person>> table = (Grid<BaseEntityModel<Person>>) widget;
-        GridTestUtils.fireSelectRow(table, PersonColDefKind.USER_ID.id(), person);
+        GridTestUtils.fireSelectRow(table, PersonGridColumnIDs.USER_ID, person);
         GWTTestUtil.clickButtonWithID(PersonGrid.createRemoveButtonId(authGroup));
     }
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProviderTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProviderTest.java
new file mode 100644
index 00000000000..e7b4c5300d2
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/PersonsProviderTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+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.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PersonBuilder;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class PersonsProviderTest extends AbstractProviderTest
+{
+    @Test
+    public void testWithNoAuthorizationGroup()
+    {
+        final PersonBuilder p1 = new PersonBuilder();
+        p1.name("Isaac", "Newton").userID("in").email("in@o.uk").registrationDate(new Date(4711L));
+        final PersonBuilder p2 = new PersonBuilder();
+        p2.name("Albert", "Einstein").userID("ae").email("ae@c.de").registrator(p1.getPerson());
+        context.checking(new Expectations()
+            {
+                {
+                    one(server).listPersons(SESSION_TOKEN);
+                    will(returnValue(Arrays.asList(p1.getPerson(), p2.getPerson())));
+                }
+            });
+        
+        PersonsProvider personsProvider = new PersonsProvider(server, SESSION_TOKEN, null);
+        TypedTableModel<Person> tableModel = personsProvider.getTableModel(10);
+
+        assertEquals("[USER_ID, FIRST_NAME, LAST_NAME, EMAIL, REGISTRATOR, REGISTRATION_DATE]",
+                getHeaderIDs(tableModel).toString());
+        assertEquals("[VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, TIMESTAMP]",
+                getHeaderDataTypes(tableModel).toString());
+        List<TableModelRowWithObject<Person>> rows = tableModel.getRows();
+        assertSame(p1.getPerson(), rows.get(0).getObjectOrNull());
+        assertEquals("[in, Isaac, Newton, in@o.uk, , Thu Jan 01 01:00:04 CET 1970]", rows.get(0)
+                .getValues().toString());
+        assertSame(p2.getPerson(), rows.get(1).getObjectOrNull());
+        assertEquals("[ae, Albert, Einstein, ae@c.de, Newton, Isaac, ]", rows.get(1).getValues()
+                .toString());
+        assertEquals(2, rows.size());
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testWithAuthorizationGroup()
+    {
+        final PersonBuilder p = new PersonBuilder();
+        p.name("Isaac", "Newton").userID("in").email("in@o.uk").registrationDate(new Date(4711L));
+        final TechId groupId = new TechId(42);
+        context.checking(new Expectations()
+            {
+                {
+                    one(server).listPersonInAuthorizationGroup(SESSION_TOKEN, groupId);
+                    will(returnValue(Arrays.asList(p.getPerson())));
+                }
+            });
+
+        PersonsProvider personsProvider = new PersonsProvider(server, SESSION_TOKEN, groupId);
+        TypedTableModel<Person> tableModel = personsProvider.getTableModel(10);
+
+        assertEquals("[USER_ID, FIRST_NAME, LAST_NAME, EMAIL, REGISTRATOR, REGISTRATION_DATE]",
+                getHeaderIDs(tableModel).toString());
+        assertEquals("[VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, TIMESTAMP]",
+                getHeaderDataTypes(tableModel).toString());
+        List<TableModelRowWithObject<Person>> rows = tableModel.getRows();
+        assertSame(p.getPerson(), rows.get(0).getObjectOrNull());
+        assertEquals("[in, Isaac, Newton, in@o.uk, , Thu Jan 01 01:00:04 CET 1970]", rows.get(0)
+                .getValues().toString());
+        assertEquals(1, rows.size());
+        context.assertIsSatisfied();
+    }
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/builders/PersonBuilder.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/builders/PersonBuilder.java
index 57c558dc53f..6e25ab25717 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/builders/PersonBuilder.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/builders/PersonBuilder.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders;
 
+import java.util.Date;
+
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 
 /**
@@ -40,6 +42,24 @@ public class PersonBuilder
         return this;
     }
     
+    public PersonBuilder email(String email)
+    {
+        person.setEmail(email);
+        return this;
+    }
+    
+    public PersonBuilder registrator(Person registrator)
+    {
+        person.setRegistrator(registrator);
+        return this;
+    }
+    
+    public PersonBuilder registrationDate(Date registrationDate)
+    {
+        person.setRegistrationDate(registrationDate);
+        return this;
+    }
+    
     public final Person getPerson()
     {
         return person;
-- 
GitLab