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 188e987550636cf50131638193f131631187448d..1f61940f26543f9a404851f36aec5036799c02f3 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
@@ -66,7 +66,6 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DataSetUp
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DeletionTechIdCollectionPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ExperimentUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ListSampleCriteriaPredicate;
-import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.MetaprojectPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectUpdatesPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.RevertDeletionPredicate;
 import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleTechIdCollectionPredicate;
@@ -3450,14 +3449,14 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
             IMetaprojectId metaprojectId)
     {
-        Session session = getSession(sessionToken);
-        String baseIndexURL = getBaseIndexURL(sessionToken);
-
         if (metaprojectId == null)
         {
             throw new UserFailureException("Metaproject id cannot be null");
         }
 
+        Session session = getSession(sessionToken);
+        String baseIndexURL = getBaseIndexURL(sessionToken);
+
         IMetaprojectBO metaprojectBO = getBusinessObjectFactory().createMetaprojectBO(session);
         MetaprojectPE metaprojectPE = metaprojectBO.tryFindByMetaprojectId(metaprojectId);
 
@@ -3533,6 +3532,15 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     public void addToMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToAdd)
     {
+        if (metaprojectId == null)
+        {
+            throw new UserFailureException("Metaproject id cannot be null");
+        }
+        if (assignmentsToAdd == null)
+        {
+            throw new UserFailureException("Assignments to add cannot be null");
+        }
+
         Session session = getSession(sessionToken);
 
         IMetaprojectBO metaprojectBO = getBusinessObjectFactory().createMetaprojectBO(session);
@@ -3553,6 +3561,15 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     public void removeFromMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToRemove)
     {
+        if (metaprojectId == null)
+        {
+            throw new UserFailureException("Metaproject id cannot be null");
+        }
+        if (assignmentsToRemove == null)
+        {
+            throw new UserFailureException("Assignments to remove cannot be null");
+        }
+
         Session session = getSession(sessionToken);
 
         IMetaprojectBO metaprojectBO = getBusinessObjectFactory().createMetaprojectBO(session);
@@ -3572,6 +3589,11 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     public void deleteMetaproject(String sessionToken, IMetaprojectId metaprojectId)
     {
+        if (metaprojectId == null)
+        {
+            throw new UserFailureException("Metaproject id cannot be null");
+        }
+
         Session session = getSession(sessionToken);
 
         IMetaprojectBO metaprojectBO = getBusinessObjectFactory().createMetaprojectBO(session);
@@ -3584,8 +3606,14 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
 
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
-    public Metaproject registerMetaproject(String sessionToken, Metaproject metaproject)
+    public Metaproject registerMetaproject(String sessionToken, String name,
+            String descriptionOrNull)
     {
+        if (name == null)
+        {
+            throw new UserFailureException("Metaproject name cannot be null");
+        }
+
         Session session = getSession(sessionToken);
 
         IDAOFactory daoFactory = getDAOFactory();
@@ -3595,29 +3623,43 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
 
         MetaprojectPE metaprojectPE = new MetaprojectPE();
         metaprojectPE.setOwner(owner);
-        MetaprojectTranslator.translate(metaproject, metaprojectPE);
+        metaprojectPE.setName(name);
+        metaprojectPE.setDescription(descriptionOrNull);
+        metaprojectPE.setPrivate(true);
         metaprojectDAO.createOrUpdateMetaproject(metaprojectPE, session.tryGetPerson());
         return MetaprojectTranslator.translate(metaprojectPE);
     }
 
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
-    public Metaproject updateMetaproject(String sessionToken,
-            @AuthorizationGuard(guardClass = MetaprojectPredicate.class)
-            Metaproject metaproject)
+    public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
+            String name, String descriptionOrNull)
     {
+        if (metaprojectId == null)
+        {
+            throw new UserFailureException("Metaproject id cannot be null");
+        }
+        if (name == null)
+        {
+            throw new UserFailureException("Metaproject name cannot be null");
+        }
+
         Session session = getSession(sessionToken);
 
-        IDAOFactory daoFactory = getDAOFactory();
-        IMetaprojectDAO metaprojectDAO = daoFactory.getMetaprojectDAO();
+        IMetaprojectBO metaprojectBO = getBusinessObjectFactory().createMetaprojectBO(session);
+        MetaprojectPE metaprojectPE = metaprojectBO.tryFindByMetaprojectId(metaprojectId);
 
-        if (metaproject.getId() == null)
+        if (metaprojectPE == null)
         {
-            throw new UserFailureException("The ID of metaproject for update cannot be null.");
+            throw new UserFailureException("Metaproject with id: " + metaprojectId
+                    + " doesn't exist");
         }
-        MetaprojectPE metaprojectPE = metaprojectDAO.getByTechId(new TechId(metaproject.getId()));
 
-        MetaprojectTranslator.translate(metaproject, metaprojectPE);
+        getAuthorizationService(session).checkAccessMetaproject(metaprojectPE);
+
+        metaprojectPE.setName(name);
+        metaprojectPE.setDescription(descriptionOrNull);
+        IMetaprojectDAO metaprojectDAO = getDAOFactory().getMetaprojectDAO();
         metaprojectDAO.createOrUpdateMetaproject(metaprojectPE, session.tryGetPerson());
         return MetaprojectTranslator.translate(metaprojectPE);
     }
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 8efb3693c6afc6b94f5cb8110ef6d95e603af9b5..107b55458010da59691e50b96c117c5586dae866 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
@@ -1475,24 +1475,28 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
     public void addToMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToAdd)
     {
+        MetaprojectAssignmentsIds assignments =
+                assignmentsToAdd != null ? assignmentsToAdd : new MetaprojectAssignmentsIds();
+
         logAccess(sessionToken, "addToMetaproject",
                 "METAPROJECT_ID(%s), EXPERIMENTS(%s), SAMPLES(%s), DATA_SETS(%s), MATERIALS(%s)",
-                metaprojectId, abbreviate(assignmentsToAdd.getExperiments()),
-                abbreviate(assignmentsToAdd.getSamples()),
-                abbreviate(assignmentsToAdd.getDataSets()),
-                abbreviate(assignmentsToAdd.getMaterials()));
+                metaprojectId, abbreviate(assignments.getExperiments()),
+                abbreviate(assignments.getSamples()), abbreviate(assignments.getDataSets()),
+                abbreviate(assignments.getMaterials()));
     }
 
     @Override
     public void removeFromMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToRemove)
     {
+        MetaprojectAssignmentsIds assignments =
+                assignmentsToRemove != null ? assignmentsToRemove : new MetaprojectAssignmentsIds();
+
         logAccess(sessionToken, "removeFromMetaproject",
                 "METAPROJECT_ID(%s), EXPERIMENTS(%s), SAMPLES(%s), DATA_SETS(%s), MATERIALS(%s)",
-                metaprojectId, abbreviate(assignmentsToRemove.getExperiments()),
-                abbreviate(assignmentsToRemove.getSamples()),
-                abbreviate(assignmentsToRemove.getDataSets()),
-                abbreviate(assignmentsToRemove.getMaterials()));
+                metaprojectId, abbreviate(assignments.getExperiments()),
+                abbreviate(assignments.getSamples()), abbreviate(assignments.getDataSets()),
+                abbreviate(assignments.getMaterials()));
     }
 
     @Override
@@ -1502,18 +1506,20 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
     }
 
     @Override
-    public Metaproject registerMetaproject(String sessionToken, Metaproject metaproject)
+    public Metaproject registerMetaproject(String sessionToken, String name,
+            String descriptionOrNull)
     {
-        String identifier = metaproject == null ? "null" : metaproject.getIdentifier();
-        logAccess(sessionToken, "registerMetaproject", "METAPROJECT(%s)", identifier);
+        logAccess(sessionToken, "registerMetaproject", "NAME(%s) DESCRIPTION(%s)", name,
+                descriptionOrNull);
         return null;
     }
 
     @Override
-    public Metaproject updateMetaproject(String sessionToken, Metaproject metaproject)
+    public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
+            String name, String descriptionOrNull)
     {
-        String identifier = metaproject == null ? "null" : metaproject.getIdentifier();
-        logAccess(sessionToken, "updateMetaproject", "METAPROJECT(%s)", identifier);
+        logAccess(sessionToken, "updateMetaproject", "METAPROJECT_ID(%s) NAME(%s) DESCRIPTION(%s)",
+                metaprojectId, name, descriptionOrNull);
         return null;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
index 8eec036e736501b30cb73e743d2a599ec7833118..0405ff93b82a9516ef797642cfdb7919cd35f5bb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
@@ -148,20 +148,18 @@ public class GeneralInformationChangingService extends
     @Override
     @Transactional(readOnly = false)
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
-    public Metaproject createMetaproject(String sessionToken, String name, String description)
+    public Metaproject createMetaproject(String sessionToken, String name, String descriptionOrNull)
     {
-        Metaproject metaproject = new Metaproject();
-        metaproject.setName(name);
-        metaproject.setDescription(description);
-        return server.registerMetaproject(sessionToken, metaproject);
+        return server.registerMetaproject(sessionToken, name, descriptionOrNull);
     }
 
     @Override
     @Transactional(readOnly = false)
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
-    public Metaproject updateMetaproject(String sessionToken, Metaproject metaproject)
+    public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
+            String name, String descriptionOrNull)
     {
-        return server.updateMetaproject(sessionToken, metaproject);
+        return server.updateMetaproject(sessionToken, metaprojectId, name, descriptionOrNull);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
index cf0c2668ddd861bb4576ae78a020faee6f401ebf..5ce162954b0d55d362939d8d25c5ad2c69cb08d0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
@@ -90,10 +90,11 @@ class GeneralInformationChangingServiceLogger extends AbstractServerLogger imple
     }
 
     @Override
-    public Metaproject updateMetaproject(String sessionToken, Metaproject metaproject)
+    public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
+            String name, String descriptionOrNull)
     {
-        String identifier = metaproject == null ? "null" : metaproject.getIdentifier();
-        logAccess(sessionToken, "updateMetaproject", "METAPROJECT(%s)", identifier);
+        logAccess(sessionToken, "updateMetaproject", "METAPROJECT_ID(%s) NAME(%s) DESCRIPTION(%s)",
+                metaprojectId, name, descriptionOrNull);
         return null;
     }
 
@@ -107,24 +108,28 @@ class GeneralInformationChangingServiceLogger extends AbstractServerLogger imple
     public void addToMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToAdd)
     {
+        MetaprojectAssignmentsIds assignments =
+                assignmentsToAdd != null ? assignmentsToAdd : new MetaprojectAssignmentsIds();
+
         logAccess(sessionToken, "addToMetaproject",
                 "METAPROJECT_ID(%s), EXPERIMENTS(%s), SAMPLES(%s), DATA_SETS(%s), MATERIALS(%s)",
-                metaprojectId, abbreviate(assignmentsToAdd.getExperiments()),
-                abbreviate(assignmentsToAdd.getSamples()),
-                abbreviate(assignmentsToAdd.getDataSets()),
-                abbreviate(assignmentsToAdd.getMaterials()));
+                metaprojectId, abbreviate(assignments.getExperiments()),
+                abbreviate(assignments.getSamples()), abbreviate(assignments.getDataSets()),
+                abbreviate(assignments.getMaterials()));
     }
 
     @Override
     public void removeFromMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToRemove)
     {
+        MetaprojectAssignmentsIds assignments =
+                assignmentsToRemove != null ? assignmentsToRemove : new MetaprojectAssignmentsIds();
+
         logAccess(sessionToken, "removeFromMetaproject",
                 "METAPROJECT_ID(%s), EXPERIMENTS(%s), SAMPLES(%s), DATA_SETS(%s), MATERIALS(%s)",
-                metaprojectId, abbreviate(assignmentsToRemove.getExperiments()),
-                abbreviate(assignmentsToRemove.getSamples()),
-                abbreviate(assignmentsToRemove.getDataSets()),
-                abbreviate(assignmentsToRemove.getMaterials()));
+                metaprojectId, abbreviate(assignments.getExperiments()),
+                abbreviate(assignments.getSamples()), abbreviate(assignments.getDataSets()),
+                abbreviate(assignments.getMaterials()));
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java
index ae53f3e8de711f029b4edc57fbd322a38efc2a63..084c9a7bd989d9d15fd3247630c7893a7a66b3c4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java
@@ -21,6 +21,7 @@ import java.util.List;
 import org.apache.log4j.Logger;
 import org.hibernate.SessionFactory;
 import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Order;
 import org.hibernate.criterion.Restrictions;
 import org.springframework.orm.hibernate3.HibernateTemplate;
 
@@ -73,6 +74,7 @@ public class MetaprojectDAO extends AbstractGenericEntityDAO<MetaprojectPE> impl
     {
         final DetachedCriteria criteria = DetachedCriteria.forClass(MetaprojectPE.class);
         criteria.add(Restrictions.eq("owner", owner));
+        criteria.addOrder(Order.asc("name"));
         final List<MetaprojectPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
         if (operationLog.isDebugEnabled())
         {
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 519d907d7c0a2c2a8841aac10b58c7fb77fd7f35..88bec154d14ddf23e5acc5694bf978b3ba9b7f02 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
@@ -1376,11 +1376,13 @@ public interface ICommonServer extends IServer
      * Registers a new metaproject.
      */
     @Transactional
-    public Metaproject registerMetaproject(String sessionToken, Metaproject metaproject);
+    public Metaproject registerMetaproject(String sessionToken, String name,
+            String descriptionOrNull);
 
     /**
      * Updates existing metaprojest.
      */
     @Transactional
-    public Metaproject updateMetaproject(String sessionToken, Metaproject metaproject);
+    public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
+            String name, String descriptionOrNull);
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAOTest.java
index 54ddad5dc4e03befd4dfd55ca3dce5efc5f65426..705c436ebb822a3e870f460160329ebc3b42f42a 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAOTest.java
@@ -33,6 +33,20 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.MetaprojectPE;
  */
 public class MetaprojectDAOTest extends AbstractDAOTest
 {
+
+    @Test
+    public void testFindByOwnerAndName()
+    {
+        MetaprojectPE metaproject =
+                daoFactory.getMetaprojectDAO().tryFindByOwnerAndName("test", "TEST_METAPROJECTS");
+        assertEquals(Long.valueOf(1), metaproject.getId());
+
+        metaproject =
+                daoFactory.getMetaprojectDAO().tryFindByOwnerAndName("test",
+                        "ANOTHER_TEST_METAPROJECTS");
+        assertEquals(Long.valueOf(3), metaproject.getId());
+    }
+
     @Test
     public void testListMetaprojects()
     {
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java
index 10cca0a1bcdd38ac4723d262bee7b9c800699e18..c6f1a44768738f9995d009290c249da3989f2741 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java
@@ -17,20 +17,42 @@
 package ch.systemsx.cisd.openbis.systemtest.api.v1;
 
 import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertTrue;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.common.exception.AuthorizationFailureException;
+import ch.systemsx.cisd.common.exception.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignmentsIds;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.dataset.DataSetCodeId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.dataset.DataSetTechIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.ExperimentIdentifierId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.ExperimentPermIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.ExperimentTechIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.material.MaterialCodeAndTypeCodeId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.material.MaterialTechIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.MetaprojectIdentifierId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.MetaprojectTechIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.SampleIdentifierId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.SamplePermIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.SampleTechIdId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.systemtest.PropertyHistory;
 import ch.systemsx.cisd.openbis.systemtest.SystemTestCase;
@@ -58,12 +80,6 @@ public class GeneralInformationChangingServiceTest extends SystemTestCase
         sessionToken = generalInformationService.tryToAuthenticateForAllServices("test", "a");
     }
 
-    @AfterMethod
-    public void afterMethod()
-    {
-        generalInformationService.logout(sessionToken);
-    }
-
     @Test
     public void testUpdateExperimentProperties()
     {
@@ -78,8 +94,8 @@ public class GeneralInformationChangingServiceTest extends SystemTestCase
         localCommonServer.assignPropertyType(sessionToken, new NewETPTAssignment(EntityKind.SAMPLE,
                 "GENDER", "CELL_PLATE", false, null, null, 1L, false, false, null, true));
         assertProperties("[ANY_MATERIAL: 2 (GENE), BACTERIUM: BACTERIUM-Y (BACTERIUM), "
-                + "COMMENT: extremely simple stuff, ORGANISM: GORILLA, SIZE: 321]", localCommonServer
-                .getSampleInfo(sessionToken, id).getParent());
+                + "COMMENT: extremely simple stuff, ORGANISM: GORILLA, SIZE: 321]",
+                localCommonServer.getSampleInfo(sessionToken, id).getParent());
         HashMap<String, String> properties = new HashMap<String, String>();
         properties.put("SIZE", "42");
         properties.put("any_material", "1 (GENE)");
@@ -99,6 +115,406 @@ public class GeneralInformationChangingServiceTest extends SystemTestCase
         assertEquals(
                 "[ANY_MATERIAL: material:2 [GENE]<a:1>, ORGANISM: term:GORILLA [ORGANISM]<a:1>, SIZE: 321<a:1>]",
                 history.toString());
+    }
+
+    @Test
+    public void testCreateMetaproject()
+    {
+        String name = "BRAND_NEW_METAPROJECT";
+        String description = "I'm brand new";
+
+        List<String> beforeNames = listMetaprojectNames();
+        assertFalse(beforeNames.contains(name));
+
+        Metaproject metaproject =
+                generalInformationChangingService
+                        .createMetaproject(sessionToken, name, description);
+
+        List<String> afterNames = listMetaprojectNames();
+        assertTrue(afterNames.contains(name));
+
+        assertEquals(beforeNames.size() + 1, afterNames.size());
+        afterNames.remove(name);
+        assertEquals(beforeNames, afterNames);
+
+        assertNotNull(metaproject.getId());
+        assertEquals("test", metaproject.getOwnerId());
+        assertEquals("/test/" + name, metaproject.getIdentifier());
+        assertEquals(name, metaproject.getName());
+        assertEquals(description, metaproject.getDescription());
+        assertNotNull(metaproject.getCreationDate());
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testCreateMetaprojectWithNameDuplicatedForSameOwner()
+    {
+        generalInformationChangingService.createMetaproject(sessionToken, "TEST_METAPROJECTS",
+                "My name is already used by the same owner");
+    }
+
+    @Test
+    public void testCreateMetaprojectWithNameDuplicatedForDifferentOwner()
+    {
+        generalInformationChangingService.createMetaproject(sessionToken, "TEST_METAPROJECTS_2",
+                "My name is already used by a different owner");
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testCreateMetaprojectWithEmptyName()
+    {
+        generalInformationChangingService.createMetaproject(sessionToken, null, "My name is empty");
+    }
+
+    @Test
+    public void testCreateMetaprojectWithEmptyDescription()
+    {
+        String name = "METAPROJECT_WITH_EMPTY_DESCRIPTION";
+
+        Metaproject metaproject =
+                generalInformationChangingService.createMetaproject(sessionToken, name, null);
+        assertEquals(name, metaproject.getName());
+        assertNull(metaproject.getDescription());
+    }
+
+    @Test
+    public void testUpdateMetaproject()
+    {
+        String beforeName = "TEST_METAPROJECTS";
+        String afterName = "TEST_METAPROJECTS_UPDATED";
+        String description = "My description is brand new";
+
+        List<String> beforeNames = listMetaprojectNames();
+        assertTrue(beforeNames.contains(beforeName));
+        assertFalse(beforeNames.contains(afterName));
+
+        Metaproject metaproject =
+                generalInformationChangingService.updateMetaproject(sessionToken,
+                        new MetaprojectIdentifierId("/test/" + beforeName), afterName, description);
+
+        List<String> afterNames = listMetaprojectNames();
+        assertFalse(afterNames.contains(beforeName));
+        assertTrue(afterNames.contains(afterName));
+
+        assertEquals(beforeNames.size(), afterNames.size());
+        beforeNames.remove(beforeName);
+        afterNames.remove(afterName);
+        assertEquals(beforeNames, afterNames);
+
+        assertNotNull(metaproject.getId());
+        assertEquals("test", metaproject.getOwnerId());
+        assertEquals("/test/" + afterName, metaproject.getIdentifier());
+        assertEquals(afterName, metaproject.getName());
+        assertEquals(description, metaproject.getDescription());
+        assertNotNull(metaproject.getCreationDate());
+    }
+
+    @Test(expectedExceptions = AuthorizationFailureException.class)
+    public void testUpdateMetaprojectOwnedBySomebodyElse()
+    {
+        generalInformationChangingService.updateMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test_role/TEST_METAPROJECTS"), "SOME_NEW_NAME",
+                "some new description");
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testUpdateMetaprojectWithEmptyId()
+    {
+        generalInformationChangingService.updateMetaproject(sessionToken, null, "SOME_NEW_NAME",
+                "some new description");
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testUpdateMetaprojectThatDoesntExist()
+    {
+        generalInformationChangingService.updateMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/METAPROJECT_THAT_DOESNT_EXIST"),
+                "SOME_NEW_NAME", "some new description");
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testUpdateMetaprojectToEmptyName()
+    {
+        generalInformationChangingService.updateMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/TEST_METAPROJECTS"), null,
+                "some new description");
+    }
+
+    @Test
+    public void testUpdateMetaprojectToEmptyDescription()
+    {
+        generalInformationChangingService.updateMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/TEST_METAPROJECTS"), "TEST_METAPROJECTS", null);
+    }
+
+    @Test
+    public void testDeleteMetaproject()
+    {
+        String name = "TEST_METAPROJECTS";
+
+        List<String> beforeNames = listMetaprojectNames();
+        assertTrue(beforeNames.contains(name));
+
+        generalInformationChangingService.deleteMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/" + name));
+
+        List<String> afterNames = listMetaprojectNames();
+        assertFalse(afterNames.contains(name));
+
+        assertEquals(beforeNames.size() - 1, afterNames.size());
+        beforeNames.remove(name);
+        assertEquals(beforeNames, afterNames);
+    }
+
+    @Test(expectedExceptions = AuthorizationFailureException.class)
+    public void testDeleteMetaprojectOwnedBySomebodyElse()
+    {
+        generalInformationChangingService.deleteMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test_role/TEST_METAPROJECTS"));
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testDeleteMetaprojectWithEmptyId()
+    {
+        generalInformationChangingService.deleteMetaproject(sessionToken, null);
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testDeleteMetaprojectThatDoesntExist()
+    {
+        generalInformationChangingService.deleteMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/METAPROJECT_THAT_DOESNT_EXIST"));
+    }
+
+    @Test
+    public void testAddToMetaproject()
+    {
+        Metaproject metaproject = createMetaprojectWithAssignments();
+
+        MetaprojectAssignments assignments =
+                generalInformationService.getMetaproject(sessionToken, new MetaprojectIdentifierId(
+                        metaproject.getIdentifier()));
+
+        List<Long> experimentIds = getObjectIds(assignments.getExperiments());
+        assertEquals(3, experimentIds.size());
+        assertTrue(experimentIds.contains(2L));
+        assertTrue(experimentIds.contains(22L));
+        assertTrue(experimentIds.contains(23L));
+
+        List<Long> samplesIds = getObjectIds(assignments.getSamples());
+        assertEquals(4, samplesIds.size());
+        assertTrue(samplesIds.contains(647L));
+        assertTrue(samplesIds.contains(602L));
+        assertTrue(samplesIds.contains(340L));
+        assertTrue(samplesIds.contains(342L));
 
+        List<Long> dataSetIds = getObjectIds(assignments.getDataSets());
+        assertEquals(2, dataSetIds.size());
+        assertTrue(dataSetIds.contains(8L));
+        assertTrue(dataSetIds.contains(12L));
+
+        List<Long> materialIds = getObjectIds(assignments.getMaterials());
+        assertEquals(2, materialIds.size());
+        assertTrue(materialIds.contains(18L));
+        assertTrue(materialIds.contains(8L));
+    }
+
+    @Test(expectedExceptions = AuthorizationFailureException.class)
+    public void testAddToMetaprojectOwnedBySomebodyElse()
+    {
+        generalInformationChangingService.addToMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test_role/TEST_METAPROJECTS"),
+                new MetaprojectAssignmentsIds());
+    }
+
+    @Test
+    public void testAddToMetaprojectAssignmentsThatAlreadyExist()
+    {
+        Metaproject metaproject =
+                generalInformationChangingService.createMetaproject(sessionToken,
+                        "BRAND_NEW_METAPROJECT", null);
+
+        MetaprojectAssignmentsIds assignmentsToAdd = new MetaprojectAssignmentsIds();
+        assignmentsToAdd.addExperiment(new ExperimentIdentifierId("/CISD/NEMO/EXP1"));
+
+        generalInformationChangingService.addToMetaproject(sessionToken, new MetaprojectTechIdId(
+                metaproject.getId()), assignmentsToAdd);
+        generalInformationChangingService.addToMetaproject(sessionToken, new MetaprojectTechIdId(
+                metaproject.getId()), assignmentsToAdd);
+
+        MetaprojectAssignments assignments =
+                generalInformationService.getMetaproject(sessionToken, new MetaprojectTechIdId(
+                        metaproject.getId()));
+        assertEquals(1, assignments.getExperiments().size());
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testAddToMetaprojectWithEmptyId()
+    {
+        generalInformationChangingService.addToMetaproject(sessionToken, null,
+                new MetaprojectAssignmentsIds());
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testAddToMetaprojectWithNullAssignments()
+    {
+        generalInformationChangingService.addToMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/TEST_METAPROJECTS"), null);
+    }
+
+    @Test
+    public void testAddToMetaprojectWithEmptyAssignments()
+    {
+        generalInformationChangingService.addToMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/TEST_METAPROJECTS"),
+                new MetaprojectAssignmentsIds());
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testAddToMetaprojectThatDoesntExist()
+    {
+        generalInformationChangingService.addToMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/METAPROJECT_THAT_DOESNT_EXIST"),
+                new MetaprojectAssignmentsIds());
+    }
+
+    @Test
+    public void testRemoveFromMetaproject()
+    {
+        Metaproject metaproject = createMetaprojectWithAssignments();
+
+        MetaprojectAssignmentsIds assignmentsToRemove = new MetaprojectAssignmentsIds();
+        assignmentsToRemove.addExperiment(new ExperimentIdentifierId("/CISD/NEMO/EXP1"));
+        assignmentsToRemove.addSample(new SampleIdentifierId("/A03"));
+        assignmentsToRemove.addDataSet(new DataSetCodeId("20081105092259000-8"));
+        assignmentsToRemove.addMaterial(new MaterialCodeAndTypeCodeId("GFP", "CONTROL"));
+
+        generalInformationChangingService.removeFromMetaproject(sessionToken,
+                new MetaprojectIdentifierId(metaproject.getIdentifier()), assignmentsToRemove);
+
+        MetaprojectAssignments assignments =
+                generalInformationService.getMetaproject(sessionToken, new MetaprojectIdentifierId(
+                        metaproject.getIdentifier()));
+
+        List<Long> experimentIds = getObjectIds(assignments.getExperiments());
+        assertEquals(2, experimentIds.size());
+        assertTrue(experimentIds.contains(22L));
+        assertTrue(experimentIds.contains(23L));
+
+        List<Long> samplesIds = getObjectIds(assignments.getSamples());
+        assertEquals(3, samplesIds.size());
+        assertTrue(samplesIds.contains(602L));
+        assertTrue(samplesIds.contains(340L));
+        assertTrue(samplesIds.contains(342L));
+
+        List<Long> dataSetIds = getObjectIds(assignments.getDataSets());
+        assertEquals(1, dataSetIds.size());
+        assertTrue(dataSetIds.contains(12L));
+
+        List<Long> materialIds = getObjectIds(assignments.getMaterials());
+        assertEquals(1, materialIds.size());
+        assertTrue(materialIds.contains(8L));
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testRemoveFromMetaprojectOwnedBySomebodyElse()
+    {
+        generalInformationChangingService.removeFromMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test_role/TEST_METAPROJECTS"),
+                new MetaprojectAssignmentsIds());
     }
+
+    public void testRemoveFromMetaprojectAssignmentsThatDoNotExist()
+    {
+        Metaproject metaproject = createMetaprojectWithAssignments();
+        MetaprojectAssignmentsIds assignmentsToRemove = new MetaprojectAssignmentsIds();
+        assignmentsToRemove.addExperiment(new ExperimentIdentifierId("/CISD/NEMO/EXP10"));
+
+        generalInformationChangingService.removeFromMetaproject(sessionToken,
+                new MetaprojectIdentifierId(metaproject.getIdentifier()), assignmentsToRemove);
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testRemoveFromMetaprojectWithEmptyId()
+    {
+        generalInformationChangingService.removeFromMetaproject(sessionToken, null,
+                new MetaprojectAssignmentsIds());
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testRemoveFromMetaprojectWithNullAssignments()
+    {
+        generalInformationChangingService.removeFromMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/TEST_METAPROJECTS"), null);
+    }
+
+    @Test
+    public void testRemoveFromMetaprojectWithEmptyAssignments()
+    {
+        generalInformationChangingService.removeFromMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/TEST_METAPROJECTS"),
+                new MetaprojectAssignmentsIds());
+    }
+
+    @Test(expectedExceptions = UserFailureException.class)
+    public void testRemoveFromMetaprojectThatDoesntExist()
+    {
+        generalInformationChangingService.removeFromMetaproject(sessionToken,
+                new MetaprojectIdentifierId("/test/METAPROJECT_THAT_DOESNT_EXIST"),
+                new MetaprojectAssignmentsIds());
+    }
+
+    private List<String> listMetaprojectNames()
+    {
+        List<Metaproject> metaprojects = generalInformationService.listMetaprojects(sessionToken);
+        List<String> names = new ArrayList<String>();
+
+        for (Metaproject metaproject : metaprojects)
+        {
+            names.add(metaproject.getName());
+        }
+
+        return names;
+    }
+
+    private Metaproject createMetaprojectWithAssignments()
+    {
+        Metaproject metaproject =
+                generalInformationChangingService.createMetaproject(sessionToken,
+                        "BRAND_NEW_METAPROJECT", null);
+
+        MetaprojectAssignmentsIds assignmentsToAdd = new MetaprojectAssignmentsIds();
+
+        assignmentsToAdd.addExperiment(new ExperimentIdentifierId("/CISD/NEMO/EXP1")); // id: 2
+        assignmentsToAdd.addExperiment(new ExperimentPermIdId("201108050937246-1031")); // id: 22
+        assignmentsToAdd.addExperiment(new ExperimentTechIdId(23L)); // id: 23
+
+        assignmentsToAdd.addSample(new SampleIdentifierId("/A03")); // id: 647
+        assignmentsToAdd.addSample(new SampleIdentifierId("/CISD/N19")); // id: 602
+        assignmentsToAdd.addSample(new SamplePermIdId("200811050917877-346")); // id: 340
+        assignmentsToAdd.addSample(new SampleTechIdId(342L)); // id: 342
+
+        assignmentsToAdd.addDataSet(new DataSetCodeId("20081105092259000-8")); // id: 8
+        assignmentsToAdd.addDataSet(new DataSetTechIdId(12L)); // id: 12
+
+        assignmentsToAdd.addMaterial(new MaterialCodeAndTypeCodeId("GFP", "CONTROL")); // id: 18
+        assignmentsToAdd.addMaterial(new MaterialTechIdId(8L)); // id: 8
+
+        generalInformationChangingService.addToMetaproject(sessionToken, new MetaprojectTechIdId(
+                metaproject.getId()), assignmentsToAdd);
+
+        return metaproject;
+    }
+
+    private List<Long> getObjectIds(List<? extends IIdHolder> objects)
+    {
+        List<Long> ids = new ArrayList<Long>();
+
+        for (IIdHolder object : objects)
+        {
+            ids.add(object.getId());
+        }
+
+        return ids;
+    }
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
index fb6306268eeb22d49e6b12a13849f059898fc98d..00d64e09ff3cd4c8a910c7cdb6c15492608ad3cc 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
@@ -61,7 +61,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchCl
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClauseAttribute;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClauseTimeAttribute;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
-import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.MetaprojectTechIdId;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.MetaprojectIdentifierId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
@@ -1026,16 +1026,19 @@ public class GeneralInformationServiceTest extends SystemTestCase
         assertEquals(2, metaprojects.size());
     }
 
+    @Test(expectedExceptions = AuthorizationFailureException.class)
+    public void testGetMetaprojectOwnedBySomebodyElse()
+    {
+        generalInformationService.getMetaproject(sessionToken, new MetaprojectIdentifierId(
+                "/test_role/TEST_METAPROJECTS"));
+    }
+
     @Test
     public void testGetMetaprojects()
     {
-        List<Metaproject> metaprojects = generalInformationService.listMetaprojects(sessionToken);
-
-        Metaproject metaproject = metaprojects.iterator().next();
-
         MetaprojectAssignments metaprojectAssignments =
-                generalInformationService.getMetaproject(sessionToken, new MetaprojectTechIdId(
-                        metaproject.getId()));
+                generalInformationService.getMetaproject(sessionToken, new MetaprojectIdentifierId(
+                        "/test/TEST_METAPROJECTS"));
 
         assertEquals(1, metaprojectAssignments.getDataSets().size());
         assertEquals(1, metaprojectAssignments.getMaterials().size());
@@ -1045,12 +1048,9 @@ public class GeneralInformationServiceTest extends SystemTestCase
         generalInformationService.logout(sessionToken);
         sessionToken = generalInformationService.tryToAuthenticateForAllServices("test_role", "a");
 
-        metaprojects = generalInformationService.listMetaprojects(sessionToken);
-        metaproject = metaprojects.iterator().next();
-
         metaprojectAssignments =
-                generalInformationService.getMetaproject(sessionToken, new MetaprojectTechIdId(
-                        metaproject.getId()));
+                generalInformationService.getMetaproject(sessionToken, new MetaprojectIdentifierId(
+                        "/test_role/TEST_METAPROJECTS"));
 
         assertEquals(1, metaprojectAssignments.getMaterials().size());
         assertEquals(1, metaprojectAssignments.getDataSets().size());
@@ -1063,4 +1063,5 @@ public class GeneralInformationServiceTest extends SystemTestCase
         assertTrue(metaprojectAssignments.getExperiments().get(0).isStub());
         assertTrue(metaprojectAssignments.getExperiments().get(0).toString().contains("STUB"));
     }
+
 }
diff --git a/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv b/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv
index 44b2274d4c54b5425ec6b58a724733dc7d1aafa6..23128b4687aefe50394bed7cdcc4644f1ccf6a15 100644
--- a/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv
+++ b/openbis/sourceTest/sql/postgresql/124/043=metaprojects.tsv
@@ -1,3 +1,4 @@
 1	TEST_METAPROJECTS	Example metaproject no. 1	2	t	2012-09-05 10:18:10.581+02
 2	TEST_METAPROJECTS	Example metaproject no. 2	6	t	2012-09-05 10:18:10.581+02
 3	ANOTHER_TEST_METAPROJECTS	Another example metaproject	2	t	2012-09-05 10:18:10.581+02
+4	TEST_METAPROJECTS_2	Example metaproject no. 2	6	t	2012-09-05 10:18:10.581+02
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
index a7c03e8e25117bea0274f806d20cd2d7709aa97e..db64b7dd92dd68b9d99dec07e0fb0145ae3d9d34 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.shared.api.v1;
 import java.util.Map;
 
 import ch.systemsx.cisd.common.api.IRpcService;
+import ch.systemsx.cisd.common.exception.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignmentsIds;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.WebAppSettings;
@@ -87,25 +88,30 @@ public interface IGeneralInformationChangingService extends IRpcService
      * Creates a new metaproject.
      * 
      * @param name Name of the metaproject
-     * @param description Description of the metaproject
+     * @param descriptionOrNull Description of the metaproject
      * @return Newly created metaproject
      * @since 1.3
      */
-    public Metaproject createMetaproject(String sessionToken, String name, String description);
+    public Metaproject createMetaproject(String sessionToken, String name, String descriptionOrNull);
 
     /**
-     * Updates existing metaproject.
+     * Updates an existing metaproject.
      * 
-     * @param metaproject Metaproject that should be updated
+     * @param metaprojectId Id of the metaproject
+     * @param name New name of the metaproject
+     * @param descriptionOrNull New description of the metaproject
      * @return Updated metaproject
+     * @throws UserFailureException when a metaproject with the specified id doesn't exist.
      * @since 1.3
      */
-    public Metaproject updateMetaproject(String sessionToken, Metaproject metaproject);
+    public Metaproject updateMetaproject(String sessionToken, IMetaprojectId metaprojectId,
+            String name, String descriptionOrNull);
 
     /**
      * Deletes existing metaproject.
      * 
      * @param metaprojectId Id of a metaproject to delete
+     * @throws UserFailureException when a metaproject with the specified id doesn't exist.
      * @since 1.3
      */
     public void deleteMetaproject(String sessionToken, IMetaprojectId metaprojectId);
@@ -115,6 +121,7 @@ public interface IGeneralInformationChangingService extends IRpcService
      * 
      * @param metaprojectId Id of a metaproject
      * @param assignmentsToAdd Assignments that should be added to the metaproject
+     * @throws UserFailureException when a metaproject with the specified id doesn't exist.
      * @since 1.3
      */
     public void addToMetaproject(String sessionToken, IMetaprojectId metaprojectId,
@@ -125,6 +132,7 @@ public interface IGeneralInformationChangingService extends IRpcService
      * 
      * @param metaprojectId Id of a metaproject
      * @param assignmentsToRemove Assignments that should be removed from the metaproject
+     * @throws UserFailureException when a metaproject with the specified id doesn't exist.
      * @since 1.3
      */
     public void removeFromMetaproject(String sessionToken, IMetaprojectId metaprojectId,
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
index d6db264582f4ce6c12fe817b474fac72c35bb2f9..a01cbce02440c820f693115a30f26b5c291838d4 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.Set;
 
 import ch.systemsx.cisd.common.api.IRpcService;
+import ch.systemsx.cisd.common.exception.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ControlledVocabularyPropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet.Connections;
@@ -472,6 +473,8 @@ public interface IGeneralInformationService extends IRpcService
 
     /**
      * Returns all entities tagged with given metaproject.
+     * 
+     * @throws UserFailureException when a metaproject with the specified id doesn't exist.
      */
     public MetaprojectAssignments getMetaproject(String sessionToken, IMetaprojectId metaprojectId);
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/IObjectId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/IObjectId.java
index a4807b15f6e1977c4e7e6719f71e8b5fdc60a5d4..021013baa879878f17d07e55c5b69114d6f4b049 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/IObjectId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/IObjectId.java
@@ -21,6 +21,8 @@ import java.io.Serializable;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
+ * Holds information that uniquely identifies an object in openBIS.
+ * 
  * @author pkupczyk
  */
 @JsonObject("IObjectId")
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectIdentifierId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectIdentifierId.java
index 98c4080c2c54327fee05d2a55560a9cd3c3350e3..6001a9eeab148e78eb38d1da86922da3f81521a9 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectIdentifierId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectIdentifierId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Base class for ids that identify objects by identifier.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ObjectIdentifierId")
@@ -57,4 +59,10 @@ public abstract class ObjectIdentifierId implements IObjectId
         this.identifier = identifier;
     }
 
+    @Override
+    public String toString()
+    {
+        return getIdentifier();
+    }
+
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectPermIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectPermIdId.java
index 6d67a550798289a93c38762af570caf1699c6814..4d81764575b5d2fddfcde019ece96a7e4ec3bd08 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectPermIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectPermIdId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Base class for ids that identify objects by perm id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ObjectPermIdId")
@@ -57,4 +59,10 @@ public abstract class ObjectPermIdId implements IObjectId
         this.permId = permId;
     }
 
+    @Override
+    public String toString()
+    {
+        return getPermId();
+    }
+
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectTechIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectTechIdId.java
index b0c296f07052f93d1f0219afe2443983a7f05d9d..d18ff2ed4218bc3744a9c9a1979c2e4ceaf2d2c5 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectTechIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/ObjectTechIdId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Base class for ids that identify objects by tech id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ObjectTechIdId")
@@ -57,4 +59,10 @@ public abstract class ObjectTechIdId implements IObjectId
         this.techId = techId;
     }
 
+    @Override
+    public String toString()
+    {
+        return getTechId().toString();
+    }
+
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetCodeId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetCodeId.java
index 9909ba8d5d95b3969a51bf20bad85ad86ed77b52..c5a1ff6170f31d73dd4110b93f3d09d5a52143cd 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetCodeId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetCodeId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a data set by code.
+ * 
  * @author pkupczyk
  */
 @JsonObject("DataSetCodeId")
@@ -30,6 +32,9 @@ public class DataSetCodeId implements IDataSetId
 
     private String code;
 
+    /**
+     * @param code Data set code, e.g "201108050937246-1031".
+     */
     public DataSetCodeId(String code)
     {
         setCode(code);
@@ -58,4 +63,10 @@ public class DataSetCodeId implements IDataSetId
         this.code = code;
     }
 
+    @Override
+    public String toString()
+    {
+        return getCode();
+    }
+
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetTechIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetTechIdId.java
index 79aebad4d7d6263a2c3431bc34dfabc488c7f33e..a164449ab10b8dd68182af8bc27ae8d02a67b291 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetTechIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/DataSetTechIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a data set by tech id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("DataSetTechIdId")
@@ -29,6 +31,9 @@ public class DataSetTechIdId extends ObjectTechIdId implements IDataSetId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param techId Data set tech id.
+     */
     public DataSetTechIdId(Long techId)
     {
         super(techId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/IDataSetId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/IDataSetId.java
index 9c461a6c38482375655c6f76dd2d084d0b20ca9b..4aba633f1cb855d694b7aa70a176bcf9d0068d47 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/IDataSetId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/dataset/IDataSetId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.IObjectId;
 
 /**
+ * Holds information that uniquely identifies a data set in openBIS.
+ * 
  * @author pkupczyk
  */
 @JsonObject("IDataSetId")
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentIdentifierId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentIdentifierId.java
index 479ef277b432fe91f70ebea6303df02183a6836e..50a3f7102bf7e7bb235f0372355296131ff8ea21 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentIdentifierId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentIdentifierId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectIdentifierId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies an experiment by identifier.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ExperimentIdentifierId")
@@ -29,6 +31,9 @@ public class ExperimentIdentifierId extends ObjectIdentifierId implements IExper
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param identifier Experiment identifier, e.g. "/MY_SPACE/MY_PROJECT/MY_EXPERIMENT".
+     */
     public ExperimentIdentifierId(String identifier)
     {
         super(identifier);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentPermIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentPermIdId.java
index da5ab99dc14bc01ddfa831df738417e421f53af2..8ccf324dbed680f9a111e66d95f9e3bb8551ce03 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentPermIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentPermIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectPermIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies an experiment by perm id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ExperimentPermIdId")
@@ -29,6 +31,9 @@ public class ExperimentPermIdId extends ObjectPermIdId implements IExperimentId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param permId Experiment perm id, e.g. "201108050937246-1031".
+     */
     public ExperimentPermIdId(String permId)
     {
         super(permId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentTechIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentTechIdId.java
index 549ad3fd5d9722449284a5a0c168d12bf14572db..4b8f04dcc36b2f5a30caceea8ee7132ad8c6731e 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentTechIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/ExperimentTechIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies an experiment by tech id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ExperimentTechIdId")
@@ -29,6 +31,9 @@ public class ExperimentTechIdId extends ObjectTechIdId implements IExperimentId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param techId Experiment tech id.
+     */
     public ExperimentTechIdId(Long techId)
     {
         super(techId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/IExperimentId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/IExperimentId.java
index f8986bf63138fc69b373fcc0092fd61da94e1085..828d6ccc62799e59983365868aee030651b90869 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/IExperimentId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/experiment/IExperimentId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.IObjectId;
 
 /**
+ * Holds information that uniquely identifies an experiment in openBIS.
+ * 
  * @author pkupczyk
  */
 @JsonObject("IExperimentId")
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/IMaterialId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/IMaterialId.java
index 981a6bb880d5409c84d96a8e83d346e18bbe25de..373f05c53eaf0909619d0b732a1f88f7364bf0eb 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/IMaterialId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/IMaterialId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.IObjectId;
 
 /**
+ * Holds information that uniquely identifies a material in openBIS.
+ * 
  * @author pkupczyk
  */
 @JsonObject("IMaterialId")
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialCodeAndTypeCodeId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialCodeAndTypeCodeId.java
index fafc1dc66160af9d8b9d7080646d369c762f06d1..995d31210a55a96b599eb9f848c05aea57509182 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialCodeAndTypeCodeId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialCodeAndTypeCodeId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a material by code and material type code.
+ * 
  * @author pkupczyk
  */
 @JsonObject("MaterialCodeAndTypeCodeId")
@@ -32,6 +34,10 @@ public class MaterialCodeAndTypeCodeId implements IMaterialId
 
     private String typeCode;
 
+    /**
+     * @param code Material code
+     * @param typeCode Material type code
+     */
     public MaterialCodeAndTypeCodeId(String code, String typeCode)
     {
         setCode(code);
@@ -75,4 +81,10 @@ public class MaterialCodeAndTypeCodeId implements IMaterialId
         this.typeCode = typeCode;
     }
 
+    @Override
+    public String toString()
+    {
+        return getCode() + " (" + getTypeCode() + ")";
+    }
+
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialTechIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialTechIdId.java
index 4784d700add878fec67614a51c6242e786d3c639..a395edf68dfe0b36e965271bd9ef475208ea6a5a 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialTechIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/material/MaterialTechIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a material by tech id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("MaterialTechIdId")
@@ -29,6 +31,9 @@ public class MaterialTechIdId extends ObjectTechIdId implements IMaterialId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param techId Material tech id.
+     */
     public MaterialTechIdId(Long techId)
     {
         super(techId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/IMetaprojectId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/IMetaprojectId.java
index f0396b6d85eba666ce12ff16dabac573461749b6..6ccbcd3b2e175a6bfd54b5cb7b675d63644d9ec9 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/IMetaprojectId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/IMetaprojectId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.IObjectId;
 
 /**
+ * Holds information that uniquely identifies a metaproject in openBIS.
+ * 
  * @author pkupczyk
  */
 @JsonObject("IMetaprojectId")
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectIdentifierId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectIdentifierId.java
index 1daab2ec1b0103a35b55f87fb050b2ab501c65fa..f73c9393d90f7c4588d2e9876c2fed6f06cdaf3b 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectIdentifierId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectIdentifierId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectIdentifierId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a metaproject by identifier.
+ * 
  * @author pkupczyk
  */
 @JsonObject("MetaprojectIdentifierId")
@@ -29,6 +31,9 @@ public class MetaprojectIdentifierId extends ObjectIdentifierId implements IMeta
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param identifier Metaproject identifier, e.e. "/MY_USER/MY_METAPROJECT".
+     */
     public MetaprojectIdentifierId(String identifier)
     {
         super(identifier);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectTechIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectTechIdId.java
index 81bd609073dc5322c947278bc08e64febb5772df..d5122930b13433086833b3c7d27f5584dc2f7b87 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectTechIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/metaproject/MetaprojectTechIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a metaproject by tech id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("MetaprojectTechIdId")
@@ -29,6 +31,9 @@ public class MetaprojectTechIdId extends ObjectTechIdId implements IMetaprojectI
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param techId Metaproject tech id.
+     */
     public MetaprojectTechIdId(Long techId)
     {
         super(techId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/ISampleId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/ISampleId.java
index f1baeb8f8b384bc29a526814ad8b761a58bed11b..50b3662ee08f19270682bf54cd905efd4d5745fa 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/ISampleId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/ISampleId.java
@@ -20,6 +20,8 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.IObjectId;
 
 /**
+ * Holds information that uniquely identifies a sample in openBIS.
+ * 
  * @author pkupczyk
  */
 @JsonObject("ISampleId")
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleIdentifierId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleIdentifierId.java
index 11195a88d2bcf64aff359b2bd1a77f55fbb0d12d..997d8914a97b58829ef167b654186012d25f4d38 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleIdentifierId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleIdentifierId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectIdentifierId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a sample by identifier.
+ * 
  * @author pkupczyk
  */
 @JsonObject("SampleIdentifierId")
@@ -29,6 +31,10 @@ public class SampleIdentifierId extends ObjectIdentifierId implements ISampleId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param identifier Sample identifier, e.g. "/MY_SPACE/MY_SAMPLE" (space sample) or
+     *            "/MY_SAMPLE" (shared sample)
+     */
     public SampleIdentifierId(String identifier)
     {
         super(identifier);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SamplePermIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SamplePermIdId.java
index c1f1dedd37803c6f8d6e24c834cb5f8963bac79c..b2e2205ba30a4207fd0eb7fc6ea834a590458c22 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SamplePermIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SamplePermIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectPermIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a sample by perm id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("SamplePermIdId")
@@ -29,6 +31,9 @@ public class SamplePermIdId extends ObjectPermIdId implements ISampleId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param permId Sample perm id, e.g. "201108050937246-1031".
+     */
     public SamplePermIdId(String permId)
     {
         super(permId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleTechIdId.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleTechIdId.java
index 61b3dee41f074dda394fe9610b9dcc7f08a29784..e83b3cee37a2165091a3e11e820188407b2487f2 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleTechIdId.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/id/sample/SampleTechIdId.java
@@ -21,6 +21,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.ObjectTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
+ * Identifies a sample by tech id.
+ * 
  * @author pkupczyk
  */
 @JsonObject("SampleTechIdId")
@@ -29,6 +31,9 @@ public class SampleTechIdId extends ObjectTechIdId implements ISampleId
 
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
+    /**
+     * @param techId Sample tech id.
+     */
     public SampleTechIdId(Long techId)
     {
         super(techId);
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectIdentifier.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectIdentifier.java
index 63099fe4478fd00c4fd1eaa61dc258b02c4dac33..ae156e202a2f72bffb7925ba07196abb1814f1bd 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectIdentifier.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectIdentifier.java
@@ -53,7 +53,7 @@ public class MetaprojectIdentifier implements Serializable
 
     public String format()
     {
-        return metaprojectOwnerId + SEPARATOR + metaprojectName;
+        return SEPARATOR + metaprojectOwnerId + SEPARATOR + metaprojectName;
     }
 
     public static MetaprojectIdentifier parse(String str)
@@ -65,13 +65,13 @@ public class MetaprojectIdentifier implements Serializable
 
         String[] splitted = str.split(SEPARATOR);
 
-        if (splitted.length == 2)
+        if (splitted.length == 3)
         {
-            return new MetaprojectIdentifier(splitted[0], splitted[1]);
+            return new MetaprojectIdentifier(splitted[1], splitted[2]);
         } else
         {
-            throw new IllegalArgumentException("Metaproject identifier must have USER_ID"
-                    + SEPARATOR + "METAPROJECT_NAME format");
+            throw new IllegalArgumentException("Metaproject identifier must have " + SEPARATOR
+                    + "USER_ID" + SEPARATOR + "METAPROJECT_NAME format");
         }
     }