diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java
index cf175c2a91fe6f32afd7e461773f9b85195246e2..95c32d655760c742eab3610530b145610eba6296 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java
@@ -282,9 +282,7 @@ class PutDataSetExecutor implements IDataSetHandlerRpc
                 break;
             case SAMPLE:
                 SampleIdentifier sampleId = trySampleIdentifier();
-
-                dataSetInfo.setSampleCode(sampleId.getSampleCode());
-                dataSetInfo.setSpaceCode(sampleId.getSpaceLevel().getSpaceCode());
+                dataSetInfo.setSampleIdentifier(sampleId);
                 break;
             case DATA_SET:
                 String dataSetCode = tryGetDataSetCode();
@@ -735,9 +733,7 @@ class PutDataSetExecutor implements IDataSetHandlerRpc
                         break;
                     case SAMPLE:
                         SampleIdentifier sampleId = trySampleIdentifier();
-
-                        dataSetInfo.setSampleCode(sampleId.getSampleCode());
-                        dataSetInfo.setSpaceCode(sampleId.getSpaceLevel().getSpaceCode());
+                        dataSetInfo.setSampleIdentifier(sampleId);
                         break;
                     case DATA_SET:
                         String dataSetCode = tryGetDataSetCode();
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetTopLevelDataSetHandler.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetTopLevelDataSetHandler.java
index ed03cf3d54231437bf2686a3a81c51f7bfc1d17b..ef3d528e22e8b9cbf0b7dc66cac0cb18c78ad80a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetTopLevelDataSetHandler.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetTopLevelDataSetHandler.java
@@ -190,9 +190,7 @@ class PutDataSetTopLevelDataSetHandler
                     break;
                 case SAMPLE:
                     SampleIdentifier sampleId = trySampleIdentifier();
-
-                    dataSetInfo.setSampleCode(sampleId.getSampleCode());
-                    dataSetInfo.setSpaceCode(sampleId.getSpaceLevel().getSpaceCode());
+                    dataSetInfo.setSampleIdentifier(sampleId);
                     break;
                 case DATA_SET:
                     String dataSetCode = tryGetDataSetCode();
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/cifex/CifexDataSetInfoExtractor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/cifex/CifexDataSetInfoExtractor.java
index 95a392bb0b271d44c0938c0c6c1fcc9e4c6dd68e..aaac89863745b5c26cc83e6cf8aaf82048e82a2a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/cifex/CifexDataSetInfoExtractor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/cifex/CifexDataSetInfoExtractor.java
@@ -78,12 +78,7 @@ public class CifexDataSetInfoExtractor implements IDataSetInfoExtractor
         SampleIdentifier sampleIdentifierOrNull = tryGetSampleIdentifier(info);
         if (sampleIdentifierOrNull != null)
         {
-            dataSetInformation.setSampleCode(sampleIdentifierOrNull.getSampleCode());
-            if (sampleIdentifierOrNull.isSpaceLevel())
-            {
-                dataSetInformation.setSpaceCode(sampleIdentifierOrNull.getSpaceLevel()
-                        .getSpaceCode());
-            }
+            dataSetInformation.setSampleIdentifier(sampleIdentifierOrNull);
         } else
         {
             ExperimentIdentifier experimentIdentifier =
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/AbstractTransactionState.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/AbstractTransactionState.java
index 3f1c33ce297f02a604961d0f952fbe8fe34304a6..9dc41318633f751bc7645f9d50163289fb11febf 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/AbstractTransactionState.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/AbstractTransactionState.java
@@ -413,14 +413,23 @@ public abstract class AbstractTransactionState<T extends DataSetInformation>
             {
                 return false;
             }
+            if (sampleIdentifier.isProjectLevel())
+            {
+                ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project projectDTO = sampleDTO.getProject();
+                if (projectDTO == null)
+                {
+                    return false;
+                }
+                ProjectIdentifier project = sampleIdentifier.getProjectLevel();
+                return project.getProjectCode().equals(projectDTO.getCode()) 
+                        && project.getSpaceCode().equals(projectDTO.getSpace().getCode());
+            } 
             if (sampleIdentifier.isSpaceLevel())
             {
                 return sampleIdentifier.getSpaceLevel().getSpaceCode()
                         .equals(sampleDTO.getSpace().getCode());
             }
-            {
-                return sampleDTO.getSpace() == null;
-            }
+            return sampleDTO.getSpace() == null;
         }
 
         public IDataSetUpdatable getDataSetForUpdate(String dataSetCode)
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/DataSet.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/DataSet.java
index 5a02dd5d75c1aa793f3388f1201e0087017e6629..8bc2c309b84df8f88661d833749d2c8a533bf489 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/DataSet.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/DataSet.java
@@ -37,7 +37,6 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.dataset.DataSetCode
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
@@ -165,13 +164,7 @@ public class DataSet<T extends DataSetInformation> extends AbstractDataSetImmuta
             SampleImmutable sample = (SampleImmutable) sampleOrNull;
 
             Sample sampleDTO = sample.getSample();
-            dataSetInformation.setSample(sampleDTO);
-            dataSetInformation.setSampleCode(sampleDTO.getCode());
-            Space space = sampleDTO.getSpace();
-            if (null != space)
-            {
-                dataSetInformation.setSpaceCode(space.getCode());
-            }
+            dataSetInformation.setSampleIdentifier(sampleDTO.getIdentifier());
 
             if (sampleDTO.getExperiment() != null)
             {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/Sample.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/Sample.java
index 4e4b2a6dc9bfe00e5e8885d06d2281ebd181ee74..30dd74af380e9fe48ec4b331391252b375dfd66d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/Sample.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/impl/Sample.java
@@ -26,9 +26,11 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.IExperimentIm
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISampleImmutable;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleBatchUpdateDetails;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
@@ -58,7 +60,17 @@ public class Sample extends SampleImmutable implements ISample
         sample.setCode(sampleIdentifier.getSampleCode());
         String sampleSubCode = sampleIdentifier.getSampleSubCode();
         sample.setSubCode(sampleSubCode);
-        if (sampleIdentifier.isSpaceLevel())
+        if (sampleIdentifier.isProjectLevel())
+        {
+            ProjectIdentifier projectLevel = sampleIdentifier.getProjectLevel();
+            Space space = new Space();
+            space.setCode(projectLevel.getSpaceCode());
+            Project project = new Project();
+            project.setSpace(space);
+            project.setCode(projectLevel.getProjectCode());
+            sample.setSpace(space);
+            sample.setProject(project);
+        } else if (sampleIdentifier.isSpaceLevel())
         {
             Space space = new Space();
             SpaceIdentifier spaceLevel = sampleIdentifier.getSpaceLevel();
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v1/AbstractDataSetRegistrationDetailsFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v1/AbstractDataSetRegistrationDetailsFactory.java
index 7aa93c512c3d3c856787d4f309073382a416db34..9a1774f9f05299d32ba5393875c2cad6943dd719 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v1/AbstractDataSetRegistrationDetailsFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v1/AbstractDataSetRegistrationDetailsFactory.java
@@ -94,8 +94,7 @@ public abstract class AbstractDataSetRegistrationDetailsFactory<T extends DataSe
         SampleIdentifier sampleId = userProvidedDataSetInformationOrNull.getSampleIdentifier();
         if (null != sampleId)
         {
-            dataSetInfo.setSampleCode(sampleId.getSampleCode());
-            dataSetInfo.setSpaceCode(sampleId.getSpaceLevel().getSpaceCode());
+            dataSetInfo.setSampleIdentifier(sampleId);
         }
 
         if (null != userProvidedDataSetInformationOrNull.tryToGetSample())
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v2/AbstractDataSetRegistrationDetailsFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v2/AbstractDataSetRegistrationDetailsFactory.java
index 38739c70c7fd5569ee33b5f037728321f1ae301a..7a2142efad063c4ace4bb3688cb66d104f403e7b 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v2/AbstractDataSetRegistrationDetailsFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/v2/AbstractDataSetRegistrationDetailsFactory.java
@@ -94,8 +94,7 @@ public abstract class AbstractDataSetRegistrationDetailsFactory<T extends DataSe
         SampleIdentifier sampleId = userProvidedDataSetInformationOrNull.getSampleIdentifier();
         if (null != sampleId)
         {
-            dataSetInfo.setSampleCode(sampleId.getSampleCode());
-            dataSetInfo.setSpaceCode(sampleId.getSpaceLevel().getSpaceCode());
+            dataSetInfo.setSampleIdentifier(sampleId);
         }
 
         if (null != userProvidedDataSetInformationOrNull.tryToGetSample())
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractDropboxProcessingPlugin.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractDropboxProcessingPlugin.java
index b4c57d4f0c1ba23e84d9cb4e800dea59e48d4852..db67fc407cdc4318e6214c8e1f5e03bc3a629f94 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractDropboxProcessingPlugin.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractDropboxProcessingPlugin.java
@@ -40,6 +40,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
 
@@ -200,23 +201,35 @@ abstract public class AbstractDropboxProcessingPlugin extends AbstractDatastoreP
 
     private DataSetInformation createDatasetInfo(DatasetDescription dataset)
     {
-        DataSetInformation datasetInfo = new DataSetInformation();
         String datasetTypeCode = dataset.getDataSetTypeCode();
+        String spaceCode = dataset.getSpaceCode();
+        String projectCode = dataset.getProjectCode();
+        String sampleCode = dataset.getSampleCode();
+        String experimentCode = dataset.getExperimentCode();
+        DataSetInformation datasetInfo = new DataSetInformation();
         datasetInfo.setDataSetType(new DataSetType(datasetTypeCode));
-        datasetInfo.setSampleCode(dataset.getSampleCode());
-        datasetInfo.setSpaceCode(dataset.getSpaceCode());
+        datasetInfo.setSampleCode(sampleCode);
+        datasetInfo.setProjectCode(projectCode);
+        datasetInfo.setSpaceCode(spaceCode);
         datasetInfo.setDataSetCode(dataset.getDataSetCode());
-        if (dataset.getExperimentCode() != null)
+        if (experimentCode != null)
         {
-            ExperimentIdentifier expIdent =
-                    new ExperimentIdentifier(dataset.getSpaceCode(), dataset.getProjectCode(),
-                            dataset.getExperimentCode());
+            ExperimentIdentifier expIdent = new ExperimentIdentifier(spaceCode, projectCode, experimentCode);
             datasetInfo.setExperimentIdentifier(expIdent);
         }
-        if (dataset.getSampleCode() != null)
+        if (sampleCode != null)
         {
-            SpaceIdentifier spaceIdentifier = new SpaceIdentifier(dataset.getSpaceCode());
-            datasetInfo.setSampleIdentifier(new SampleIdentifier(spaceIdentifier, dataset.getSampleCode()));
+            SampleIdentifier sampleIdentifier;
+            if (projectCode != null)
+            {
+                ProjectIdentifier projectIdentifier = new ProjectIdentifier(spaceCode, projectCode);
+                sampleIdentifier = new SampleIdentifier(projectIdentifier, sampleCode);
+            } else
+            {
+                SpaceIdentifier spaceIdentifier = new SpaceIdentifier(spaceCode);
+                sampleIdentifier = new SampleIdentifier(spaceIdentifier, sampleCode);
+            }
+            datasetInfo.setSampleIdentifier(sampleIdentifier);
         }
         return datasetInfo;
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetInformation.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetInformation.java
index 61de7ba18d14689dbaf602361a02a67b96637290..cfbe68c1618380cfe407d63dcf348b137a8b8e1f 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetInformation.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetInformation.java
@@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ExtractableData;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
@@ -67,11 +68,8 @@ public class DataSetInformation implements Serializable
      */
     private String instanceUUID;
 
-    /**
-     * The database instance code.
-     */
-    private String instanceCode;
-
+    private String projectCode;
+    
     private String spaceCode;
 
     /** An object that uniquely identifies the experiment. Can be <code>null</code>. */
@@ -252,6 +250,10 @@ public class DataSetInformation implements Serializable
         {
             return null;
         }
+        if (projectCode != null)
+        {
+            return new SampleIdentifier(new ProjectIdentifier(spaceCode, projectCode), sampleCode);
+        }
         if (spaceCode == null)
         {
             return new SampleIdentifier(sampleCode);
@@ -263,13 +265,23 @@ public class DataSetInformation implements Serializable
     /**
      * Sets the sample identifier.
      */
-    public final void setSampleIdentifier(SampleIdentifier sampleIdentifier)
+    public final void setSampleIdentifier(SampleIdentifier sampleIdentifierOrNull)
     {
-        setSampleCode(sampleIdentifier.getSampleCode());
-        final SpaceIdentifier spaceLevel = sampleIdentifier.getSpaceLevel();
-        if (spaceLevel != null)
+        if (sampleIdentifierOrNull != null)
         {
-            setSpaceCode(spaceLevel.getSpaceCode());
+            setSampleCode(sampleIdentifierOrNull.getSampleCode());
+            if (sampleIdentifierOrNull.isProjectLevel())
+            {
+                setProjectCode(sampleIdentifierOrNull.getProjectLevel().getProjectCode());
+                setSpaceCode(sampleIdentifierOrNull.getProjectLevel().getSpaceCode());
+            } else
+            {
+                final SpaceIdentifier spaceLevel = sampleIdentifierOrNull.getSpaceLevel();
+                if (spaceLevel != null)
+                {
+                    setSpaceCode(spaceLevel.getSpaceCode());
+                }
+            }
         }
     }
 
@@ -348,6 +360,16 @@ public class DataSetInformation implements Serializable
         extractableData.setParentDataSetCodes(parentDataSetCodes);
     }
 
+    public String getProjectCode()
+    {
+        return projectCode;
+    }
+
+    public void setProjectCode(String projectCode)
+    {
+        this.projectCode = projectCode;
+    }
+
     public final void setSpaceCode(final String spaceCode)
     {
         this.spaceCode = spaceCode;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleGenericBusinessRules.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleGenericBusinessRules.java
index 47f507f774e48936311f8e2a0135752d8b0902a1..ed5bb218382c20c4718eb52fe2d5ce0bed303aa1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleGenericBusinessRules.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleGenericBusinessRules.java
@@ -45,8 +45,9 @@ public class SampleGenericBusinessRules
         {
             if (child.getSpace() == null)
             {
+                String kind = parent.getProject() == null ? "space" : "project";
                 throwUserFailureException("The database instance sample '%s' "
-                        + "can not be %s the space sample '%s'.", child, parent, childRelationName);
+                        + "can not be %s the " + kind + " sample '%s'.", child, parent, childRelationName);
             }
         }
     }
@@ -60,14 +61,15 @@ public class SampleGenericBusinessRules
         // new identifier of a parent is needed for comparison
         SampleIdentifier parentId = IdentifierHelper.createSampleIdentifier(parent);
 
-        if (parentId.isSpaceLevel())
+        if (parentId.isSpaceLevel() || parentId.isProjectLevel())
         {
+            String kind = parentId.isProjectLevel() ? "project" : "sample";
             for (SamplePE child : children)
             {
                 SampleIdentifier childId = child.getSampleIdentifier();
                 if (childId.isDatabaseInstanceLevel())
                 {
-                    throwUserFailureException("Sample '%s' can not be a space sample because of "
+                    throwUserFailureException("Sample '%s' can not be a space " + kind + " because of "
                             + "a %s database instance sample '%s'.", parent, child,
                             childRelationName);
                 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProvider.java
index 7c353905158da9e12a9d834d60642169dd2de058..3168a99c49bcca42dd92dea1daddf2b712f0540d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProvider.java
@@ -29,9 +29,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
 import ch.systemsx.cisd.openbis.generic.shared.managed_property.EntityLinkElementTranslator;
@@ -117,6 +119,16 @@ public class EntityInformationProvider implements IEntityInformationProvider
 
         return space;
     }
+    
+    private ProjectPE tryGetProjectByCode(String spaceCode, String projectCode)
+    {
+        ProjectPE project = daoFactory.getProjectDAO().tryFindProject(spaceCode, projectCode);
+        if (project == null)
+        {
+            throw new UserFailureException("Project /" + spaceCode + "/" + projectCode + " doesn't exist.");
+        }
+        return project;
+    }
 
     @Override
     public String getSamplePermId(String spaceCode, String sampleCode)
@@ -126,11 +138,27 @@ public class EntityInformationProvider implements IEntityInformationProvider
         return (sample != null) ? sample.getPermId() : null;
     }
 
+    @Override
+    public String getProjectSamplePermId(String spaceCode, String projectCode, String sampleCode)
+    {
+        
+        ProjectPE project = tryGetProjectByCode(spaceCode, projectCode);
+        SamplePE sample = daoFactory.getSampleDAO().tryfindByCodeAndProject(sampleCode, project);
+        return (sample != null) ? sample.getPermId() : null;
+    }
+
     @Override
     public String getSamplePermId(String sampleIdentifier)
     {
         SampleIdentifier identifier = SampleIdentifierFactory.parse(sampleIdentifier);
         String sampleCode = identifier.getSampleCode();
+        if (identifier.isProjectLevel())
+        {
+            ProjectIdentifier projectIdentifier = identifier.getProjectLevel();
+            String spaceCode = projectIdentifier.getSpaceCode();
+            String projectCode = projectIdentifier.getProjectCode();
+            return getProjectSamplePermId(spaceCode, projectCode, sampleCode);
+        }
         if (identifier.isSpaceLevel())
         {
             String spaceCode = identifier.getSpaceLevel().getSpaceCode();
@@ -185,6 +213,19 @@ public class EntityInformationProvider implements IEntityInformationProvider
         return getSamplesPermIds(sample.getParents());
     }
 
+    @Override
+    public List<String> getProjectSampleParentPermIds(String spaceCode, String projectCode, String sampleCode)
+    {
+        ProjectPE project = tryGetProjectByCode(spaceCode, projectCode);
+        SamplePE sample = daoFactory.getSampleDAO().tryfindByCodeAndProject(sampleCode, project);
+        if (sample == null)
+        {
+            throw new UserFailureException("Sample /" + spaceCode + "/" + projectCode + "/" 
+                    + sampleCode + " doesn't exist.");
+        }
+        return getSamplesPermIds(sample.getParents());
+    }
+
     @Override
     public List<String> getSampleParentPermIds(String permId)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/SpaceIdentifierHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/SpaceIdentifierHelper.java
index f30db5b7979ecead93323ee87703477085c0326e..129c04a2bde15ad99d447db272d1104d203ec18a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/SpaceIdentifierHelper.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/util/SpaceIdentifierHelper.java
@@ -16,7 +16,6 @@
 
 package ch.systemsx.cisd.openbis.generic.server.util;
 
-import ch.systemsx.cisd.common.exceptions.InternalErr;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAuthorizationDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISpaceDAO;
@@ -24,15 +23,11 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
-import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.util.SpaceCodeHelper;
 
 /**
  * Some useful identifier methods on the <i>server</i> side.
- * <p>
- * This class is the only place which provides the correct way to resolve {@link DatabaseInstanceIdentifier} into a {@link DatabaseInstancePE}!
- * </p>
  * 
  * @author Franz-Josef Elmer
  */
@@ -44,66 +39,6 @@ public final class SpaceIdentifierHelper
         // Can not be instantiated.
     }
 
-    /**
-     * Class which transforms identifiers to the canonical form. Normalized database identifier always has a code, never UUID. Normalized space
-     * identifier has always space code, even when it is a home space. It also has normalized database identifier.
-     */
-    public static class SpaceIdentifierNormalizer
-    {
-        public static SpaceIdentifierNormalizer create(final IAuthorizationDAOFactory daoFactory,
-                final String homeSpaceCodeOrNull)
-        {
-            return new SpaceIdentifierNormalizer(homeSpaceCodeOrNull);
-        }
-
-        private final String homeSpaceCodeOrNull;
-
-        private SpaceIdentifierNormalizer(final String homeSpaceCodeOrNull)
-        {
-            this.homeSpaceCodeOrNull = homeSpaceCodeOrNull;
-        }
-
-        public final SpaceIdentifier normalize(final SpaceIdentifier identifier)
-        {
-            return SpaceIdentifierHelper.normalize(identifier, homeSpaceCodeOrNull);
-        }
-
-        public final SampleIdentifier normalize(final SampleIdentifier identifier)
-        {
-            return SpaceIdentifierHelper.normalize(identifier, homeSpaceCodeOrNull);
-        }
-    }
-
-    /** Transforms given space identifier to the canonical form. */
-    private final static SpaceIdentifier normalize(final SpaceIdentifier spaceIdentifier,
-            final String homeSpaceCodeOrNull)
-    {
-        String spaceCode = spaceIdentifier.getSpaceCode();
-        if (spaceCode == null)
-        {
-            spaceCode = homeSpaceCodeOrNull;
-        }
-        return new SpaceIdentifier(spaceCode.toUpperCase());
-    }
-
-    /** Transforms given sample identifier to the canonical form. */
-    private final static SampleIdentifier normalize(final SampleIdentifier sampleIdentifier,
-            final String homeSpaceCodeOrNull)
-    {
-        if (sampleIdentifier.isDatabaseInstanceLevel())
-        {
-            return new SampleIdentifier(sampleIdentifier.getSampleCode());
-        } else if (sampleIdentifier.isSpaceLevel())
-        {
-            final SpaceIdentifier spaceIdentifier =
-                    normalize(sampleIdentifier.getSpaceLevel(), homeSpaceCodeOrNull);
-            return new SampleIdentifier(spaceIdentifier, sampleIdentifier.getSampleCode());
-        } else
-        {
-            throw InternalErr.error(sampleIdentifier);
-        }
-    }
-
     /** finds a space in the database for the given identifier */
     public static final SpacePE tryGetSpace(final SpaceIdentifier spaceIdentifier,
             final PersonPE person, final IAuthorizationDAOFactory daoFactory)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/api/IEntityInformationProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/api/IEntityInformationProvider.java
index 161f675ac98407f5a6c1f555552c6ba099ee1548..90b0ebd361331d424d0160c64cd61546426f6aeb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/api/IEntityInformationProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/api/IEntityInformationProvider.java
@@ -36,6 +36,11 @@ public interface IEntityInformationProvider
      */
     String getSamplePermId(String spaceCode, String sampleCode);
 
+    /**
+     * @return permId of project sample specified by given space, project and code, <code>null</code> if such a sample doesn't exist
+     */
+    String getProjectSamplePermId(String spaceCode, String projectCode, String sampleCode);
+    
     /**
      * @return permId of sample specified by given identifier, <code>null</code> if such a sample doesn't exist
      */
@@ -46,6 +51,11 @@ public interface IEntityInformationProvider
      */
     List<String> getSampleParentPermIds(String spaceCode, String sampleCode);
 
+    /**
+     * @return list of permIds of parents of a project sample with given space, project and code
+     */
+    List<String> getProjectSampleParentPermIds(String spaceCode, String projectCode, String sampleCode);
+    
     /**
      * @return list of permIds of parents of a sample with given permId
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
index 154b2df859e39637f7151a723462ea74ea3b50eb..d9b3c41c5c0e7055c36341055eae532aec4db26f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
@@ -125,6 +125,11 @@ public class DataSetTranslator
             {
                 description.setSampleTypeCode(sampleType.getCode());
             }
+            Project project = sample.getProject();
+            if (project != null)
+            {
+                description.setProjectCode(project.getCode());
+            }
             Space space = sample.getSpace();
             if (space != null)
             {
@@ -465,6 +470,11 @@ public class DataSetTranslator
             description.setSampleCode(sample.getCode());
             description.setSampleIdentifier(sample.getIdentifier());
             description.setSampleTypeCode(sample.getSampleType().getCode());
+            ProjectPE project = sample.getProject();
+            if (project != null)
+            {
+                description.setProjectCode(project.getCode());
+            }
             description.setSpaceCode(sample.getSpace().getCode());
         }
         ExperimentPE experiment = dataSet.getExperiment();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/EntityExistenceChecker.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/EntityExistenceChecker.java
index 6f4fd657a58b08f5be145f86e00b77918ef9fd2c..3727c8901bf426c2e4696c92b213253d44adfe0a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/EntityExistenceChecker.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/EntityExistenceChecker.java
@@ -24,6 +24,7 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
@@ -45,6 +46,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
@@ -190,6 +192,19 @@ class EntityExistenceChecker
                                 return sampleDAO.tryFindByCodeAndSpace(sampleCode,
                                         spaceExistenceManager.tryGet(spaceLevel));
                             }
+                            if (identifier.isProjectLevel())
+                            {
+                                ProjectIdentifier projectIdentifier = identifier.getProjectLevel();
+                                IProjectDAO projectDAO = daoFactory.getProjectDAO();
+                                String spaceCode = projectIdentifier.getSpaceCode();
+                                String projectCode = projectIdentifier.getProjectCode();
+                                ProjectPE project = projectDAO.tryFindProject(spaceCode, projectCode);
+                                if (project == null)
+                                {
+                                    return null;
+                                }
+                                return sampleDAO.tryfindByCodeAndProject(sampleCode, project);
+                            }
                             return sampleDAO.tryFindByCodeAndDatabaseInstance(sampleCode);
                         }
                     };
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProviderTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProviderTest.java
index 020226eaaa790b61c4b6074eb6480cd2d0f23895..962ff97e72dfe094732812cd48533b92de976aac 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProviderTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/managed_property/EntityInformationProviderTest.java
@@ -27,7 +27,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
 import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.IEntityLinkElement;
 import ch.systemsx.cisd.openbis.generic.shared.managed_property.structured.ElementFactory;
 
@@ -118,4 +120,108 @@ public class EntityInformationProviderTest extends AbstractBOTest
 
         context.assertIsSatisfied();
     }
+
+    @Test
+    public void testGetProjectSamplePermId()
+    {
+        final SamplePE sample = new SamplePE();
+        final ProjectPE project = new ProjectPE();
+        SpacePE space = new SpacePE();
+        space.setCode("S1");
+        project.setSpace(space);
+        project.setCode("P1");
+        sample.setProject(project);
+        sample.setCode("SAMP1");
+        sample.setPermId("123");
+        context.checking(new Expectations()
+            {
+                {
+                    one(projectDAO).tryFindProject("S1", "P1");
+                    will(returnValue(project));
+
+                    one(sampleDAO).tryfindByCodeAndProject("SAMP1", project);
+                    will(returnValue(sample));
+                }
+            });
+
+        String permId = provider.getProjectSamplePermId("S1", "P1", "SAMP1");
+
+        assertEquals("123", permId);
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testGetProjectSampleByIdentifier()
+    {
+        final SamplePE sample = new SamplePE();
+        final ProjectPE project = new ProjectPE();
+        SpacePE space = new SpacePE();
+        space.setCode("S1");
+        project.setSpace(space);
+        project.setCode("P1");
+        sample.setProject(project);
+        sample.setCode("SAMP1");
+        sample.setPermId("123");
+        context.checking(new Expectations()
+            {
+                {
+                    one(projectDAO).tryFindProject("S1", "P1");
+                    will(returnValue(project));
+
+                    one(sampleDAO).tryfindByCodeAndProject("SAMP1", project);
+                    will(returnValue(sample));
+                }
+            });
+
+        String permId = provider.getSamplePermId("/S1/P1/SAMP1");
+
+        assertEquals("123", permId);
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testGetSpaceSampleByIdentifier()
+    {
+        final SamplePE sample = new SamplePE();
+        final SpacePE space = new SpacePE();
+        space.setCode("S1");
+        sample.setSpace(space);
+        sample.setCode("SAMP1");
+        sample.setPermId("123");
+        context.checking(new Expectations()
+            {
+                {
+                    one(spaceDAO).tryFindSpaceByCode("S1");
+                    will(returnValue(space));
+
+                    one(sampleDAO).tryFindByCodeAndSpace("SAMP1", space);
+                    will(returnValue(sample));
+                }
+            });
+
+        String permId = provider.getSamplePermId("/S1/SAMP1");
+
+        assertEquals("123", permId);
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testGetSharedSampleByIdentifier()
+    {
+        final SamplePE sample = new SamplePE();
+        sample.setCode("SAMP1");
+        sample.setPermId("123");
+        context.checking(new Expectations()
+            {
+                {
+                    one(sampleDAO).tryFindByCodeAndDatabaseInstance("SAMP1");
+                    will(returnValue(sample));
+                }
+            });
+
+        String permId = provider.getSamplePermId("/SAMP1");
+        
+        assertEquals("123", permId);
+        context.assertIsSatisfied();
+    }
 }