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 9ce4d92410bf1a3b88b2952d93f6b4a5b98d801f..a1045527de3f4710e9c0b4fe099d53c000a6565b 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
@@ -360,6 +360,10 @@ public interface ICommonClientService extends IClientService {
 	 */
 	public void registerVocabulary(final Vocabulary vocabulary)
 			throws UserFailureException;
+	
+	/** Adds specified terms to the specified vocabulary. */
+    public void addVocabularyTerms(String vocabularyCode, List<String> vocabularyTerms)
+            throws UserFailureException;
 
 	/**
 	 * Registers given {@link Project}.
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 219c0b3a621f692916e00432ef5fd5ebba50dbef..cf5123c7a0ba8cebdd7d633f82033b778f7d50e5 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
@@ -19,6 +19,8 @@ package ch.systemsx.cisd.openbis.generic.client.web.client;
 import java.util.Date;
 import java.util.List;
 
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentIdentifier;
@@ -55,8 +57,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
 /**
  * Asynchronous version of {@link ICommonClientService}.
  * 
@@ -299,6 +299,10 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync {
 	public void registerVocabulary(final Vocabulary vocabulary,
 			final AsyncCallback<Void> asyncCallback);
 
+	/** @see ICommonClientService#addVocabularyTerms(String, List) */
+    public void addVocabularyTerms(String vocabularyCode, List<String> vocabularyTerms,
+            AsyncCallback<Void> callback);
+    
 	/** @see ICommonClientService#registerProject(Project) */
 	public void registerProject(Project project,
 			final AsyncCallback<Void> projectRegistrationCallback);
@@ -376,5 +380,6 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync {
 
     /** @see ICommonClientService#uploadDataSets(List, String, String) */
     public void uploadDataSets(List<String> dataSetCodes, String cifexURL, String password,
-            AsyncCallback<Void> abstractAsyncCallback);
+            AsyncCallback<Void> callback);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index 2b04cf16b6fce44ddead2a9d65404543d0dd37e5..8638774c6bb5108161c95d37fe7c72746ef4f04e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -419,6 +419,14 @@ public abstract class Dict {
 	public static final String TERM_FOR_MATERIALS_USAGE = "TERM_FOR_MATERIALS_USAGE";
 
 	public static final String TERM_TOTAL_USAGE = "TERM_TOTAL_USAGE";
+	
+	public static final String ADD_VOCABULARY_TERMS_BUTTON = "add_vocabulary_terms_button";
+	
+	public static final String ADD_VOCABULARY_TERMS_TITLE = "add_vocabulary_terms_title";
+	
+	public static final String ADD_VOCABULARY_TERMS_OK_BUTTON = "add_vocabulary_terms_ok_button";
+	
+	public static final String VOCABULARY_TERMS_VALIDATION_MESSAGE = "vocabulary_terms_validation_message";
 
 	//
 	// Project Browser
@@ -484,5 +492,7 @@ public abstract class Dict {
 
 	public static final String BUTTON_EDIT = "edit";
 
+
+
 	// ----- end generic ------------------
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
index df7b6351757af2a83502d8b88266dae0577c73f6..46e0b7f1a9e7b9ee2d5efbb48d976ff21265fa18 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
@@ -18,14 +18,26 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.vocabu
 
 import java.util.List;
 
+import com.extjs.gxt.ui.client.event.ButtonEvent;
+import com.extjs.gxt.ui.client.event.ComponentEvent;
+import com.extjs.gxt.ui.client.event.KeyListener;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.HorizontalPanel;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.form.TextArea;
+import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
+
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.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.ui.columns.framework.IColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.VocabularyTermColDefKind;
 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.DisposableComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.SimpleDialog;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
@@ -42,6 +54,20 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
 {
     // browser consists of the grid and the paging toolbar
     private static final String BROWSER_ID = GenericConstants.ID_PREFIX + "vocabulary-term-browser";
+    
+    final class VoidCallback extends AbstractAsyncCallback<Void>
+    {
+        private VoidCallback(IViewContext<?> viewContext)
+        {
+            super(viewContext);
+        }
+
+        @Override
+        protected void process(Void result)
+        {
+            refresh();
+        }
+    }
 
     private final Vocabulary vocabulary;
 
@@ -56,6 +82,16 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
     {
         super(viewContext, createBrowserId(vocabulary), createGridId(vocabulary.getCode()));
         this.vocabulary = vocabulary;
+        Button button = new Button(viewContext.getMessage(Dict.ADD_VOCABULARY_TERMS_BUTTON));
+        button.addSelectionListener(new SelectionListener<ButtonEvent>()
+            {
+                @Override
+                public void componentSelected(ButtonEvent ce)
+                {
+                    askForNewTerms();
+                }
+            });
+        pagingToolbar.add(new AdapterToolItem(button));
     }
 
     public static String createGridId(String vocabularyCode)
@@ -100,4 +136,39 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
     {
         viewContext.getService().prepareExportVocabularyTerms(exportCriteria, callback);
     }
+    
+    private void askForNewTerms()
+    {
+        final TextArea textArea = new TextArea();
+        textArea.setWidth(250);
+        textArea.setHeight(200);
+        textArea.setEmptyText(viewContext.getMessage(Dict.VOCABULARY_TERMS_EMPTY));
+        textArea.setValidator(new VocabularyTermValidator(viewContext, vocabulary.getTerms()));
+        String heading = viewContext.getMessage(Dict.ADD_VOCABULARY_TERMS_TITLE);
+        String okButtonLabel = viewContext.getMessage(Dict.ADD_VOCABULARY_TERMS_OK_BUTTON);
+        HorizontalPanel panel = new HorizontalPanel();
+        panel.setWidth(300);
+        panel.add(textArea);
+        panel.setBorders(true);
+        final SimpleDialog dialog = new SimpleDialog(panel, heading, okButtonLabel, viewContext);
+        textArea.addKeyListener(new KeyListener()
+            {
+                @Override
+                public void handleEvent(ComponentEvent ce)
+                {
+                    textArea.validate();
+                    dialog.setEnableOfAcceptButton(textArea.isValid());
+                }
+            });
+        dialog.setAcceptAction(new IDelegatedAction()
+            {
+                public void execute()
+                {
+                    viewContext.getCommonService().addVocabularyTerms(vocabulary.getCode(),
+                            VocabularyTermValidator.getTerms(textArea.getValue()),
+                            new VoidCallback(viewContext));
+                }
+            });
+        dialog.show();
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermValidator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermValidator.java
index df599fd817a3216a288bfd1311992d8c6cd2565a..f83409e294593e46d28eed67fcc7919d2ba62980 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermValidator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermValidator.java
@@ -1,7 +1,10 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.vocabulary;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import com.extjs.gxt.ui.client.widget.form.TextArea;
 import com.extjs.gxt.ui.client.widget.form.Validator;
@@ -10,6 +13,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.CodeField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
 
 /**
  * A {@link Validator} implementation which validates vocabulary terms in a text area.
@@ -19,10 +23,22 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.Strin
 final class VocabularyTermValidator implements Validator<String, TextArea>
 {
     private final IMessageProvider messageProvider;
+    private Set<String> existingTerms;
 
     VocabularyTermValidator(final IMessageProvider messageProvider)
+    {
+        this(messageProvider, Collections.<VocabularyTerm>emptyList());
+    }
+
+    public VocabularyTermValidator(final IMessageProvider messageProvider,
+            List<VocabularyTerm> terms)
     {
         this.messageProvider = messageProvider;
+        existingTerms = new HashSet<String>();
+        for (VocabularyTerm vocabularyTerm : terms)
+        {
+            existingTerms.add(vocabularyTerm.getCode());
+        }
     }
 
     final static List<String> getTerms(final String value)
@@ -60,6 +76,10 @@ final class VocabularyTermValidator implements Validator<String, TextArea>
             {
                 return messageProvider.getMessage(Dict.INVALID_CODE_MESSAGE, "Term '" + term + "'");
             }
+            if (existingTerms.contains(term.toUpperCase()))
+            {
+                return messageProvider.getMessage(Dict.VOCABULARY_TERMS_VALIDATION_MESSAGE, term);
+            }
         }
         return null;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/SimpleDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/SimpleDialog.java
index 86bb46bcb45a01117cc28fd5b8ba76d554a85501..88657cf1d7a26e670788224d4de650b6e79e461d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/SimpleDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/SimpleDialog.java
@@ -42,10 +42,13 @@ public class SimpleDialog extends Dialog
 
     private final IMessageProvider messageProvider;
 
+    private final Button acceptButton;
+    
     private IDelegatedAction acceptActionOrNull;
 
     private IDelegatedAction cancelActionOrNull;
 
+
     public SimpleDialog(final Widget widget, final String heading, String acceptButtonLabel,
             IMessageProvider messageProvider)
     {
@@ -58,7 +61,8 @@ public class SimpleDialog extends Dialog
         setModal(true);
 
         add(widget);
-        addButton(createAcceptButton(acceptButtonLabel));
+        acceptButton = createAcceptButton(acceptButtonLabel);
+        addButton(acceptButton);
         addButton(createCancelButton());
 
         addWindowListener(new WindowListener()
@@ -70,7 +74,12 @@ public class SimpleDialog extends Dialog
                 }
             });
     }
-
+    
+    public void setEnableOfAcceptButton(boolean enable)
+    {
+        acceptButton.setEnabled(enable);
+    }
+    
     private Button createCancelButton()
     {
         final Button button =
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 ec17b31014827f9288d7e0d143eea50fd749515c..f195acd9b5e637902ddd554dc249393dceafc8ed 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
@@ -122,8 +122,9 @@ import ch.systemsx.cisd.openbis.plugin.AbstractClientService;
  * @author Franz-Josef Elmer
  */
 public final class CommonClientService extends AbstractClientService implements
-		ICommonClientService {
-	private final ICommonServer commonServer;
+        ICommonClientService
+{
+    private final ICommonServer commonServer;
 
     private String dataStoreBaseURL;
 
@@ -139,12 +140,13 @@ public final class CommonClientService extends AbstractClientService implements
         this.dataStoreBaseURL = dataStoreBaseURL + "/" + DATA_STORE_SERVER_WEB_APPLICATION_NAME;
     }
 
-	@Override
-	protected final IServer getServer() {
-		return commonServer;
-	}
+    @Override
+    protected final IServer getServer()
+    {
+        return commonServer;
+    }
 
-	// ----------- export and listing with cache generic functionality
+    // ----------- export and listing with cache generic functionality
 
     @SuppressWarnings("unchecked")
     private final <K> IResultSetManager<K> getResultSetManager()
@@ -159,802 +161,914 @@ public final class CommonClientService extends AbstractClientService implements
                 .getAttribute(SessionConstants.OPENBIS_RESULT_SET_MANAGER);
     }
 
-	@SuppressWarnings("unchecked")
-	private final <T> CacheManager<String, T> getExportManager() {
-		return (CacheManager<String, T>) getHttpSession().getAttribute(
-				SessionConstants.OPENBIS_EXPORT_MANAGER);
-	}
-
-	/**
-	 * Returns and removes cached export criteria.
-	 */
-	private final <T> TableExportCriteria<T> getAndRemoveExportCriteria(
-			final String exportDataKey) {
-		final CacheManager<String, TableExportCriteria<T>> exportManager = getExportManager();
-		final TableExportCriteria<T> exportCriteria = exportManager
-				.tryGetData(exportDataKey);
-		assert exportCriteria != null : "No export criteria found at key "
-				+ exportDataKey;
-		getExportManager().removeData(exportDataKey);
-		return exportCriteria;
-	}
-
-	private final <T> List<T> fetchCachedEntities(
-			final TableExportCriteria<T> exportCriteria) {
-		final IResultSetManager<String> resultSetManager = getResultSetManager();
-		IResultSetConfig<String, T> resultSetConfig = createExportListCriteria(exportCriteria);
-		IOriginalDataProvider<T> dummyDataProvider = createDummyDataProvider();
-		final IResultSet<String, T> result = resultSetManager.getResultSet(
-				resultSetConfig, dummyDataProvider);
-		final ResultSet<T> entities = ResultSetTranslator.translate(result);
-		return entities.getList();
-	}
-
-	private static <T> IOriginalDataProvider<T> createDummyDataProvider() {
-		return new IOriginalDataProvider<T>() {
-			public List<T> getOriginalData() throws UserFailureException {
-				throw new IllegalStateException("Data not found in the cache");
-			}
-		};
-	}
-
-	private static <T> IResultSetConfig<String, T> createExportListCriteria(
-			final TableExportCriteria<T> exportCriteria) {
-		final DefaultResultSetConfig<String, T> criteria = DefaultResultSetConfig
-				.createFetchAll();
-		criteria.setSortInfo(exportCriteria.getSortInfo());
-		criteria.setFilterInfos(exportCriteria.getFilterInfos());
-		criteria.setResultSetKey(exportCriteria.getResultSetKey());
-		return criteria;
-	}
-
-	private <T> ResultSet<T> listEntities(
-			final IResultSetConfig<String, T> criteria,
-			IOriginalDataProvider<T> dataProvider)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final IResultSetManager<String> resultSetManager = getResultSetManager();
-			final IResultSet<String, T> result = resultSetManager.getResultSet(
-					criteria, dataProvider);
-			return ResultSetTranslator.translate(result);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	/**
-	 * Assumes that preparation of the export (
-	 * {@link #prepareExportSamples(TableExportCriteria)} has been invoked
-	 * before and returned with an exportDataKey passed here as a parameter.
-	 */
-	public final String getExportTable(final String exportDataKey,
-			final String lineSeparator) {
-		// NOTE: no generics in GWT
-		return getGenericExportTable(exportDataKey, lineSeparator);
-	}
-
-	private final <T> String getGenericExportTable(final String exportDataKey,
-			final String lineSeparator) {
-		try {
-			// Not directly needed but this refreshes the session.
-			getSessionToken();
-			final TableExportCriteria<T> exportCriteria = getAndRemoveExportCriteria(exportDataKey);
-			final List<T> entities = fetchCachedEntities(exportCriteria);
-			return TSVRenderer.createTable(entities, exportCriteria
-					.getColumnDefs(), lineSeparator);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	private <T> String prepareExportEntities(TableExportCriteria<T> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			// Not directly needed but this refreshes the session.
-			getSessionToken();
-			final CacheManager<String, TableExportCriteria<T>> exportManager = getExportManager();
-			return exportManager.saveData(criteria);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void removeResultSet(final String resultSetKey)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			// Not directly needed but this refreshes the session.
-			getSessionToken();
-			getResultSetManager().removeResultSet(resultSetKey);
-		} catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	// --------------- end export & listing
-
-	//
-	// IGenericClientService
-	//
-
-	public final List<Group> listGroups(final String databaseInstanceCode) {
-		try {
-			final String sessionToken = getSessionToken();
-			final DatabaseInstanceIdentifier identifier = new DatabaseInstanceIdentifier(
-					databaseInstanceCode);
-			final List<Group> result = new ArrayList<Group>();
-			final List<GroupPE> groups = commonServer.listGroups(sessionToken,
-					identifier);
-			for (final GroupPE group : groups) {
-				result.add(GroupTranslator.translate(group));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void registerGroup(final String groupCode,
-			final String descriptionOrNull, final String groupLeaderOrNull) {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerGroup(sessionToken, groupCode,
-					descriptionOrNull, groupLeaderOrNull);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final List<Person> listPersons()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-
-		try {
-			final String sessionToken = getSessionToken();
-			final List<Person> result = new ArrayList<Person>();
-			final List<PersonPE> persons = commonServer
-					.listPersons(sessionToken);
-			for (final PersonPE person : persons) {
-				result.add(PersonTranslator.translate(person));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void registerPerson(final String code) {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerPerson(sessionToken, code);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final List<RoleAssignment> listRoles()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<RoleAssignment> result = new ArrayList<RoleAssignment>();
-			final List<RoleAssignmentPE> roles = commonServer
-					.listRoles(sessionToken);
-			for (final RoleAssignmentPE role : roles) {
-				result.add(RoleAssignmentTranslator.translate(role));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void registerGroupRole(final RoleSetCode roleSetCode,
-			final String group, final String person)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final GroupIdentifier groupIdentifier = new GroupIdentifier(
-					DatabaseInstanceIdentifier.HOME, group);
-			commonServer.registerGroupRole(sessionToken, RoleCodeTranslator
-					.translate(roleSetCode), groupIdentifier, person);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void registerInstanceRole(final RoleSetCode roleSetCode,
-			final String person)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerInstanceRole(sessionToken, RoleCodeTranslator
-					.translate(roleSetCode), person);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void deleteGroupRole(final RoleSetCode roleSetCode,
-			final String group, final String person)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final GroupIdentifier groupIdentifier = new GroupIdentifier(
-					DatabaseInstanceIdentifier.HOME, group);
-			commonServer.deleteGroupRole(sessionToken, RoleCodeTranslator
-					.translate(roleSetCode), groupIdentifier, person);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-
-	}
-
-	public final void deleteInstanceRole(final RoleSetCode roleSetCode,
-			final String person)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.deleteInstanceRole(sessionToken, RoleCodeTranslator
-					.translate(roleSetCode), person);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-
-	}
-
-	public final List<SampleType> listSampleTypes()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<SampleTypePE> sampleTypes = commonServer
-					.listSampleTypes(sessionToken);
-			final List<SampleType> result = new ArrayList<SampleType>();
-			for (final SampleTypePE sampleTypePE : sampleTypes) {
-				result.add(SampleTypeTranslator.translate(sampleTypePE));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	// --------- methods preparing exported content. Note: GWT does not support
-	// generic methods :(
-
-	public final String prepareExportSamples(
-			final TableExportCriteria<Sample> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public final String prepareExportExperiments(
-			final TableExportCriteria<Experiment> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public final String prepareExportMatchingEntities(
-			final TableExportCriteria<MatchingEntity> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportPropertyTypes(
-			TableExportCriteria<PropertyType> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportPropertyTypeAssignments(
-			TableExportCriteria<EntityTypePropertyType<?>> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportProjects(TableExportCriteria<Project> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportVocabularies(
-			final TableExportCriteria<Vocabulary> criteria)
-			throws UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportVocabularyTerms(
-			TableExportCriteria<VocabularyTermWithStats> criteria) {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportMaterialTypes(
-			final TableExportCriteria<MaterialType> criteria)
-			throws UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportExperimentTypes(
-			final TableExportCriteria<ExperimentType> criteria)
-			throws UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public String prepareExportSampleTypes(
-			final TableExportCriteria<SampleType> criteria)
-			throws UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	// ---------------- methods which list entities using cache
-
-	public final ResultSet<Sample> listSamples(
-			final ListSampleCriteria listCriteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		final String sessionToken = getSessionToken();
-		return listEntities(listCriteria, new ListSamplesOriginalDataProvider(
-				commonServer, sessionToken, listCriteria));
-	}
-
-	public ResultSet<ExternalData> searchForDataSets(
-			DataSetSearchCriteria criteria,
-			final IResultSetConfig<String, ExternalData> resultSetConfig)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		final String sessionToken = getSessionToken();
-		return listEntities(resultSetConfig,
-				new ListDataSetsOriginalDataProvider(commonServer,
-						sessionToken, criteria, dataStoreBaseURL));
-	}
-
-	public final ResultSet<Experiment> listExperiments(
-			final ListExperimentsCriteria listCriteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		final String sessionToken = getSessionToken();
-		return listEntities(listCriteria,
-				new ListExperimentsOriginalDataProvider(commonServer,
-						listCriteria, sessionToken));
-	}
-
-	public ResultSet<PropertyType> listPropertyTypes(
-			DefaultResultSetConfig<String, PropertyType> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria,
-				new IOriginalDataProvider<PropertyType>() {
-					public List<PropertyType> getOriginalData()
-							throws UserFailureException {
-						return listPropertyTypes();
-					}
-				});
-	}
-
-	public final ResultSet<MatchingEntity> listMatchingEntities(
-			final SearchableEntity searchableEntityOrNull,
-			final String queryText,
-			final IResultSetConfig<String, MatchingEntity> resultSetConfig)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		final String sessionToken = getSessionToken();
-		final ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity[] matchingEntities = SearchableEntityTranslator
-				.translate(searchableEntityOrNull);
-		return listEntities(resultSetConfig,
-				new ListMatchingEntitiesOriginalDataProvider(commonServer,
-						sessionToken, matchingEntities, queryText));
-	}
-
-	public ResultSet<EntityTypePropertyType<?>> listPropertyTypeAssignments(
-			DefaultResultSetConfig<String, EntityTypePropertyType<?>> criteria) {
-		return listEntities(criteria,
-				new IOriginalDataProvider<EntityTypePropertyType<?>>() {
-					public List<EntityTypePropertyType<?>> getOriginalData()
-							throws UserFailureException {
-						return extractAssignments(listPropertyTypes());
-					}
-				});
-	}
-
-	private static List<EntityTypePropertyType<?>> extractAssignments(
-			List<PropertyType> listPropertyTypes) {
-		List<EntityTypePropertyType<?>> result = new ArrayList<EntityTypePropertyType<?>>();
-		for (PropertyType propertyType : listPropertyTypes) {
-			extractAssignments(result, propertyType);
-		}
-		return result;
-	}
-
-	private static void extractAssignments(
-			List<EntityTypePropertyType<?>> result,
-			final PropertyType propertyType) {
-		for (ExperimentTypePropertyType etpt : propertyType
-				.getExperimentTypePropertyTypes()) {
-			result.add(etpt);
-		}
-		for (SampleTypePropertyType etpt : propertyType
-				.getSampleTypePropertyTypes()) {
-			result.add(etpt);
-		}
-		for (MaterialTypePropertyType etpt : propertyType
-				.getMaterialTypePropertyTypes()) {
-			result.add(etpt);
-		}
-	}
-
-	public ResultSet<Project> listProjects(
-			DefaultResultSetConfig<String, Project> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria, new IOriginalDataProvider<Project>() {
-			public List<Project> getOriginalData() throws UserFailureException {
-				return listProjects();
-			}
-		});
-	}
-
-	private List<Project> listProjects()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<ProjectPE> projects = commonServer
-					.listProjects(sessionToken);
-			return ProjectTranslator.translate(projects);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public ResultSet<Vocabulary> listVocabularies(final boolean withTerms,
-			final boolean excludeInternal,
-			DefaultResultSetConfig<String, Vocabulary> criteria)
-			throws UserFailureException {
-		return listEntities(criteria, new IOriginalDataProvider<Vocabulary>() {
-			public List<Vocabulary> getOriginalData()
-					throws UserFailureException {
-				return listVocabularies(withTerms, excludeInternal);
-			}
-		});
-	}
-
-	private List<Vocabulary> listVocabularies(final boolean withTerms,
-			boolean excludeInternal)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<VocabularyPE> vocabularies = commonServer
-					.listVocabularies(sessionToken, withTerms, excludeInternal);
-			return BeanUtils.createBeanList(Vocabulary.class, vocabularies,
-					DtoConverters.getVocabularyConverter());
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public ResultSet<VocabularyTermWithStats> listVocabularyTerms(
-			final Vocabulary vocabulary,
-			DefaultResultSetConfig<String, VocabularyTermWithStats> criteria) {
-		return listEntities(criteria,
-				new IOriginalDataProvider<VocabularyTermWithStats>() {
-					public List<VocabularyTermWithStats> getOriginalData()
-							throws UserFailureException {
-						List<ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats> terms = commonServer
-								.listVocabularyTerms(getSessionToken(),
-										vocabulary);
-						return VocabularyTermTranslator.translate(terms);
-					}
-				});
-	}
-
-	public ResultSet<? extends EntityType> listMaterialTypes(
-			DefaultResultSetConfig<String, MaterialType> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria,
-				new IOriginalDataProvider<MaterialType>() {
-					public List<MaterialType> getOriginalData()
-							throws UserFailureException {
-						return listMaterialTypes();
-					}
-				});
-	}
-
-	public ResultSet<? extends EntityType> listSampleTypes(
-			DefaultResultSetConfig<String, SampleType> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria, new IOriginalDataProvider<SampleType>() {
-			public List<SampleType> getOriginalData()
-					throws UserFailureException {
-				return listSampleTypes();
-			}
-		});
-	}
-
-	public ResultSet<? extends EntityType> listExperimentTypes(
-			DefaultResultSetConfig<String, ExperimentType> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria,
-				new IOriginalDataProvider<ExperimentType>() {
-					public List<ExperimentType> getOriginalData()
-							throws UserFailureException {
-						return listExperimentTypes();
-					}
-				});
-	}
-
-	public ResultSet<ExternalData> listSampleDataSets(
-			final String sampleIdentifier,
-			DefaultResultSetConfig<String, ExternalData> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria,
-				new IOriginalDataProvider<ExternalData>() {
-					public List<ExternalData> getOriginalData()
-							throws UserFailureException {
-						final String sessionToken = getSessionToken();
-						final SampleIdentifier identifier = SampleIdentifierFactory
-								.parse(sampleIdentifier);
-						final List<ExternalDataPE> externalData = commonServer
-								.listExternalData(sessionToken, identifier);
-						return ExternalDataTranslator.translate(externalData,
-								dataStoreBaseURL);
-					}
-				});
-	}
-
-	public ResultSet<ExternalData> listExperimentDataSets(
-			final String experimentIdentifier,
-			DefaultResultSetConfig<String, ExternalData> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return listEntities(criteria,
-				new IOriginalDataProvider<ExternalData>() {
-
-					public List<ExternalData> getOriginalData()
-							throws UserFailureException {
-						final String sessionToken = getSessionToken();
-						final ExperimentIdentifier identifier = new ExperimentIdentifierFactory(
-								experimentIdentifier).createIdentifier();
-						final List<ExternalDataPE> externalData = commonServer
-								.listExternalData(sessionToken, identifier);
-						return ExternalDataTranslator.translate(externalData,
-								dataStoreBaseURL);
-					}
-
-				});
-	}
-
-	// ---------------- end list using cache ----------
-
-	public final List<SearchableEntity> listSearchableEntities()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			// Not directly needed but this refreshes the session.
-			getSessionToken();
-			final List<SearchableEntity> searchableEntities = BeanUtils
-					.createBeanList(
-							SearchableEntity.class,
-							Arrays
-									.asList(ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity
-											.values()));
-			Collections.sort(searchableEntities);
-			return searchableEntities;
-		} catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public List<ExperimentType> listExperimentTypes()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<ExperimentType> result = new ArrayList<ExperimentType>();
-			final List<ExperimentTypePE> experiments = commonServer
-					.listExperimentTypes(sessionToken);
-			for (final ExperimentTypePE expType : experiments) {
-				result.add(ExperimentTranslator.translate(expType));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	private List<PropertyType> listPropertyTypes()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<PropertyTypePE> propertyTypes = commonServer
-					.listPropertyTypes(sessionToken);
-			return PropertyTypeTranslator.translate(propertyTypes);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final List<DataType> listDataTypes()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<DataTypePE> dataTypes = commonServer
-					.listDataTypes(sessionToken);
-			return BeanUtils.createBeanList(DataType.class, dataTypes,
-					DtoConverters.getDataTypeConverter());
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public String assignPropertyType(final EntityKind entityKind,
-			final String propertyTypeCode, final String entityTypeCode,
-			final boolean isMandatory, final String defaultValue)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			return commonServer.assignPropertyType(sessionToken, DtoConverters
-					.convertEntityKind(entityKind), propertyTypeCode,
-					entityTypeCode, isMandatory, defaultValue);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void registerPropertyType(final PropertyType propertyType)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		assert propertyType != null : "Unspecified property type.";
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerPropertyType(sessionToken, propertyType);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public final void registerVocabulary(final Vocabulary vocabulary)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		assert vocabulary != null : "Unspecified vocabulary.";
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerVocabulary(sessionToken, vocabulary);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public void registerProject(Project project)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		assert project != null : "Unspecified project.";
-		try {
-			final String sessionToken = getSessionToken();
-			final ProjectIdentifier projectIdentifier = new ProjectIdentifierFactory(
-					project.getIdentifier()).createIdentifier();
-			Person leader = project.getProjectLeader();
-			final String leaderId = leader == null ? null : project
-					.getProjectLeader().getUserId();
-			commonServer.registerProject(sessionToken, projectIdentifier,
-					project.getDescription(), leaderId);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public String prepareExportDataSetSearchHits(
-			TableExportCriteria<ExternalData> exportCriteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(exportCriteria);
-	}
-
-	public List<MaterialType> listMaterialTypes()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<MaterialType> result = new ArrayList<MaterialType>();
-			final List<MaterialTypePE> projects = commonServer
-					.listMaterialTypes(sessionToken);
-			for (final MaterialTypePE expType : projects) {
-				result.add(MaterialTypeTranslator.translate(expType));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public List<DataSetType> listDataSetTypes()
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final List<DataSetType> result = new ArrayList<DataSetType>();
-			final List<DataSetTypePE> types = commonServer
-					.listDataSetTypes(sessionToken);
-			for (final DataSetTypePE type : types) {
-				result.add(DataSetTypeTranslator.translate(type));
-			}
-			return result;
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public ResultSet<Material> listMaterials(ListMaterialCriteria criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		final String sessionToken = getSessionToken();
-		return listEntities(criteria, new ListMaterialOriginalDataProvider(
-				commonServer, sessionToken, criteria));
-	}
-
-	public String prepareExportMaterials(TableExportCriteria<Material> criteria)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		return prepareExportEntities(criteria);
-	}
-
-	public void registerMaterialType(MaterialType entityType)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerMaterialType(sessionToken, entityType);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public void registerExperimentType(ExperimentType entityType)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerExperimentType(sessionToken, entityType);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	public void registerSampleType(SampleType entityType)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.registerSampleType(sessionToken, entityType);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-
-	private final static AttachmentPE createAttachment(String fileName,
-			final byte[] content) {
-		final AttachmentPE attachment = new AttachmentPE();
-		attachment.setFileName(fileName);
-		final AttachmentContentPE attachmentContent = new AttachmentContentPE();
-		attachmentContent.setValue(content);
-		attachment.setAttachmentContent(attachmentContent);
-		return attachment;
-	}
-
-	public void updateExperiment(String sessionKey,
-			String experimentIdentifier, List<ExperimentProperty> properties,
-			String newProjectIdentifier, Date version)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-
-		UploadedFilesBean uploadedFiles = null;
-		HttpSession session = null;
-		try {
-			final String sessionToken = getSessionToken();
-			session = getHttpSession();
-			uploadedFiles = (UploadedFilesBean) session
-					.getAttribute(sessionKey);
-			List<AttachmentPE> attachments = new ArrayList<AttachmentPE>();
-			if (uploadedFiles != null) {
-				for (final IUncheckedMultipartFile multipartFile : uploadedFiles
-						.iterable()) {
-					String fileName = multipartFile.getOriginalFilename();
-					byte[] content = multipartFile.getBytes();
-					attachments.add(createAttachment(fileName, content));
-				}
-			}
-			final ExperimentIdentifier identifier = new ExperimentIdentifierFactory(
-					experimentIdentifier).createIdentifier();
-			final ProjectIdentifier project = new ProjectIdentifierFactory(
-					newProjectIdentifier).createIdentifier();
-			commonServer.editExperiment(sessionToken, identifier, properties,
-					attachments, project, version);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		} finally {
-			if (uploadedFiles != null) {
-				uploadedFiles.deleteTransferredFiles();
-			}
-			if (session != null) {
-				session.removeAttribute(sessionKey);
-			}
-		}
-
-	}
+    @SuppressWarnings("unchecked")
+    private final <T> CacheManager<String, T> getExportManager()
+    {
+        return (CacheManager<String, T>) getHttpSession().getAttribute(
+                SessionConstants.OPENBIS_EXPORT_MANAGER);
+    }
+
+    /**
+     * Returns and removes cached export criteria.
+     */
+    private final <T> TableExportCriteria<T> getAndRemoveExportCriteria(final String exportDataKey)
+    {
+        final CacheManager<String, TableExportCriteria<T>> exportManager = getExportManager();
+        final TableExportCriteria<T> exportCriteria = exportManager.tryGetData(exportDataKey);
+        assert exportCriteria != null : "No export criteria found at key " + exportDataKey;
+        getExportManager().removeData(exportDataKey);
+        return exportCriteria;
+    }
+
+    private final <T> List<T> fetchCachedEntities(final TableExportCriteria<T> exportCriteria)
+    {
+        final IResultSetManager<String> resultSetManager = getResultSetManager();
+        IResultSetConfig<String, T> resultSetConfig = createExportListCriteria(exportCriteria);
+        IOriginalDataProvider<T> dummyDataProvider = createDummyDataProvider();
+        final IResultSet<String, T> result =
+                resultSetManager.getResultSet(resultSetConfig, dummyDataProvider);
+        final ResultSet<T> entities = ResultSetTranslator.translate(result);
+        return entities.getList();
+    }
+
+    private static <T> IOriginalDataProvider<T> createDummyDataProvider()
+    {
+        return new IOriginalDataProvider<T>()
+            {
+                public List<T> getOriginalData() throws UserFailureException
+                {
+                    throw new IllegalStateException("Data not found in the cache");
+                }
+            };
+    }
+
+    private static <T> IResultSetConfig<String, T> createExportListCriteria(
+            final TableExportCriteria<T> exportCriteria)
+    {
+        final DefaultResultSetConfig<String, T> criteria = DefaultResultSetConfig.createFetchAll();
+        criteria.setSortInfo(exportCriteria.getSortInfo());
+        criteria.setFilterInfos(exportCriteria.getFilterInfos());
+        criteria.setResultSetKey(exportCriteria.getResultSetKey());
+        return criteria;
+    }
+
+    private <T> ResultSet<T> listEntities(final IResultSetConfig<String, T> criteria,
+            IOriginalDataProvider<T> dataProvider)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final IResultSetManager<String> resultSetManager = getResultSetManager();
+            final IResultSet<String, T> result =
+                    resultSetManager.getResultSet(criteria, dataProvider);
+            return ResultSetTranslator.translate(result);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    /**
+     * Assumes that preparation of the export ( {@link #prepareExportSamples(TableExportCriteria)}
+     * has been invoked before and returned with an exportDataKey passed here as a parameter.
+     */
+    public final String getExportTable(final String exportDataKey, final String lineSeparator)
+    {
+        // NOTE: no generics in GWT
+        return getGenericExportTable(exportDataKey, lineSeparator);
+    }
+
+    private final <T> String getGenericExportTable(final String exportDataKey,
+            final String lineSeparator)
+    {
+        try
+        {
+            // Not directly needed but this refreshes the session.
+            getSessionToken();
+            final TableExportCriteria<T> exportCriteria = getAndRemoveExportCriteria(exportDataKey);
+            final List<T> entities = fetchCachedEntities(exportCriteria);
+            return TSVRenderer.createTable(entities, exportCriteria.getColumnDefs(), lineSeparator);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    private <T> String prepareExportEntities(TableExportCriteria<T> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            // Not directly needed but this refreshes the session.
+            getSessionToken();
+            final CacheManager<String, TableExportCriteria<T>> exportManager = getExportManager();
+            return exportManager.saveData(criteria);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void removeResultSet(final String resultSetKey)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            // Not directly needed but this refreshes the session.
+            getSessionToken();
+            getResultSetManager().removeResultSet(resultSetKey);
+        } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    // --------------- end export & listing
+
+    //
+    // IGenericClientService
+    //
+
+    public final List<Group> listGroups(final String databaseInstanceCode)
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final DatabaseInstanceIdentifier identifier =
+                    new DatabaseInstanceIdentifier(databaseInstanceCode);
+            final List<Group> result = new ArrayList<Group>();
+            final List<GroupPE> groups = commonServer.listGroups(sessionToken, identifier);
+            for (final GroupPE group : groups)
+            {
+                result.add(GroupTranslator.translate(group));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void registerGroup(final String groupCode, final String descriptionOrNull,
+            final String groupLeaderOrNull)
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerGroup(sessionToken, groupCode, descriptionOrNull,
+                    groupLeaderOrNull);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final List<Person> listPersons()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<Person> result = new ArrayList<Person>();
+            final List<PersonPE> persons = commonServer.listPersons(sessionToken);
+            for (final PersonPE person : persons)
+            {
+                result.add(PersonTranslator.translate(person));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void registerPerson(final String code)
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerPerson(sessionToken, code);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final List<RoleAssignment> listRoles()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<RoleAssignment> result = new ArrayList<RoleAssignment>();
+            final List<RoleAssignmentPE> roles = commonServer.listRoles(sessionToken);
+            for (final RoleAssignmentPE role : roles)
+            {
+                result.add(RoleAssignmentTranslator.translate(role));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void registerGroupRole(final RoleSetCode roleSetCode, final String group,
+            final String person)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final GroupIdentifier groupIdentifier =
+                    new GroupIdentifier(DatabaseInstanceIdentifier.HOME, group);
+            commonServer.registerGroupRole(sessionToken, RoleCodeTranslator.translate(roleSetCode),
+                    groupIdentifier, person);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void registerInstanceRole(final RoleSetCode roleSetCode, final String person)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerInstanceRole(sessionToken, RoleCodeTranslator
+                    .translate(roleSetCode), person);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void deleteGroupRole(final RoleSetCode roleSetCode, final String group,
+            final String person)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final GroupIdentifier groupIdentifier =
+                    new GroupIdentifier(DatabaseInstanceIdentifier.HOME, group);
+            commonServer.deleteGroupRole(sessionToken, RoleCodeTranslator.translate(roleSetCode),
+                    groupIdentifier, person);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+
+    }
+
+    public final void deleteInstanceRole(final RoleSetCode roleSetCode, final String person)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.deleteInstanceRole(sessionToken,
+                    RoleCodeTranslator.translate(roleSetCode), person);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+
+    }
+
+    public final List<SampleType> listSampleTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<SampleTypePE> sampleTypes = commonServer.listSampleTypes(sessionToken);
+            final List<SampleType> result = new ArrayList<SampleType>();
+            for (final SampleTypePE sampleTypePE : sampleTypes)
+            {
+                result.add(SampleTypeTranslator.translate(sampleTypePE));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    // --------- methods preparing exported content. Note: GWT does not support
+    // generic methods :(
+
+    public final String prepareExportSamples(final TableExportCriteria<Sample> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public final String prepareExportExperiments(final TableExportCriteria<Experiment> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public final String prepareExportMatchingEntities(
+            final TableExportCriteria<MatchingEntity> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportPropertyTypes(TableExportCriteria<PropertyType> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportPropertyTypeAssignments(
+            TableExportCriteria<EntityTypePropertyType<?>> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportProjects(TableExportCriteria<Project> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportVocabularies(final TableExportCriteria<Vocabulary> criteria)
+            throws UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportVocabularyTerms(TableExportCriteria<VocabularyTermWithStats> criteria)
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportMaterialTypes(final TableExportCriteria<MaterialType> criteria)
+            throws UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportExperimentTypes(final TableExportCriteria<ExperimentType> criteria)
+            throws UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public String prepareExportSampleTypes(final TableExportCriteria<SampleType> criteria)
+            throws UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    // ---------------- methods which list entities using cache
+
+    public final ResultSet<Sample> listSamples(final ListSampleCriteria listCriteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        final String sessionToken = getSessionToken();
+        return listEntities(listCriteria, new ListSamplesOriginalDataProvider(commonServer,
+                sessionToken, listCriteria));
+    }
+
+    public ResultSet<ExternalData> searchForDataSets(DataSetSearchCriteria criteria,
+            final IResultSetConfig<String, ExternalData> resultSetConfig)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        final String sessionToken = getSessionToken();
+        return listEntities(resultSetConfig, new ListDataSetsOriginalDataProvider(commonServer,
+                sessionToken, criteria, dataStoreBaseURL));
+    }
+
+    public final ResultSet<Experiment> listExperiments(final ListExperimentsCriteria listCriteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        final String sessionToken = getSessionToken();
+        return listEntities(listCriteria, new ListExperimentsOriginalDataProvider(commonServer,
+                listCriteria, sessionToken));
+    }
+
+    public ResultSet<PropertyType> listPropertyTypes(
+            DefaultResultSetConfig<String, PropertyType> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<PropertyType>()
+            {
+                public List<PropertyType> getOriginalData() throws UserFailureException
+                {
+                    return listPropertyTypes();
+                }
+            });
+    }
+
+    public final ResultSet<MatchingEntity> listMatchingEntities(
+            final SearchableEntity searchableEntityOrNull, final String queryText,
+            final IResultSetConfig<String, MatchingEntity> resultSetConfig)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        final String sessionToken = getSessionToken();
+        final ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity[] matchingEntities =
+                SearchableEntityTranslator.translate(searchableEntityOrNull);
+        return listEntities(resultSetConfig, new ListMatchingEntitiesOriginalDataProvider(
+                commonServer, sessionToken, matchingEntities, queryText));
+    }
+
+    public ResultSet<EntityTypePropertyType<?>> listPropertyTypeAssignments(
+            DefaultResultSetConfig<String, EntityTypePropertyType<?>> criteria)
+    {
+        return listEntities(criteria, new IOriginalDataProvider<EntityTypePropertyType<?>>()
+            {
+                public List<EntityTypePropertyType<?>> getOriginalData()
+                        throws UserFailureException
+                {
+                    return extractAssignments(listPropertyTypes());
+                }
+            });
+    }
+
+    private static List<EntityTypePropertyType<?>> extractAssignments(
+            List<PropertyType> listPropertyTypes)
+    {
+        List<EntityTypePropertyType<?>> result = new ArrayList<EntityTypePropertyType<?>>();
+        for (PropertyType propertyType : listPropertyTypes)
+        {
+            extractAssignments(result, propertyType);
+        }
+        return result;
+    }
+
+    private static void extractAssignments(List<EntityTypePropertyType<?>> result,
+            final PropertyType propertyType)
+    {
+        for (ExperimentTypePropertyType etpt : propertyType.getExperimentTypePropertyTypes())
+        {
+            result.add(etpt);
+        }
+        for (SampleTypePropertyType etpt : propertyType.getSampleTypePropertyTypes())
+        {
+            result.add(etpt);
+        }
+        for (MaterialTypePropertyType etpt : propertyType.getMaterialTypePropertyTypes())
+        {
+            result.add(etpt);
+        }
+    }
+
+    public ResultSet<Project> listProjects(DefaultResultSetConfig<String, Project> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<Project>()
+            {
+                public List<Project> getOriginalData() throws UserFailureException
+                {
+                    return listProjects();
+                }
+            });
+    }
+
+    private List<Project> listProjects()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<ProjectPE> projects = commonServer.listProjects(sessionToken);
+            return ProjectTranslator.translate(projects);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public ResultSet<Vocabulary> listVocabularies(final boolean withTerms,
+            final boolean excludeInternal, DefaultResultSetConfig<String, Vocabulary> criteria)
+            throws UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<Vocabulary>()
+            {
+                public List<Vocabulary> getOriginalData() throws UserFailureException
+                {
+                    return listVocabularies(withTerms, excludeInternal);
+                }
+            });
+    }
+
+    private List<Vocabulary> listVocabularies(final boolean withTerms, boolean excludeInternal)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<VocabularyPE> vocabularies =
+                    commonServer.listVocabularies(sessionToken, withTerms, excludeInternal);
+            return BeanUtils.createBeanList(Vocabulary.class, vocabularies, DtoConverters
+                    .getVocabularyConverter());
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public ResultSet<VocabularyTermWithStats> listVocabularyTerms(final Vocabulary vocabulary,
+            DefaultResultSetConfig<String, VocabularyTermWithStats> criteria)
+    {
+        return listEntities(criteria, new IOriginalDataProvider<VocabularyTermWithStats>()
+            {
+                public List<VocabularyTermWithStats> getOriginalData() throws UserFailureException
+                {
+                    List<ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats> terms =
+                            commonServer.listVocabularyTerms(getSessionToken(), vocabulary);
+                    return VocabularyTermTranslator.translate(terms);
+                }
+            });
+    }
+
+    public ResultSet<? extends EntityType> listMaterialTypes(
+            DefaultResultSetConfig<String, MaterialType> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<MaterialType>()
+            {
+                public List<MaterialType> getOriginalData() throws UserFailureException
+                {
+                    return listMaterialTypes();
+                }
+            });
+    }
+
+    public ResultSet<? extends EntityType> listSampleTypes(
+            DefaultResultSetConfig<String, SampleType> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<SampleType>()
+            {
+                public List<SampleType> getOriginalData() throws UserFailureException
+                {
+                    return listSampleTypes();
+                }
+            });
+    }
+
+    public ResultSet<? extends EntityType> listExperimentTypes(
+            DefaultResultSetConfig<String, ExperimentType> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<ExperimentType>()
+            {
+                public List<ExperimentType> getOriginalData() throws UserFailureException
+                {
+                    return listExperimentTypes();
+                }
+            });
+    }
+
+    public ResultSet<ExternalData> listSampleDataSets(final String sampleIdentifier,
+            DefaultResultSetConfig<String, ExternalData> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<ExternalData>()
+            {
+                public List<ExternalData> getOriginalData() throws UserFailureException
+                {
+                    final String sessionToken = getSessionToken();
+                    final SampleIdentifier identifier =
+                            SampleIdentifierFactory.parse(sampleIdentifier);
+                    final List<ExternalDataPE> externalData =
+                            commonServer.listExternalData(sessionToken, identifier);
+                    return ExternalDataTranslator.translate(externalData, dataStoreBaseURL);
+                }
+            });
+    }
+
+    public ResultSet<ExternalData> listExperimentDataSets(final String experimentIdentifier,
+            DefaultResultSetConfig<String, ExternalData> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return listEntities(criteria, new IOriginalDataProvider<ExternalData>()
+            {
+
+                public List<ExternalData> getOriginalData() throws UserFailureException
+                {
+                    final String sessionToken = getSessionToken();
+                    final ExperimentIdentifier identifier =
+                            new ExperimentIdentifierFactory(experimentIdentifier)
+                                    .createIdentifier();
+                    final List<ExternalDataPE> externalData =
+                            commonServer.listExternalData(sessionToken, identifier);
+                    return ExternalDataTranslator.translate(externalData, dataStoreBaseURL);
+                }
+
+            });
+    }
+
+    // ---------------- end list using cache ----------
+
+    public final List<SearchableEntity> listSearchableEntities()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            // Not directly needed but this refreshes the session.
+            getSessionToken();
+            final List<SearchableEntity> searchableEntities =
+                    BeanUtils.createBeanList(SearchableEntity.class, Arrays
+                            .asList(ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity
+                                    .values()));
+            Collections.sort(searchableEntities);
+            return searchableEntities;
+        } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public List<ExperimentType> listExperimentTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<ExperimentType> result = new ArrayList<ExperimentType>();
+            final List<ExperimentTypePE> experiments =
+                    commonServer.listExperimentTypes(sessionToken);
+            for (final ExperimentTypePE expType : experiments)
+            {
+                result.add(ExperimentTranslator.translate(expType));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    private List<PropertyType> listPropertyTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<PropertyTypePE> propertyTypes = commonServer.listPropertyTypes(sessionToken);
+            return PropertyTypeTranslator.translate(propertyTypes);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final List<DataType> listDataTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<DataTypePE> dataTypes = commonServer.listDataTypes(sessionToken);
+            return BeanUtils.createBeanList(DataType.class, dataTypes, DtoConverters
+                    .getDataTypeConverter());
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public String assignPropertyType(final EntityKind entityKind, final String propertyTypeCode,
+            final String entityTypeCode, final boolean isMandatory, final String defaultValue)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            return commonServer.assignPropertyType(sessionToken, DtoConverters
+                    .convertEntityKind(entityKind), propertyTypeCode, entityTypeCode, isMandatory,
+                    defaultValue);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void registerPropertyType(final PropertyType propertyType)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        assert propertyType != null : "Unspecified property type.";
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerPropertyType(sessionToken, propertyType);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public final void registerVocabulary(final Vocabulary vocabulary)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        assert vocabulary != null : "Unspecified vocabulary.";
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerVocabulary(sessionToken, vocabulary);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public void addVocabularyTerms(String vocabularyCode, List<String> vocabularyTerms)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        assert vocabularyCode != null : "Unspecified vocabulary code.";
+
+        if (vocabularyTerms != null && vocabularyTerms.isEmpty() == false)
+        {
+            try
+            {
+                final String sessionToken = getSessionToken();
+                commonServer.addVocabularyTerms(sessionToken, vocabularyCode, vocabularyTerms);
+            } catch (final UserFailureException e)
+            {
+                throw UserFailureExceptionTranslator.translate(e);
+            }
+        }
+    }
+
+    public void registerProject(Project project)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        assert project != null : "Unspecified project.";
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final ProjectIdentifier projectIdentifier =
+                    new ProjectIdentifierFactory(project.getIdentifier()).createIdentifier();
+            Person leader = project.getProjectLeader();
+            final String leaderId = leader == null ? null : project.getProjectLeader().getUserId();
+            commonServer.registerProject(sessionToken, projectIdentifier, project.getDescription(),
+                    leaderId);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public String prepareExportDataSetSearchHits(TableExportCriteria<ExternalData> exportCriteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(exportCriteria);
+    }
+
+    public List<MaterialType> listMaterialTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<MaterialType> result = new ArrayList<MaterialType>();
+            final List<MaterialTypePE> projects = commonServer.listMaterialTypes(sessionToken);
+            for (final MaterialTypePE expType : projects)
+            {
+                result.add(MaterialTypeTranslator.translate(expType));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public List<DataSetType> listDataSetTypes()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<DataSetType> result = new ArrayList<DataSetType>();
+            final List<DataSetTypePE> types = commonServer.listDataSetTypes(sessionToken);
+            for (final DataSetTypePE type : types)
+            {
+                result.add(DataSetTypeTranslator.translate(type));
+            }
+            return result;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public ResultSet<Material> listMaterials(ListMaterialCriteria criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        final String sessionToken = getSessionToken();
+        return listEntities(criteria, new ListMaterialOriginalDataProvider(commonServer,
+                sessionToken, criteria));
+    }
+
+    public String prepareExportMaterials(TableExportCriteria<Material> criteria)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return prepareExportEntities(criteria);
+    }
+
+    public void registerMaterialType(MaterialType entityType)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerMaterialType(sessionToken, entityType);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public void registerExperimentType(ExperimentType entityType)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerExperimentType(sessionToken, entityType);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public void registerSampleType(SampleType entityType)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerSampleType(sessionToken, entityType);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    private final static AttachmentPE createAttachment(String fileName, final byte[] content)
+    {
+        final AttachmentPE attachment = new AttachmentPE();
+        attachment.setFileName(fileName);
+        final AttachmentContentPE attachmentContent = new AttachmentContentPE();
+        attachmentContent.setValue(content);
+        attachment.setAttachmentContent(attachmentContent);
+        return attachment;
+    }
+
+    public void updateExperiment(String sessionKey, String experimentIdentifier,
+            List<ExperimentProperty> properties, String newProjectIdentifier, Date version)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+
+        UploadedFilesBean uploadedFiles = null;
+        HttpSession session = null;
+        try
+        {
+            final String sessionToken = getSessionToken();
+            session = getHttpSession();
+            uploadedFiles = (UploadedFilesBean) session.getAttribute(sessionKey);
+            List<AttachmentPE> attachments = new ArrayList<AttachmentPE>();
+            if (uploadedFiles != null)
+            {
+                for (final IUncheckedMultipartFile multipartFile : uploadedFiles.iterable())
+                {
+                    String fileName = multipartFile.getOriginalFilename();
+                    byte[] content = multipartFile.getBytes();
+                    attachments.add(createAttachment(fileName, content));
+                }
+            }
+            final ExperimentIdentifier identifier =
+                    new ExperimentIdentifierFactory(experimentIdentifier).createIdentifier();
+            final ProjectIdentifier project =
+                    new ProjectIdentifierFactory(newProjectIdentifier).createIdentifier();
+            commonServer.editExperiment(sessionToken, identifier, properties, attachments, project,
+                    version);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        } finally
+        {
+            if (uploadedFiles != null)
+            {
+                uploadedFiles.deleteTransferredFiles();
+            }
+            if (session != null)
+            {
+                session.removeAttribute(sessionKey);
+            }
+        }
+
+    }
 
     public void uploadDataSets(List<String> dataSetCodes, String cifexURL, String password)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
@@ -984,37 +1098,45 @@ public final class CommonClientService extends AbstractClientService implements
             throw UserFailureExceptionTranslator.translate(e);
         }
     }
-    
-	public void deleteDataSets(List<String> dataSetCodes, String reason)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			commonServer.deleteDataSets(sessionToken, dataSetCodes, reason);
-		} catch (final UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-	}
-	
-	public void updateSample(
-			String sampleIdentifier,
-			List<SampleProperty> properties,
-			ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentIdentifier experimentIdentifierOrNull,
-			Date version)
-			throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException {
-		try {
-			final String sessionToken = getSessionToken();
-			final SampleIdentifier identifier = new SampleIdentifierFactory(
-					sampleIdentifier).createIdentifier();
-			ExperimentIdentifier convExperimentIdentifierOrNull = null;
-			if (experimentIdentifierOrNull != null) {
-				convExperimentIdentifierOrNull = BeanUtils.createBean(
-						ExperimentIdentifier.class, experimentIdentifierOrNull);
-			}
-			commonServer.editSample(sessionToken, identifier, properties,
-					convExperimentIdentifierOrNull, version);
-		} catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e) {
-			throw UserFailureExceptionTranslator.translate(e);
-		}
-
-	}
+
+    public void deleteDataSets(List<String> dataSetCodes, String reason)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.deleteDataSets(sessionToken, dataSetCodes, reason);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public void updateSample(
+            String sampleIdentifier,
+            List<SampleProperty> properties,
+            ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentIdentifier experimentIdentifierOrNull,
+            Date version)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final SampleIdentifier identifier =
+                    new SampleIdentifierFactory(sampleIdentifier).createIdentifier();
+            ExperimentIdentifier convExperimentIdentifierOrNull = null;
+            if (experimentIdentifierOrNull != null)
+            {
+                convExperimentIdentifierOrNull =
+                        BeanUtils
+                                .createBean(ExperimentIdentifier.class, experimentIdentifierOrNull);
+            }
+            commonServer.editSample(sessionToken, identifier, properties,
+                    convExperimentIdentifierOrNull, version);
+        } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+
+    }
 }
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 ed64bb70eba0da0b141a12d442b26bf9535b93a1..5cba4c15b2ae3dc47fe99977305b06f4647bab65 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
@@ -100,473 +100,495 @@ import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
  */
 public final class CommonServer extends AbstractServer<ICommonServer> implements ICommonServer
 {
-	private final IAuthenticationService authenticationService;
-
-	private final ICommonBusinessObjectFactory businessObjectFactory;
-
-	private final DataStoreServerSessionManager dssSessionManager;
-
-	public CommonServer(final IAuthenticationService authenticationService,
-			final ISessionManager<Session> sessionManager,
-			DataStoreServerSessionManager dssSessionManager,
-			final IDAOFactory daoFactory,
-			final ICommonBusinessObjectFactory businessObjectFactory) {
-		super(sessionManager, daoFactory);
-		this.authenticationService = authenticationService;
-		this.dssSessionManager = dssSessionManager;
-		this.businessObjectFactory = businessObjectFactory;
-	}
-
-	ICommonBusinessObjectFactory getBusinessObjectFactory() {
-		return businessObjectFactory;
-	}
-
-	// Call this when session object is not needed but you want just to
-	// refresh/check the session.
-	private void checkSession(final String sessionToken) {
-		getSessionManager().getSession(sessionToken);
-	}
-
-	private static UserFailureException createUserFailureException(
-			final DataAccessException ex) {
-		return new UserFailureException(ex.getMostSpecificCause().getMessage(),
-				ex);
-	}
-
-	//
-	// AbstractServerWithLogger
-	//
-
-	@Override
-	protected final Class<ICommonServer> getProxyInterface() {
-		return ICommonServer.class;
-	}
-
-	//
-	// IInvocationLoggerFactory
-	//
-
-	/**
-	 * Creates a logger used to log invocations of objects of this class.
-	 */
-	public final ICommonServer createLogger(final boolean invocationSuccessful) {
-		return new CommonServerLogger(getSessionManager(), invocationSuccessful);
-	}
-
-	//
-	// IGenericServer
-	//
-
-	public final List<GroupPE> listGroups(final String sessionToken,
-			final DatabaseInstanceIdentifier identifier) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final DatabaseInstancePE databaseInstance = GroupIdentifierHelper
-				.getDatabaseInstance(identifier, getDAOFactory());
-		final List<GroupPE> groups = getDAOFactory().getGroupDAO().listGroups(
-				databaseInstance);
-		final Long homeGroupID = session.tryGetHomeGroupId();
-		for (final GroupPE group : groups) {
-			group.setHome(homeGroupID != null
-					&& homeGroupID.equals(group.getId()));
-		}
-		Collections.sort(groups);
-		return groups;
-	}
-
-	public final void registerGroup(final String sessionToken,
-			final String groupCode, final String descriptionOrNull,
-			final String groupLeaderOrNull) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IGroupBO groupBO = businessObjectFactory.createGroupBO(session);
-		groupBO.define(groupCode, descriptionOrNull, groupLeaderOrNull);
-		groupBO.save();
-	}
-
-	public final void registerPerson(final String sessionToken,
-			final String userID) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final PersonPE person = getDAOFactory().getPersonDAO()
-				.tryFindPersonByUserId(userID);
-		if (person != null) {
-			throw UserFailureException.fromTemplate(
-					"Person '%s' already exists.", userID);
-		}
-		final String applicationToken = authenticationService
-				.authenticateApplication();
-		if (applicationToken == null) {
-			throw new EnvironmentFailureException(
-					"Authentication service cannot be accessed.");
-		}
-		try {
-			final Principal principal = authenticationService.getPrincipal(
-					applicationToken, userID);
-			createPerson(principal, session.tryGetPerson());
-		} catch (final IllegalArgumentException e) {
-			throw new UserFailureException("Person '" + userID
-					+ "' unknown by the authentication service.");
-		}
-	}
-
-	public final List<RoleAssignmentPE> listRoles(final String sessionToken) {
-		checkSession(sessionToken);
-		return getDAOFactory().getRoleAssignmentDAO().listRoleAssignments();
-	}
-
-	public final void registerGroupRole(final String sessionToken,
-			final RoleCode roleCode, final GroupIdentifier groupIdentifier,
-			final String person) {
-		final Session session = getSessionManager().getSession(sessionToken);
-
-		final NewRoleAssignment newRoleAssignment = new NewRoleAssignment();
-		newRoleAssignment.setUserId(person);
-		newRoleAssignment.setGroupIdentifier(groupIdentifier);
-		newRoleAssignment.setRole(roleCode);
-
-		final IRoleAssignmentTable table = businessObjectFactory
-				.createRoleAssignmentTable(session);
-		table.add(newRoleAssignment);
-		table.save();
-
-	}
-
-	public final void registerInstanceRole(final String sessionToken,
-			final RoleCode roleCode, final String person) {
-		final Session session = getSessionManager().getSession(sessionToken);
-
-		final NewRoleAssignment newRoleAssignment = new NewRoleAssignment();
-		newRoleAssignment.setUserId(person);
-		newRoleAssignment
-				.setDatabaseInstanceIdentifier(new DatabaseInstanceIdentifier(
-						DatabaseInstanceIdentifier.HOME));
-		newRoleAssignment.setRole(roleCode);
-
-		final IRoleAssignmentTable table = businessObjectFactory
-				.createRoleAssignmentTable(session);
-		table.add(newRoleAssignment);
-		table.save();
-
-	}
-
-	public final void deleteGroupRole(final String sessionToken,
-			final RoleCode roleCode, final GroupIdentifier groupIdentifier,
-			final String person) {
-		final Session session = getSessionManager().getSession(sessionToken);
-
-		final RoleAssignmentPE roleAssignment = getDAOFactory()
-				.getRoleAssignmentDAO().tryFindGroupRoleAssignment(roleCode,
-						groupIdentifier.getGroupCode(), person);
-		if (roleAssignment == null) {
-			throw new UserFailureException("Given group role does not exist.");
-		}
-		final PersonPE personPE = session.tryGetPerson();
-		if (roleAssignment.getPerson().equals(personPE)
-				&& roleAssignment.getRole().equals(RoleCode.ADMIN)) {
-			boolean isInstanceAdmin = false;
-			for (final RoleAssignmentPE roleAssigment : personPE
-					.getRoleAssignments()) {
-				if (roleAssigment.getDatabaseInstance() != null
-						&& roleAssigment.getRole().equals(RoleCode.ADMIN)) {
-					isInstanceAdmin = true;
-				}
-			}
-			if (isInstanceAdmin == false) {
-				throw new UserFailureException(
-						"For safety reason you cannot give away your own group admin power. "
-								+ "Ask instance admin to do that for you.");
-			}
-		}
-		getDAOFactory().getRoleAssignmentDAO().deleteRoleAssignment(
-				roleAssignment);
-	}
-
-	public final void deleteInstanceRole(final String sessionToken,
-			final RoleCode roleCode, final String person) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IRoleAssignmentDAO roleAssignmentDAO = getDAOFactory()
-				.getRoleAssignmentDAO();
-		final RoleAssignmentPE roleAssignment = roleAssignmentDAO
-				.tryFindInstanceRoleAssignment(roleCode, person);
-		if (roleAssignment == null) {
-			throw new UserFailureException(
-					"Given database instance role does not exist.");
-		}
-		if (roleAssignment.getPerson().equals(session.tryGetPerson())
-				&& roleAssignment.getRole().equals(RoleCode.ADMIN)
-				&& roleAssignment.getDatabaseInstance() != null) {
-			throw new UserFailureException(
-					"For safety reason you cannot give away your own omnipotence. "
-							+ "Ask another instance admin to do that for you.");
-		}
-		roleAssignmentDAO.deleteRoleAssignment(roleAssignment);
-	}
-
-	public final List<PersonPE> listPersons(final String sessionToken) {
-		checkSession(sessionToken);
-		final List<PersonPE> persons = getDAOFactory().getPersonDAO()
-				.listPersons();
-		Collections.sort(persons);
-		return persons;
-	}
-
-	public final List<ProjectPE> listProjects(final String sessionToken) {
-		checkSession(sessionToken);
-		final List<ProjectPE> projects = getDAOFactory().getProjectDAO()
-				.listProjects();
-		Collections.sort(projects);
-		return projects;
-	}
-
-	public final List<SampleTypePE> listSampleTypes(final String sessionToken) {
-		checkSession(sessionToken);
-		final List<SampleTypePE> sampleTypes = getDAOFactory()
-				.getSampleTypeDAO().listSampleTypes();
-		Collections.sort(sampleTypes);
-		return sampleTypes;
-	}
-
-	public final List<SamplePE> listSamples(final String sessionToken,
-			final ListSampleCriteriaDTO criteria) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final ISampleTable sampleTable = businessObjectFactory
-				.createSampleTable(session);
-		sampleTable.loadSamplesByCriteria(criteria);
-		sampleTable.enrichWithValidProcedure();
-		sampleTable.enrichWithProperties();
-		final List<SamplePE> samples = sampleTable.getSamples();
-		Collections.sort(samples);
-		return samples;
-	}
-
-	public final List<ExternalDataPE> listExternalData(
-			final String sessionToken, final SampleIdentifier identifier) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IExternalDataTable externalDataTable = businessObjectFactory
-				.createExternalDataTable(session);
-		externalDataTable.loadBySampleIdentifier(identifier);
-		return getSortedExternalDataFrom(externalDataTable);
-	}
-
-	public List<ExternalDataPE> listExternalData(String sessionToken,
-			ExperimentIdentifier identifier) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IExternalDataTable externalDataTable = businessObjectFactory
-				.createExternalDataTable(session);
-		externalDataTable.loadByExperimentIdentifier(identifier);
-		return getSortedExternalDataFrom(externalDataTable);
-	}
-
-	private List<ExternalDataPE> getSortedExternalDataFrom(
-			final IExternalDataTable externalDataTable) {
-		final List<ExternalDataPE> externalData = externalDataTable
-				.getExternalData();
-		Collections.sort(externalData);
-		return externalData;
-	}
-
-	public final List<PropertyTypePE> listPropertyTypes(
-			final String sessionToken) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IPropertyTypeTable propertyTypeTable = businessObjectFactory
-				.createPropertyTypeTable(session);
-		propertyTypeTable.load();
-		propertyTypeTable.enrichWithRelations();
-		final List<PropertyTypePE> propertyTypes = propertyTypeTable
-				.getPropertyTypes();
-		Collections.sort(propertyTypes);
-		return propertyTypes;
-	}
-
-	public final List<SearchHit> listMatchingEntities(
-			final String sessionToken,
-			final SearchableEntity[] searchableEntities, final String queryText) {
-		checkSession(sessionToken);
-		final List<SearchHit> list = new ArrayList<SearchHit>();
-		try {
-			for (final SearchableEntity searchableEntity : searchableEntities) {
-				final List<SearchHit> entities = getDAOFactory()
-						.getHibernateSearchDAO().searchEntitiesByTerm(
-								searchableEntity.getMatchingEntityClass(),
-								queryText);
-				list.addAll(entities);
-			}
-		} catch (final DataAccessException ex) {
-			throw createUserFailureException(ex);
-		}
-		return list;
-	}
-
-	public final List<ExperimentPE> listExperiments(final String sessionToken,
-			final ExperimentTypePE experimentType,
-			final ProjectIdentifier projectIdentifier) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IExperimentTable experimentTable = businessObjectFactory
-				.createExperimentTable(session);
-		experimentTable.load(experimentType.getCode(), projectIdentifier);
-		experimentTable.enrichWithProperties();
-		final List<ExperimentPE> experiments = experimentTable.getExperiments();
-		Collections.sort(experiments);
-		return experiments;
-	}
-
-	public final List<ExperimentTypePE> listExperimentTypes(
-			final String sessionToken) {
-		return listEntityTypes(sessionToken, EntityKind.EXPERIMENT);
-	}
-
-	public List<MaterialTypePE> listMaterialTypes(String sessionToken) {
-		return listEntityTypes(sessionToken, EntityKind.MATERIAL);
-	}
-
-	private <T extends EntityTypePE> List<T> listEntityTypes(
-			String sessionToken, EntityKind entityKind) {
-		checkSession(sessionToken);
-		final List<T> types = getDAOFactory().getEntityTypeDAO(entityKind)
-				.listEntityTypes();
-		Collections.sort(types);
-		return types;
-	}
-
-	public final List<DataTypePE> listDataTypes(final String sessionToken) {
-		assert sessionToken != null : "Unspecified session token";
-		checkSession(sessionToken);
-		final List<DataTypePE> dataTypes = getDAOFactory().getPropertyTypeDAO()
-				.listDataTypes();
-		Collections.sort(dataTypes);
-		return dataTypes;
-	}
-
-	public final List<VocabularyPE> listVocabularies(final String sessionToken,
-			final boolean withTerms, boolean excludeInternal) {
-		assert sessionToken != null : "Unspecified session token";
-		checkSession(sessionToken);
-		final List<VocabularyPE> vocabularies = getDAOFactory()
-				.getVocabularyDAO().listVocabularies(excludeInternal);
-		if (withTerms) {
-			for (final VocabularyPE vocabularyPE : vocabularies) {
-				enrichWithTerms(vocabularyPE);
-			}
-		}
-		Collections.sort(vocabularies);
-		return vocabularies;
-	}
-
-	private void enrichWithTerms(final VocabularyPE vocabularyPE) {
-		HibernateUtils.initialize(vocabularyPE.getTerms());
-	}
-
-	public String assignPropertyType(final String sessionToken,
-			final EntityKind entityKind, final String propertyTypeCode,
-			final String entityTypeCode, final boolean isMandatory,
-			final String defaultValue) {
-		assert sessionToken != null : "Unspecified session token";
-		Session session = getSessionManager().getSession(sessionToken);
-
-		IEntityTypePropertyTypeBO etptBO = businessObjectFactory
-				.createEntityTypePropertyTypeBO(session, entityKind);
-		etptBO.createAssignment(propertyTypeCode, entityTypeCode, isMandatory,
-				defaultValue);
-		return String.format(
-				"%s property type '%s' successfully assigned to %s type '%s'",
-				isMandatory ? "Mandatory" : "Optional", propertyTypeCode,
-				entityKind.getLabel(), entityTypeCode);
-
-	}
-
-	public final void registerPropertyType(final String sessionToken,
-			final PropertyType propertyType) {
-		assert sessionToken != null : "Unspecified session token";
-		assert propertyType != null : "Unspecified property type";
-
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IPropertyTypeBO propertyTypeBO = businessObjectFactory
-				.createPropertyTypeBO(session);
-		propertyTypeBO.define(propertyType);
-		propertyTypeBO.save();
-	}
-
-	public final void registerVocabulary(final String sessionToken,
-			final Vocabulary vocabulary) {
-		assert sessionToken != null : "Unspecified session token";
-		assert vocabulary != null : "Unspecified vocabulary";
-
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IVocabularyBO vocabularyBO = businessObjectFactory
-				.createVocabularyBO(session);
-		vocabularyBO.define(vocabulary);
-		vocabularyBO.save();
-	}
-
-	public void registerProject(String sessionToken,
-			ProjectIdentifier projectIdentifier, String description,
-			String leaderId) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IProjectBO projectBO = businessObjectFactory
-				.createProjectBO(session);
-		projectBO.define(projectIdentifier, description, leaderId);
-		projectBO.save();
-
-	}
-
-	public List<ExternalDataPE> searchForDataSets(String sessionToken,
-			DataSetSearchCriteria criteria) {
-		checkSession(sessionToken);
-		try {
-			IHibernateSearchDAO searchDAO = getDAOFactory()
-					.getHibernateSearchDAO();
-			return searchDAO.searchForDataSets(criteria);
-		} catch (final DataAccessException ex) {
-			throw createUserFailureException(ex);
-		}
-	}
-
-	public List<MaterialPE> listMaterials(String sessionToken,
-			MaterialTypePE materialType) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IMaterialTable materialTable = businessObjectFactory
-				.createMaterialTable(session);
-		materialTable.load(materialType.getCode());
-		final List<MaterialPE> materials = materialTable.getMaterials();
-		Collections.sort(materials);
-		return materials;
-	}
-
-	public void registerSampleType(String sessionToken, SampleType entityType) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		try {
-			IEntityTypeBO entityTypeBO = businessObjectFactory
-					.createEntityTypeBO(session);
-			entityTypeBO.define(entityType);
-			entityTypeBO.save();
-		} catch (final DataAccessException ex) {
-			throw createUserFailureException(ex);
-		}
-	}
-
-	public void registerMaterialType(String sessionToken,
-			MaterialType entityType) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		try {
-			IEntityTypeBO entityTypeBO = businessObjectFactory
-					.createEntityTypeBO(session);
-			entityTypeBO.define(entityType);
-			entityTypeBO.save();
-		} catch (final DataAccessException ex) {
-			throw createUserFailureException(ex);
-		}
-	}
-
-	public void registerExperimentType(String sessionToken,
-			ExperimentType entityType) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		try {
-			IEntityTypeBO entityTypeBO = businessObjectFactory
-					.createEntityTypeBO(session);
-			entityTypeBO.define(entityType);
-			entityTypeBO.save();
-		} catch (final DataAccessException ex) {
-			throw createUserFailureException(ex);
-		}
-	}
+    private final IAuthenticationService authenticationService;
+
+    private final ICommonBusinessObjectFactory businessObjectFactory;
+
+    private final DataStoreServerSessionManager dssSessionManager;
+
+    public CommonServer(final IAuthenticationService authenticationService,
+            final ISessionManager<Session> sessionManager,
+            DataStoreServerSessionManager dssSessionManager, final IDAOFactory daoFactory,
+            final ICommonBusinessObjectFactory businessObjectFactory)
+    {
+        super(sessionManager, daoFactory);
+        this.authenticationService = authenticationService;
+        this.dssSessionManager = dssSessionManager;
+        this.businessObjectFactory = businessObjectFactory;
+    }
+
+    ICommonBusinessObjectFactory getBusinessObjectFactory()
+    {
+        return businessObjectFactory;
+    }
+
+    // Call this when session object is not needed but you want just to
+    // refresh/check the session.
+    private void checkSession(final String sessionToken)
+    {
+        getSessionManager().getSession(sessionToken);
+    }
+
+    private static UserFailureException createUserFailureException(final DataAccessException ex)
+    {
+        return new UserFailureException(ex.getMostSpecificCause().getMessage(), ex);
+    }
+
+    //
+    // AbstractServerWithLogger
+    //
+
+    @Override
+    protected final Class<ICommonServer> getProxyInterface()
+    {
+        return ICommonServer.class;
+    }
+
+    //
+    // IInvocationLoggerFactory
+    //
+
+    /**
+     * Creates a logger used to log invocations of objects of this class.
+     */
+    public final ICommonServer createLogger(final boolean invocationSuccessful)
+    {
+        return new CommonServerLogger(getSessionManager(), invocationSuccessful);
+    }
+
+    //
+    // IGenericServer
+    //
+
+    public final List<GroupPE> listGroups(final String sessionToken,
+            final DatabaseInstanceIdentifier identifier)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final DatabaseInstancePE databaseInstance =
+                GroupIdentifierHelper.getDatabaseInstance(identifier, getDAOFactory());
+        final List<GroupPE> groups = getDAOFactory().getGroupDAO().listGroups(databaseInstance);
+        final Long homeGroupID = session.tryGetHomeGroupId();
+        for (final GroupPE group : groups)
+        {
+            group.setHome(homeGroupID != null && homeGroupID.equals(group.getId()));
+        }
+        Collections.sort(groups);
+        return groups;
+    }
+
+    public final void registerGroup(final String sessionToken, final String groupCode,
+            final String descriptionOrNull, final String groupLeaderOrNull)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IGroupBO groupBO = businessObjectFactory.createGroupBO(session);
+        groupBO.define(groupCode, descriptionOrNull, groupLeaderOrNull);
+        groupBO.save();
+    }
+
+    public final void registerPerson(final String sessionToken, final String userID)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final PersonPE person = getDAOFactory().getPersonDAO().tryFindPersonByUserId(userID);
+        if (person != null)
+        {
+            throw UserFailureException.fromTemplate("Person '%s' already exists.", userID);
+        }
+        final String applicationToken = authenticationService.authenticateApplication();
+        if (applicationToken == null)
+        {
+            throw new EnvironmentFailureException("Authentication service cannot be accessed.");
+        }
+        try
+        {
+            final Principal principal =
+                    authenticationService.getPrincipal(applicationToken, userID);
+            createPerson(principal, session.tryGetPerson());
+        } catch (final IllegalArgumentException e)
+        {
+            throw new UserFailureException("Person '" + userID
+                    + "' unknown by the authentication service.");
+        }
+    }
+
+    public final List<RoleAssignmentPE> listRoles(final String sessionToken)
+    {
+        checkSession(sessionToken);
+        return getDAOFactory().getRoleAssignmentDAO().listRoleAssignments();
+    }
+
+    public final void registerGroupRole(final String sessionToken, final RoleCode roleCode,
+            final GroupIdentifier groupIdentifier, final String person)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+
+        final NewRoleAssignment newRoleAssignment = new NewRoleAssignment();
+        newRoleAssignment.setUserId(person);
+        newRoleAssignment.setGroupIdentifier(groupIdentifier);
+        newRoleAssignment.setRole(roleCode);
+
+        final IRoleAssignmentTable table = businessObjectFactory.createRoleAssignmentTable(session);
+        table.add(newRoleAssignment);
+        table.save();
+
+    }
+
+    public final void registerInstanceRole(final String sessionToken, final RoleCode roleCode,
+            final String person)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+
+        final NewRoleAssignment newRoleAssignment = new NewRoleAssignment();
+        newRoleAssignment.setUserId(person);
+        newRoleAssignment.setDatabaseInstanceIdentifier(new DatabaseInstanceIdentifier(
+                DatabaseInstanceIdentifier.HOME));
+        newRoleAssignment.setRole(roleCode);
+
+        final IRoleAssignmentTable table = businessObjectFactory.createRoleAssignmentTable(session);
+        table.add(newRoleAssignment);
+        table.save();
+
+    }
+
+    public final void deleteGroupRole(final String sessionToken, final RoleCode roleCode,
+            final GroupIdentifier groupIdentifier, final String person)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+
+        final RoleAssignmentPE roleAssignment =
+                getDAOFactory().getRoleAssignmentDAO().tryFindGroupRoleAssignment(roleCode,
+                        groupIdentifier.getGroupCode(), person);
+        if (roleAssignment == null)
+        {
+            throw new UserFailureException("Given group role does not exist.");
+        }
+        final PersonPE personPE = session.tryGetPerson();
+        if (roleAssignment.getPerson().equals(personPE)
+                && roleAssignment.getRole().equals(RoleCode.ADMIN))
+        {
+            boolean isInstanceAdmin = false;
+            for (final RoleAssignmentPE roleAssigment : personPE.getRoleAssignments())
+            {
+                if (roleAssigment.getDatabaseInstance() != null
+                        && roleAssigment.getRole().equals(RoleCode.ADMIN))
+                {
+                    isInstanceAdmin = true;
+                }
+            }
+            if (isInstanceAdmin == false)
+            {
+                throw new UserFailureException(
+                        "For safety reason you cannot give away your own group admin power. "
+                                + "Ask instance admin to do that for you.");
+            }
+        }
+        getDAOFactory().getRoleAssignmentDAO().deleteRoleAssignment(roleAssignment);
+    }
+
+    public final void deleteInstanceRole(final String sessionToken, final RoleCode roleCode,
+            final String person)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IRoleAssignmentDAO roleAssignmentDAO = getDAOFactory().getRoleAssignmentDAO();
+        final RoleAssignmentPE roleAssignment =
+                roleAssignmentDAO.tryFindInstanceRoleAssignment(roleCode, person);
+        if (roleAssignment == null)
+        {
+            throw new UserFailureException("Given database instance role does not exist.");
+        }
+        if (roleAssignment.getPerson().equals(session.tryGetPerson())
+                && roleAssignment.getRole().equals(RoleCode.ADMIN)
+                && roleAssignment.getDatabaseInstance() != null)
+        {
+            throw new UserFailureException(
+                    "For safety reason you cannot give away your own omnipotence. "
+                            + "Ask another instance admin to do that for you.");
+        }
+        roleAssignmentDAO.deleteRoleAssignment(roleAssignment);
+    }
+
+    public final List<PersonPE> listPersons(final String sessionToken)
+    {
+        checkSession(sessionToken);
+        final List<PersonPE> persons = getDAOFactory().getPersonDAO().listPersons();
+        Collections.sort(persons);
+        return persons;
+    }
+
+    public final List<ProjectPE> listProjects(final String sessionToken)
+    {
+        checkSession(sessionToken);
+        final List<ProjectPE> projects = getDAOFactory().getProjectDAO().listProjects();
+        Collections.sort(projects);
+        return projects;
+    }
+
+    public final List<SampleTypePE> listSampleTypes(final String sessionToken)
+    {
+        checkSession(sessionToken);
+        final List<SampleTypePE> sampleTypes = getDAOFactory().getSampleTypeDAO().listSampleTypes();
+        Collections.sort(sampleTypes);
+        return sampleTypes;
+    }
+
+    public final List<SamplePE> listSamples(final String sessionToken,
+            final ListSampleCriteriaDTO criteria)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final ISampleTable sampleTable = businessObjectFactory.createSampleTable(session);
+        sampleTable.loadSamplesByCriteria(criteria);
+        sampleTable.enrichWithValidProcedure();
+        sampleTable.enrichWithProperties();
+        final List<SamplePE> samples = sampleTable.getSamples();
+        Collections.sort(samples);
+        return samples;
+    }
+
+    public final List<ExternalDataPE> listExternalData(final String sessionToken,
+            final SampleIdentifier identifier)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IExternalDataTable externalDataTable =
+                businessObjectFactory.createExternalDataTable(session);
+        externalDataTable.loadBySampleIdentifier(identifier);
+        return getSortedExternalDataFrom(externalDataTable);
+    }
+
+    public List<ExternalDataPE> listExternalData(String sessionToken,
+            ExperimentIdentifier identifier)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IExternalDataTable externalDataTable =
+                businessObjectFactory.createExternalDataTable(session);
+        externalDataTable.loadByExperimentIdentifier(identifier);
+        return getSortedExternalDataFrom(externalDataTable);
+    }
+
+    private List<ExternalDataPE> getSortedExternalDataFrom(
+            final IExternalDataTable externalDataTable)
+    {
+        final List<ExternalDataPE> externalData = externalDataTable.getExternalData();
+        Collections.sort(externalData);
+        return externalData;
+    }
+
+    public final List<PropertyTypePE> listPropertyTypes(final String sessionToken)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IPropertyTypeTable propertyTypeTable =
+                businessObjectFactory.createPropertyTypeTable(session);
+        propertyTypeTable.load();
+        propertyTypeTable.enrichWithRelations();
+        final List<PropertyTypePE> propertyTypes = propertyTypeTable.getPropertyTypes();
+        Collections.sort(propertyTypes);
+        return propertyTypes;
+    }
+
+    public final List<SearchHit> listMatchingEntities(final String sessionToken,
+            final SearchableEntity[] searchableEntities, final String queryText)
+    {
+        checkSession(sessionToken);
+        final List<SearchHit> list = new ArrayList<SearchHit>();
+        try
+        {
+            for (final SearchableEntity searchableEntity : searchableEntities)
+            {
+                final List<SearchHit> entities =
+                        getDAOFactory().getHibernateSearchDAO().searchEntitiesByTerm(
+                                searchableEntity.getMatchingEntityClass(), queryText);
+                list.addAll(entities);
+            }
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+        return list;
+    }
+
+    public final List<ExperimentPE> listExperiments(final String sessionToken,
+            final ExperimentTypePE experimentType, final ProjectIdentifier projectIdentifier)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IExperimentTable experimentTable =
+                businessObjectFactory.createExperimentTable(session);
+        experimentTable.load(experimentType.getCode(), projectIdentifier);
+        experimentTable.enrichWithProperties();
+        final List<ExperimentPE> experiments = experimentTable.getExperiments();
+        Collections.sort(experiments);
+        return experiments;
+    }
+
+    public final List<ExperimentTypePE> listExperimentTypes(final String sessionToken)
+    {
+        return listEntityTypes(sessionToken, EntityKind.EXPERIMENT);
+    }
+
+    public List<MaterialTypePE> listMaterialTypes(String sessionToken)
+    {
+        return listEntityTypes(sessionToken, EntityKind.MATERIAL);
+    }
+
+    private <T extends EntityTypePE> List<T> listEntityTypes(String sessionToken,
+            EntityKind entityKind)
+    {
+        checkSession(sessionToken);
+        final List<T> types = getDAOFactory().getEntityTypeDAO(entityKind).listEntityTypes();
+        Collections.sort(types);
+        return types;
+    }
+
+    public final List<DataTypePE> listDataTypes(final String sessionToken)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        checkSession(sessionToken);
+        final List<DataTypePE> dataTypes = getDAOFactory().getPropertyTypeDAO().listDataTypes();
+        Collections.sort(dataTypes);
+        return dataTypes;
+    }
+
+    public final List<VocabularyPE> listVocabularies(final String sessionToken,
+            final boolean withTerms, boolean excludeInternal)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        checkSession(sessionToken);
+        final List<VocabularyPE> vocabularies =
+                getDAOFactory().getVocabularyDAO().listVocabularies(excludeInternal);
+        if (withTerms)
+        {
+            for (final VocabularyPE vocabularyPE : vocabularies)
+            {
+                enrichWithTerms(vocabularyPE);
+            }
+        }
+        Collections.sort(vocabularies);
+        return vocabularies;
+    }
+
+    private void enrichWithTerms(final VocabularyPE vocabularyPE)
+    {
+        HibernateUtils.initialize(vocabularyPE.getTerms());
+    }
+
+    public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
+            final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
+            final String defaultValue)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        Session session = getSessionManager().getSession(sessionToken);
+
+        IEntityTypePropertyTypeBO etptBO =
+                businessObjectFactory.createEntityTypePropertyTypeBO(session, entityKind);
+        etptBO.createAssignment(propertyTypeCode, entityTypeCode, isMandatory, defaultValue);
+        return String.format("%s property type '%s' successfully assigned to %s type '%s'",
+                isMandatory ? "Mandatory" : "Optional", propertyTypeCode, entityKind.getLabel(),
+                entityTypeCode);
+
+    }
+
+    public final void registerPropertyType(final String sessionToken,
+            final PropertyType propertyType)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        assert propertyType != null : "Unspecified property type";
+
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IPropertyTypeBO propertyTypeBO = businessObjectFactory.createPropertyTypeBO(session);
+        propertyTypeBO.define(propertyType);
+        propertyTypeBO.save();
+    }
+
+    public final void registerVocabulary(final String sessionToken, final Vocabulary vocabulary)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        assert vocabulary != null : "Unspecified vocabulary";
+
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IVocabularyBO vocabularyBO = businessObjectFactory.createVocabularyBO(session);
+        vocabularyBO.define(vocabulary);
+        vocabularyBO.save();
+    }
+
+    public void addVocabularyTerms(String sessionToken, String vocabularyCode,
+            List<String> vocabularyTerms)
+    {
+        System.out.println(vocabularyCode+":"+vocabularyTerms);
+        
+    }
+
+    public void registerProject(String sessionToken, ProjectIdentifier projectIdentifier,
+            String description, String leaderId)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IProjectBO projectBO = businessObjectFactory.createProjectBO(session);
+        projectBO.define(projectIdentifier, description, leaderId);
+        projectBO.save();
+
+    }
+
+    public List<ExternalDataPE> searchForDataSets(String sessionToken,
+            DataSetSearchCriteria criteria)
+    {
+        checkSession(sessionToken);
+        try
+        {
+            IHibernateSearchDAO searchDAO = getDAOFactory().getHibernateSearchDAO();
+            return searchDAO.searchForDataSets(criteria);
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
+
+    public List<MaterialPE> listMaterials(String sessionToken, MaterialTypePE materialType)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IMaterialTable materialTable = businessObjectFactory.createMaterialTable(session);
+        materialTable.load(materialType.getCode());
+        final List<MaterialPE> materials = materialTable.getMaterials();
+        Collections.sort(materials);
+        return materials;
+    }
+
+    public void registerSampleType(String sessionToken, SampleType entityType)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        try
+        {
+            IEntityTypeBO entityTypeBO = businessObjectFactory.createEntityTypeBO(session);
+            entityTypeBO.define(entityType);
+            entityTypeBO.save();
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
+
+    public void registerMaterialType(String sessionToken, MaterialType entityType)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        try
+        {
+            IEntityTypeBO entityTypeBO = businessObjectFactory.createEntityTypeBO(session);
+            entityTypeBO.define(entityType);
+            entityTypeBO.save();
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
+
+    public void registerExperimentType(String sessionToken, ExperimentType entityType)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        try
+        {
+            IEntityTypeBO entityTypeBO = businessObjectFactory.createEntityTypeBO(session);
+            entityTypeBO.define(entityType);
+            entityTypeBO.save();
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
 
     public void deleteDataSets(String sessionToken, List<String> dataSetCodes, String reason)
     {
@@ -598,105 +620,105 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
             throw createUserFailureException(ex);
         }
     }
-    
-	public void editExperiment(String sessionToken,
-			ExperimentIdentifier identifier,
-			List<ExperimentProperty> properties,
-			List<AttachmentPE> attachments,
-			ProjectIdentifier newProjectIdentifier, Date version) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		if (newProjectIdentifier.equals(identifier) == false) {
-			checkExternalData(identifier, session);
-			checkSampleConsistency(identifier, newProjectIdentifier, session);
-		}
-
-		final IExperimentBO experimentBO = businessObjectFactory
-				.createExperimentBO(session);
-		experimentBO.edit(identifier, properties, attachments,
-				newProjectIdentifier, version);
-		experimentBO.save();
-	}
-
-	private void checkExternalData(ExperimentIdentifier identifier,
-			final Session session) {
-		final IExternalDataTable externalDataTable = businessObjectFactory
-				.createExternalDataTable(session);
-		externalDataTable.loadByExperimentIdentifier(identifier);
-		if (externalDataTable.getExternalData().size() > 0) {
-			throw new UserFailureException(
-					"Changing the project of experiment containing data sets is not allowed.");
-		}
-	}
-
-	private void checkSampleConsistency(ExperimentIdentifier identifier,
-			ProjectIdentifier newProjectIdentifier, final Session session) {
-		ListSampleCriteriaDTO criteria = ListSampleCriteriaDTO
-				.createExperimentIdentifier(identifier);
-		final ISampleTable sampleTable = businessObjectFactory
-				.createSampleTable(session);
-		sampleTable.loadSamplesByCriteria(criteria);
-		final List<SamplePE> samples = sampleTable.getSamples();
-		if (samples.size() > 0) {
-			checkExperimentGroupMatches(samples.get(0).getSampleIdentifier(),
-					newProjectIdentifier);
-		}
-	}
-
-	private void checkExperimentGroupMatches(SampleIdentifier sampleIdentifier,
-			ProjectIdentifier newProjectIdentifier) {
-		assert sampleIdentifier != null : "Sample identifier not specified";
-		assert newProjectIdentifier != null : "Project identifier not specified";
-		final GroupIdentifier sampleGroup = sampleIdentifier.getGroupLevel();
-		if (sampleGroup == null) {
-			throw new UserFailureException(
-					"Inconsistency detected: shared sample found in experiment.");
-		}
-		if (sampleGroup.getDatabaseInstanceCode().equals(
-				newProjectIdentifier.getDatabaseInstanceCode()) == false
-				|| sampleGroup.getGroupCode().equals(
-						newProjectIdentifier.getGroupCode()) == false) {
-			throw new UserFailureException(
-					String
-							.format(
-									"Project cannot be changed to '%s' because experiment containes samples from group '%s'.",
-									newProjectIdentifier, sampleGroup));
-		}
-	}
-
-	public void editMaterial(String sessionToken,
-			MaterialIdentifier identifier, List<MaterialProperty> properties,
-			Date version) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IMaterialBO materialBO = businessObjectFactory
-				.createMaterialBO(session);
-		materialBO.edit(identifier, properties, version);
-		materialBO.save();
-
-	}
-
-	public void editSample(String sessionToken, SampleIdentifier identifier,
-			List<SampleProperty> properties,
-			ExperimentIdentifier experimentIdentifierOrNull, Date version) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final ISampleBO sampleBO = businessObjectFactory
-				.createSampleBO(session);
-		sampleBO.edit(identifier, properties, experimentIdentifierOrNull,
-				version);
-		sampleBO.save();
-
-	}
-
-	public List<VocabularyTermWithStats> listVocabularyTerms(
-			String sessionToken, Vocabulary vocabulary) {
-		final Session session = getSessionManager().getSession(sessionToken);
-		final IVocabularyBO vocabularyBO = businessObjectFactory
-				.createVocabularyBO(session);
-		vocabularyBO.load(vocabulary);
-		return vocabularyBO.countTermsUsageStatistics();
-	}
-
-	public List<DataSetTypePE> listDataSetTypes(String sessionToken) {
-		return listEntityTypes(sessionToken, EntityKind.DATA_SET);
-	}
+
+    public void editExperiment(String sessionToken, ExperimentIdentifier identifier,
+            List<ExperimentProperty> properties, List<AttachmentPE> attachments,
+            ProjectIdentifier newProjectIdentifier, Date version)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        if (newProjectIdentifier.equals(identifier) == false)
+        {
+            checkExternalData(identifier, session);
+            checkSampleConsistency(identifier, newProjectIdentifier, session);
+        }
+
+        final IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
+        experimentBO.edit(identifier, properties, attachments, newProjectIdentifier, version);
+        experimentBO.save();
+    }
+
+    private void checkExternalData(ExperimentIdentifier identifier, final Session session)
+    {
+        final IExternalDataTable externalDataTable =
+                businessObjectFactory.createExternalDataTable(session);
+        externalDataTable.loadByExperimentIdentifier(identifier);
+        if (externalDataTable.getExternalData().size() > 0)
+        {
+            throw new UserFailureException(
+                    "Changing the project of experiment containing data sets is not allowed.");
+        }
+    }
+
+    private void checkSampleConsistency(ExperimentIdentifier identifier,
+            ProjectIdentifier newProjectIdentifier, final Session session)
+    {
+        ListSampleCriteriaDTO criteria =
+                ListSampleCriteriaDTO.createExperimentIdentifier(identifier);
+        final ISampleTable sampleTable = businessObjectFactory.createSampleTable(session);
+        sampleTable.loadSamplesByCriteria(criteria);
+        final List<SamplePE> samples = sampleTable.getSamples();
+        if (samples.size() > 0)
+        {
+            checkExperimentGroupMatches(samples.get(0).getSampleIdentifier(), newProjectIdentifier);
+        }
+    }
+
+    private void checkExperimentGroupMatches(SampleIdentifier sampleIdentifier,
+            ProjectIdentifier newProjectIdentifier)
+    {
+        assert sampleIdentifier != null : "Sample identifier not specified";
+        assert newProjectIdentifier != null : "Project identifier not specified";
+        final GroupIdentifier sampleGroup = sampleIdentifier.getGroupLevel();
+        if (sampleGroup == null)
+        {
+            throw new UserFailureException(
+                    "Inconsistency detected: shared sample found in experiment.");
+        }
+        if (sampleGroup.getDatabaseInstanceCode().equals(
+                newProjectIdentifier.getDatabaseInstanceCode()) == false
+                || sampleGroup.getGroupCode().equals(newProjectIdentifier.getGroupCode()) == false)
+        {
+            throw new UserFailureException(
+                    String
+                            .format(
+                                    "Project cannot be changed to '%s' because experiment containes samples from group '%s'.",
+                                    newProjectIdentifier, sampleGroup));
+        }
+    }
+
+    public void editMaterial(String sessionToken, MaterialIdentifier identifier,
+            List<MaterialProperty> properties, Date version)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IMaterialBO materialBO = businessObjectFactory.createMaterialBO(session);
+        materialBO.edit(identifier, properties, version);
+        materialBO.save();
+
+    }
+
+    public void editSample(String sessionToken, SampleIdentifier identifier,
+            List<SampleProperty> properties, ExperimentIdentifier experimentIdentifierOrNull,
+            Date version)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
+        sampleBO.edit(identifier, properties, experimentIdentifierOrNull, version);
+        sampleBO.save();
+
+    }
+
+    public List<VocabularyTermWithStats> listVocabularyTerms(String sessionToken,
+            Vocabulary vocabulary)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IVocabularyBO vocabularyBO = businessObjectFactory.createVocabularyBO(session);
+        vocabularyBO.load(vocabulary);
+        return vocabularyBO.countTermsUsageStatistics();
+    }
+
+    public List<DataSetTypePE> listDataSetTypes(String sessionToken)
+    {
+        return listEntityTypes(sessionToken, EntityKind.DATA_SET);
+    }
 
 }
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 ef782cd1d0c2e608a91739f7c878f92b5f9dd3b0..adc6c5dfa0ffdbbf16e931fce5d95a5bf77682bd 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
@@ -65,296 +65,306 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
 /**
- * Logger class for {@link CommonServer} which creates readable logs of method
- * invocations.
+ * Logger class for {@link CommonServer} which creates readable logs of method invocations.
  * 
  * @author Franz-Josef Elmer
  */
-final class CommonServerLogger extends AbstractServerLogger implements
-		ICommonServer {
-	/**
-	 * Creates an instance for the specified session manager and invocation
-	 * status. The session manager is used to retrieve user information which
-	 * will be a part of the log message.
-	 */
-	CommonServerLogger(final ISessionManager<Session> sessionManager,
-			final boolean invocationSuccessful) {
-		super(sessionManager, invocationSuccessful);
-	}
-
-	//
-	// IGenericServer
-	//
-
-	public List<GroupPE> listGroups(final String sessionToken,
-			final DatabaseInstanceIdentifier identifier) {
-		final String command = "list_groups";
-		if (identifier == null || identifier.getDatabaseInstanceCode() == null) {
-			logAccess(sessionToken, command);
-		} else {
-			logAccess(sessionToken, command, "DATABASE-INSTANCE(%s)",
-					identifier);
-		}
-		return null;
-	}
-
-	public void registerGroup(final String sessionToken,
-			final String groupCode, final String descriptionOrNull,
-			final String groupLeaderOrNull) {
-		logTracking(sessionToken, "register_group", "CODE(%s)", groupCode);
-	}
-
-	public List<PersonPE> listPersons(final String sessionToken) {
-		logAccess(sessionToken, "list_persons");
-		return null;
-	}
-
-	public void registerPerson(final String sessionToken, final String userID) {
-		logTracking(sessionToken, "register_person", "CODE(%s)", userID);
-
-	}
-
-	public List<RoleAssignmentPE> listRoles(final String sessionToken) {
-		logAccess(sessionToken, "list_roles");
-		return null;
-	}
-
-	public void registerGroupRole(final String sessionToken,
-			final RoleCode roleCode, final GroupIdentifier groupIdentifier,
-			final String person) {
-		logTracking(sessionToken, "register_role",
-				"ROLE(%s) GROUP(%s) PERSON(%s)", roleCode, groupIdentifier,
-				person);
-
-	}
-
-	public void registerInstanceRole(final String sessionToken,
-			final RoleCode roleCode, final String person) {
-		logTracking(sessionToken, "register_role", "ROLE(%s)  PERSON(%s)",
-				roleCode, person);
-
-	}
-
-	public void deleteGroupRole(final String sessionToken,
-			final RoleCode roleCode, final GroupIdentifier groupIdentifier,
-			final String person) {
-		logTracking(sessionToken, "delete_role",
-				"ROLE(%s) GROUP(%s) PERSON(%s)", roleCode, groupIdentifier,
-				person);
-
-	}
-
-	public void deleteInstanceRole(final String sessionToken,
-			final RoleCode roleCode, final String person) {
-		logTracking(sessionToken, "delete_role", "ROLE(%s) PERSON(%s)",
-				roleCode, person);
-
-	}
-
-	public final List<SampleTypePE> listSampleTypes(final String sessionToken) {
-		logAccess(sessionToken, "list_sample_types");
-		return null;
-	}
-
-	public final List<SamplePE> listSamples(final String sessionToken,
-			final ListSampleCriteriaDTO criteria) {
-		logAccess(sessionToken, "list_samples",
-				"TYPE(%s) OWNERS(%s) CONTAINER(%s) EXPERIMENT(%s)", criteria
-						.getSampleType(), criteria.getOwnerIdentifiers(),
-				criteria.getContainerIdentifier(), criteria
-						.getExperimentIdentifier());
-		return null;
-	}
-
-	public final List<SamplePropertyPE> listSamplesProperties(
-			final String sessionToken, final ListSampleCriteriaDTO criteria,
-			final List<PropertyTypePE> propertyCodes) {
-		logAccess(sessionToken, "list_samples_properties",
-				"CRITERIA(%s) PROPERTIES(%s)", criteria, propertyCodes.size());
-		return null;
-	}
-
-	public final SampleGenerationDTO getSampleInfo(final String sessionToken,
-			final SampleIdentifier identifier) {
-		logAccess(sessionToken, "get_sample_info", "IDENTIFIER(%s)", identifier);
-		return null;
-	}
-
-	public final List<ExternalDataPE> listExternalData(
-			final String sessionToken, final SampleIdentifier identifier) {
-		logAccess(sessionToken, "list_external_data", "IDENTIFIER(%s)",
-				identifier);
-		return null;
-	}
-
-	public List<ExternalDataPE> listExternalData(String sessionToken,
-			ExperimentIdentifier identifier) {
-		logAccess(sessionToken, "list_external_data", "IDENTIFIER(%s)",
-				identifier);
-		return null;
-	}
-
-	public final List<SearchHit> listMatchingEntities(
-			final String sessionToken,
-			final SearchableEntity[] searchableEntities, final String queryText) {
-		logAccess(sessionToken, "list_matching_entities",
-				"SEARCHABLE-ENTITIES(%s) QUERY-TEXT(%s)", Arrays
-						.toString(searchableEntities), queryText);
-		return null;
-	}
-
-	public void registerSample(final String sessionToken,
-			final NewSample newSample) {
-		logTracking(sessionToken, "register_sample",
-				"SAMPLE_TYPE(%s) SAMPLE(%S)", newSample.getSampleType(),
-				newSample.getIdentifier());
-	}
-
-	public List<ExperimentPE> listExperiments(final String sessionToken,
-			final ExperimentTypePE experimentType,
-			final ProjectIdentifier project) {
-		logAccess(sessionToken, "list_experiments", "TYPE(%s) PROJECT(%s)",
-				experimentType, project);
-		return null;
-	}
-
-	public List<ProjectPE> listProjects(final String sessionToken) {
-		logAccess(sessionToken, "list_projects");
-		return null;
-	}
-
-	public List<ExperimentTypePE> listExperimentTypes(final String sessionToken) {
-		logAccess(sessionToken, "list_experiment_types");
-		return null;
-	}
-
-	public List<PropertyTypePE> listPropertyTypes(final String sessionToken) {
-		logAccess(sessionToken, "list_property_types");
-		return null;
-	}
-
-	public final List<DataTypePE> listDataTypes(final String sessionToken) {
-		logAccess(sessionToken, "list_data_types");
-		return null;
-	}
-
-	public final List<VocabularyPE> listVocabularies(final String sessionToken,
-			boolean withTerms, boolean excludeInternal) {
-		logAccess(sessionToken, "list_vocabularies");
-		return null;
-	}
-
-	public String assignPropertyType(final String sessionToken,
-			final EntityKind entityKind, final String propertyTypeCode,
-			final String entityTypeCode, final boolean isMandatory,
-			final String defaultValue) {
-		final String entityTypeFormat = entityKind.name() + "_TYPE(%S)";
-		logTracking(sessionToken, "assign_property_type", " PROPERTY_TYPE(%S) "
-				+ entityTypeFormat + " MANDATORY(%S) DEFAULT(%S)",
-				propertyTypeCode, entityTypeCode, isMandatory, defaultValue);
-		return null;
-	}
-
-	public final void registerPropertyType(final String sessionToken,
-			final PropertyType propertyType) {
-		logTracking(sessionToken, "register_property_type",
-				"PROPERTY_TYPE(%s)", propertyType.getCode());
-	}
-
-	public final void registerVocabulary(final String sessionToken,
-			final Vocabulary vocabulary) {
-		logTracking(sessionToken, "register_vocabulary", "VOCABULARY(%s)",
-				vocabulary.getCode());
-	}
-
-	public void registerProject(String sessionToken,
-			ProjectIdentifier projectIdentifier, String description,
-			String leaderId) {
-		logTracking(sessionToken, "register_project", "PROJECT(%s)",
-				projectIdentifier);
-	}
-
-	public List<ExternalDataPE> searchForDataSets(String sessionToken,
-			DataSetSearchCriteria criteria) {
-		logAccess(sessionToken, "search_for_datasets");
-		return null;
-	}
-
-	public List<MaterialTypePE> listMaterialTypes(String sessionToken) {
-		logAccess(sessionToken, "list_material_types");
-		return null;
-	}
-
-	public List<MaterialPE> listMaterials(String sessionToken,
-			MaterialTypePE materialType) {
-		logAccess(sessionToken, "list_materials", "TYPE(%s)", materialType);
-		return null;
-	}
-
-	public void registerMaterialType(String sessionToken,
-			MaterialType entityType) {
-		logTracking(sessionToken, "register_material_type", "CODE(%s)",
-				entityType.getCode());
-	}
-
-	public void registerSampleType(String sessionToken, SampleType entityType) {
-		logTracking(sessionToken, "register_sample_type", "CODE(%s)",
-				entityType.getCode());
-	}
-
-	public void registerExperimentType(String sessionToken,
-			ExperimentType entityType) {
-		logTracking(sessionToken, "register_experiment_type", "CODE(%s)",
-				entityType.getCode());
-	}
-
-	public void editExperiment(String sessionToken,
-			ExperimentIdentifier experimentIdentifier,
-			List<ExperimentProperty> properties,
-			List<AttachmentPE> attachments,
-			ProjectIdentifier newProjectIdentifierOrNull, Date version) {
-		logTracking(sessionToken, "edit_experiment",
-				"EXPERIMENT(%s) ATTACHMENTS_ADDED(%s) NEW_PROJECT(%s)",
-				experimentIdentifier, attachments.size(),
-				newProjectIdentifierOrNull);
-	}
-
-	public void deleteDataSets(String sessionToken, List<String> dataSetCodes,
-			String reason) {
-		logTracking(sessionToken, "delete_data_sets", "CODES(%s) REASON(%s)",
-				dataSetCodes, reason);
-	}
+final class CommonServerLogger extends AbstractServerLogger implements ICommonServer
+{
+    /**
+     * Creates an instance for the specified session manager and invocation status. The session
+     * manager is used to retrieve user information which will be a part of the log message.
+     */
+    CommonServerLogger(final ISessionManager<Session> sessionManager,
+            final boolean invocationSuccessful)
+    {
+        super(sessionManager, invocationSuccessful);
+    }
+
+    //
+    // IGenericServer
+    //
+
+    public List<GroupPE> listGroups(final String sessionToken,
+            final DatabaseInstanceIdentifier identifier)
+    {
+        final String command = "list_groups";
+        if (identifier == null || identifier.getDatabaseInstanceCode() == null)
+        {
+            logAccess(sessionToken, command);
+        } else
+        {
+            logAccess(sessionToken, command, "DATABASE-INSTANCE(%s)", identifier);
+        }
+        return null;
+    }
+
+    public void registerGroup(final String sessionToken, final String groupCode,
+            final String descriptionOrNull, final String groupLeaderOrNull)
+    {
+        logTracking(sessionToken, "register_group", "CODE(%s)", groupCode);
+    }
+
+    public List<PersonPE> listPersons(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_persons");
+        return null;
+    }
+
+    public void registerPerson(final String sessionToken, final String userID)
+    {
+        logTracking(sessionToken, "register_person", "CODE(%s)", userID);
+
+    }
+
+    public List<RoleAssignmentPE> listRoles(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_roles");
+        return null;
+    }
+
+    public void registerGroupRole(final String sessionToken, final RoleCode roleCode,
+            final GroupIdentifier groupIdentifier, final String person)
+    {
+        logTracking(sessionToken, "register_role", "ROLE(%s) GROUP(%s) PERSON(%s)", roleCode,
+                groupIdentifier, person);
+
+    }
+
+    public void registerInstanceRole(final String sessionToken, final RoleCode roleCode,
+            final String person)
+    {
+        logTracking(sessionToken, "register_role", "ROLE(%s)  PERSON(%s)", roleCode, person);
+
+    }
+
+    public void deleteGroupRole(final String sessionToken, final RoleCode roleCode,
+            final GroupIdentifier groupIdentifier, final String person)
+    {
+        logTracking(sessionToken, "delete_role", "ROLE(%s) GROUP(%s) PERSON(%s)", roleCode,
+                groupIdentifier, person);
+
+    }
+
+    public void deleteInstanceRole(final String sessionToken, final RoleCode roleCode,
+            final String person)
+    {
+        logTracking(sessionToken, "delete_role", "ROLE(%s) PERSON(%s)", roleCode, person);
+
+    }
+
+    public final List<SampleTypePE> listSampleTypes(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_sample_types");
+        return null;
+    }
+
+    public final List<SamplePE> listSamples(final String sessionToken,
+            final ListSampleCriteriaDTO criteria)
+    {
+        logAccess(sessionToken, "list_samples", "TYPE(%s) OWNERS(%s) CONTAINER(%s) EXPERIMENT(%s)",
+                criteria.getSampleType(), criteria.getOwnerIdentifiers(), criteria
+                        .getContainerIdentifier(), criteria.getExperimentIdentifier());
+        return null;
+    }
+
+    public final List<SamplePropertyPE> listSamplesProperties(final String sessionToken,
+            final ListSampleCriteriaDTO criteria, final List<PropertyTypePE> propertyCodes)
+    {
+        logAccess(sessionToken, "list_samples_properties", "CRITERIA(%s) PROPERTIES(%s)", criteria,
+                propertyCodes.size());
+        return null;
+    }
+
+    public final SampleGenerationDTO getSampleInfo(final String sessionToken,
+            final SampleIdentifier identifier)
+    {
+        logAccess(sessionToken, "get_sample_info", "IDENTIFIER(%s)", identifier);
+        return null;
+    }
+
+    public final List<ExternalDataPE> listExternalData(final String sessionToken,
+            final SampleIdentifier identifier)
+    {
+        logAccess(sessionToken, "list_external_data", "IDENTIFIER(%s)", identifier);
+        return null;
+    }
+
+    public List<ExternalDataPE> listExternalData(String sessionToken,
+            ExperimentIdentifier identifier)
+    {
+        logAccess(sessionToken, "list_external_data", "IDENTIFIER(%s)", identifier);
+        return null;
+    }
+
+    public final List<SearchHit> listMatchingEntities(final String sessionToken,
+            final SearchableEntity[] searchableEntities, final String queryText)
+    {
+        logAccess(sessionToken, "list_matching_entities", "SEARCHABLE-ENTITIES(%s) QUERY-TEXT(%s)",
+                Arrays.toString(searchableEntities), queryText);
+        return null;
+    }
+
+    public void registerSample(final String sessionToken, final NewSample newSample)
+    {
+        logTracking(sessionToken, "register_sample", "SAMPLE_TYPE(%s) SAMPLE(%S)", newSample
+                .getSampleType(), newSample.getIdentifier());
+    }
+
+    public List<ExperimentPE> listExperiments(final String sessionToken,
+            final ExperimentTypePE experimentType, final ProjectIdentifier project)
+    {
+        logAccess(sessionToken, "list_experiments", "TYPE(%s) PROJECT(%s)", experimentType, project);
+        return null;
+    }
+
+    public List<ProjectPE> listProjects(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_projects");
+        return null;
+    }
+
+    public List<ExperimentTypePE> listExperimentTypes(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_experiment_types");
+        return null;
+    }
+
+    public List<PropertyTypePE> listPropertyTypes(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_property_types");
+        return null;
+    }
+
+    public final List<DataTypePE> listDataTypes(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_data_types");
+        return null;
+    }
+
+    public final List<VocabularyPE> listVocabularies(final String sessionToken, boolean withTerms,
+            boolean excludeInternal)
+    {
+        logAccess(sessionToken, "list_vocabularies");
+        return null;
+    }
+
+    public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
+            final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
+            final String defaultValue)
+    {
+        final String entityTypeFormat = entityKind.name() + "_TYPE(%S)";
+        logTracking(sessionToken, "assign_property_type", " PROPERTY_TYPE(%S) " + entityTypeFormat
+                + " MANDATORY(%S) DEFAULT(%S)", propertyTypeCode, entityTypeCode, isMandatory,
+                defaultValue);
+        return null;
+    }
+
+    public final void registerPropertyType(final String sessionToken,
+            final PropertyType propertyType)
+    {
+        logTracking(sessionToken, "register_property_type", "PROPERTY_TYPE(%s)", propertyType
+                .getCode());
+    }
+
+    public final void registerVocabulary(final String sessionToken, final Vocabulary vocabulary)
+    {
+        logTracking(sessionToken, "register_vocabulary", "VOCABULARY(%s)", vocabulary.getCode());
+    }
+
+    public void addVocabularyTerms(String sessionToken, String vocabularyCode,
+            List<String> vocabularyTerms)
+    {
+        logTracking(sessionToken, "add_vocabulary_terms", "VOCABULARY(%s) NUMBER_OF_TERMS(%s)",
+                vocabularyCode, Integer.toString(vocabularyTerms.size()));
+    }
+
+    public void registerProject(String sessionToken, ProjectIdentifier projectIdentifier,
+            String description, String leaderId)
+    {
+        logTracking(sessionToken, "register_project", "PROJECT(%s)", projectIdentifier);
+    }
+
+    public List<ExternalDataPE> searchForDataSets(String sessionToken,
+            DataSetSearchCriteria criteria)
+    {
+        logAccess(sessionToken, "search_for_datasets");
+        return null;
+    }
+
+    public List<MaterialTypePE> listMaterialTypes(String sessionToken)
+    {
+        logAccess(sessionToken, "list_material_types");
+        return null;
+    }
+
+    public List<MaterialPE> listMaterials(String sessionToken, MaterialTypePE materialType)
+    {
+        logAccess(sessionToken, "list_materials", "TYPE(%s)", materialType);
+        return null;
+    }
+
+    public void registerMaterialType(String sessionToken, MaterialType entityType)
+    {
+        logTracking(sessionToken, "register_material_type", "CODE(%s)", entityType.getCode());
+    }
+
+    public void registerSampleType(String sessionToken, SampleType entityType)
+    {
+        logTracking(sessionToken, "register_sample_type", "CODE(%s)", entityType.getCode());
+    }
+
+    public void registerExperimentType(String sessionToken, ExperimentType entityType)
+    {
+        logTracking(sessionToken, "register_experiment_type", "CODE(%s)", entityType.getCode());
+    }
+
+    public void editExperiment(String sessionToken, ExperimentIdentifier experimentIdentifier,
+            List<ExperimentProperty> properties, List<AttachmentPE> attachments,
+            ProjectIdentifier newProjectIdentifierOrNull, Date version)
+    {
+        logTracking(sessionToken, "edit_experiment",
+                "EXPERIMENT(%s) ATTACHMENTS_ADDED(%s) NEW_PROJECT(%s)", experimentIdentifier,
+                attachments.size(), newProjectIdentifierOrNull);
+    }
+
+    public void deleteDataSets(String sessionToken, List<String> dataSetCodes, String reason)
+    {
+        logTracking(sessionToken, "delete_data_sets", "CODES(%s) REASON(%s)", dataSetCodes, reason);
+    }
 
     public void uploadDataSets(String sessionToken, List<String> dataSetCodes, String cifexURL,
             String password)
     {
-        logTracking(sessionToken, "upload_data_sets", "CODES(%s) CIFEX-URL(%s)", dataSetCodes, cifexURL);
+        logTracking(sessionToken, "upload_data_sets", "CODES(%s) CIFEX-URL(%s)", dataSetCodes,
+                cifexURL);
     }
 
     public void editMaterial(String sessionToken, MaterialIdentifier identifier,
             List<MaterialProperty> properties, Date version)
     {
         logTracking(sessionToken, "edit_material", "MATERIAL(%s)", identifier);
-	}
-
-	public void editSample(String sessionToken, SampleIdentifier identifier,
-			List<SampleProperty> properties,
-			ExperimentIdentifier experimentIdentifierOrNull, Date version) {
-		logTracking(sessionToken, "edit_sample",
-				"SAMPLE(%s), CHANGE_TO_EXPERIMENT(%S)", identifier,
-				experimentIdentifierOrNull);
-
-	}
-
-	public List<VocabularyTermWithStats> listVocabularyTerms(
-			String sessionToken, Vocabulary vocabulary) {
-		logAccess(sessionToken, "list_vocabulary_terms", "VOCABULARY(%s)",
-				vocabulary.getCode());
-		return null;
-	}
-
-	public List<DataSetTypePE> listDataSetTypes(String sessionToken) {
-		logAccess(sessionToken, "list_data_set_types");
-		return null;
-	}
+    }
+
+    public void editSample(String sessionToken, SampleIdentifier identifier,
+            List<SampleProperty> properties, ExperimentIdentifier experimentIdentifierOrNull,
+            Date version)
+    {
+        logTracking(sessionToken, "edit_sample", "SAMPLE(%s), CHANGE_TO_EXPERIMENT(%S)",
+                identifier, experimentIdentifierOrNull);
+
+    }
+
+    public List<VocabularyTermWithStats> listVocabularyTerms(String sessionToken,
+            Vocabulary vocabulary)
+    {
+        logAccess(sessionToken, "list_vocabulary_terms", "VOCABULARY(%s)", vocabulary.getCode());
+        return null;
+    }
+
+    public List<DataSetTypePE> listDataSetTypes(String sessionToken)
+    {
+        logAccess(sessionToken, "list_data_set_types");
+        return null;
+    }
 }
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 7d069ee3a1532fa32e4c5e2a534c259762189886..e67f1eb952164c490cc8f5b265f51f164d2018f0 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
@@ -284,6 +284,14 @@ public interface ICommonServer extends IServer
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
     public void registerVocabulary(final String sessionToken, final Vocabulary vocabulary);
 
+    /**
+     * Adds new terms to a vocabulary.
+     */
+    @Transactional
+    @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    public void addVocabularyTerms(String sessionToken, String vocabularyCode,
+            List<String> vocabularyTerms);
+
     /**
      * Registers new project.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index e57053c22a95f040b95556ceaa8b9fdeda4fc485..9d15068eedf5a349cc0c70e7e4e4b0885e55efcc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -145,7 +145,7 @@ var common = {
   type_of: "Entity",
   vocabulary: "Vocabulary",
   vocabulary_terms: "Terms",
-  vocabulary_terms_empty: "White space or comma separated list",
+  vocabulary_terms_empty: "Space or comma separated list",
   mandatory: "Mandatory",
   default_value: "Initial Value",
   default_value_tooltip: "The value of the assigned property for all currently existing entities.",
@@ -248,6 +248,10 @@ var common = {
  TERM_FOR_EXPERIMENTS_USAGE: "Usages for Experiments",
  TERM_FOR_MATERIALS_USAGE: "Usages for Materials",
  TERM_TOTAL_USAGE: "Total Usages Number",
+ add_vocabulary_terms_button: "Add New Terms",
+ add_vocabulary_terms_title: "Add New Terms",
+ add_vocabulary_terms_ok_button: "OK",
+ vocabulary_terms_validation_message: "Term '{0}' already exists.", 
  
  //
  // Project Browser