diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java
index 7a32092c032a09f9bce4729565421431ce9d2a94..6d59045873083d11dcf820cda6cf964d63be71d1 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java
@@ -24,7 +24,9 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.AtomicEntityOperationDeta
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetRegistrationInformation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
@@ -52,6 +54,8 @@ public class DefaultEntityOperationService<T extends DataSetInformation> impleme
             AtomicEntityOperationDetails<T> details)
     {
 
+        List<NewSpace> spaceRegistrations = details.getSpaceRegistrations();
+        List<NewProject> projectRegistrations = details.getProjectRegistrations();
         List<NewExperiment> experimentRegistrations = details.getExperimentRegistrations();
         List<SampleUpdatesDTO> sampleUpdates = details.getSampleUpdates();
         List<NewSample> sampleRegistrations = details.getSampleRegistrations();
@@ -64,7 +68,8 @@ public class DefaultEntityOperationService<T extends DataSetInformation> impleme
         }
 
         return new ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails(
-                details.tryUserIdOrNull(), experimentRegistrations, sampleUpdates,
+                details.tryUserIdOrNull(), spaceRegistrations, projectRegistrations,
+                experimentRegistrations, sampleUpdates,
                 sampleRegistrations, dataSetRegistrations);
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java
index 5394b33814486dfd2d18c73820007cbe5483df76..8b26bb1e90dffda3f378b2f8e3da61ca9edafc49 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java
@@ -79,6 +79,35 @@ public interface IDataSetRegistrationTransaction
      */
     IExperiment createNewExperiment(String experimentIdentifierString, String experimentTypeCode);
 
+    /**
+     * Create a new project to register with the openBIS AS.
+     * 
+     * @param projectIdentifier .
+     */
+    IProject createNewProject(String projectIdentifier);
+
+    /**
+     * Get a project from the openBIS AS. Returns null if the project does not exist.
+     * 
+     * @return A project or null
+     */
+    IProjectImmutable getProject(String projectIdentifier);
+
+    /**
+     * Create a new space to register with the openBIS AS.
+     * 
+     * @param spaceCode the code of the space
+     * @param spaceAdminUserId the user id of the person, who will receive space admin priviliges.
+     */
+    ISpace createNewSpace(String spaceCode, String spaceAdminUserId);
+
+    /**
+     * Get a space from the openBIS AS. Returns null if the space does not exist.
+     * 
+     * @return A space or null
+     */
+    ISpaceImmutable getSpace(String spaceCode);
+
     // File operations -- The source and destination paths are local to the incoming data set folder
     // or incoming directory if the data set is just one file
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IProject.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IProject.java
new file mode 100644
index 0000000000000000000000000000000000000000..25182fa9fd1a3edc1a3991a3bb21c288c6d22e71
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IProject.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+public interface IProject extends IProjectImmutable
+{
+    /**
+     * Set the project description.
+     */
+    void setDescription(String description);
+
+    /**
+     * Set the project leader id.
+     */
+    void setProjectLeaderId(String leaderId);
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IProjectImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IProjectImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f04beefadcfafcddec324c07763feaefafd9df6
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IProjectImmutable.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1;
+
+
+/**
+ * @author Kaloyan Enimanev
+ */
+public interface IProjectImmutable
+{
+
+    /**
+     * Return the identifier for this project.
+     */
+    String getProjectIdentifier();
+
+    /**
+     * Return the description for this project.
+     */
+    String getDescription();
+
+    /**
+     * Return the project leader id. May be null.
+     */
+    String getProjectLeaderId();
+
+
+    /**
+     * Return true if the project exists in the database.
+     */
+    boolean isExistingProject();
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/ISpace.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/ISpace.java
new file mode 100644
index 0000000000000000000000000000000000000000..81f84a411ba1f526898bc1871c7e96c898fc128c
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/ISpace.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+public interface ISpace extends ISpaceImmutable
+{
+    /**
+     * Set the space description.
+     */
+    void setDescription(String description);
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/ISpaceImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/ISpaceImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..d05883ec7a3353e6f6dae97d8098d0c64e0efa3c
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/ISpaceImmutable.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1;
+
+/**
+ * An interface for spaces from the database that should not be altered.
+ * 
+ * @author Kaloyan Enimanev
+ */
+public interface ISpaceImmutable
+{
+
+    /**
+     * Return the code for this space.
+     */
+    String getSpaceCode();
+
+    /**
+     * Return the description for this space.
+     */
+    String getDescription();
+
+    /**
+     * Return true if the space exists in the database.
+     */
+    boolean isExistingSpace();
+
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java
index 5111255b263a33f219f72c8cb191f59e76b15771..3b2656c64ec38fc4eb1ff7903758a794267b0094 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java
@@ -29,13 +29,17 @@ import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithmRunner;
 import ch.systemsx.cisd.etlserver.registrator.IDataSetRegistrationDetailsFactory;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSet;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperiment;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.IProject;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.ISample;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.ISpace;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetRegistrationInformation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
@@ -89,6 +93,10 @@ abstract class AbstractTransactionState<T extends DataSetInformation>
 
         private final List<Experiment> experimentsToBeRegistered = new ArrayList<Experiment>();
 
+        private final List<Space> spacesToBeRegistered = new ArrayList<Space>();
+
+        private final List<Project> projectsToBeRegistered = new ArrayList<Project>();
+
         private final List<Sample> samplesToBeRegistered = new ArrayList<Sample>();
 
         private final List<Sample> samplesToBeUpdated = new ArrayList<Sample>();
@@ -202,6 +210,20 @@ abstract class AbstractTransactionState<T extends DataSetInformation>
             return experiment;
         }
 
+        public ISpace createNewSpace(String spaceCode, String spaceAdminUserId)
+        {
+            Space space = new Space(spaceCode, spaceAdminUserId);
+            spacesToBeRegistered.add(space);
+            return space;
+        }
+
+        public IProject createNewProject(String projectIdentifier)
+        {
+            Project project = new Project(projectIdentifier);
+            projectsToBeRegistered.add(project);
+            return project;
+        }
+
         public String moveFile(String src, IDataSet dst)
         {
             File srcFile = new File(src);
@@ -332,6 +354,8 @@ abstract class AbstractTransactionState<T extends DataSetInformation>
                 List<DataSetRegistrationInformation<T>> dataSetRegistrations)
         {
 
+            List<NewSpace> spaceRegistrations = convertSpacesToBeRegistered();
+            List<NewProject> projectRegistrations = convertProjectsToBeRegistered();
             List<NewExperiment> experimentRegistrations = convertExperimentsToBeRegistered();
             List<SampleUpdatesDTO> sampleUpdates = convertSamplesToBeUpdated();
             List<NewSample> sampleRegistrations = convertSamplesToBeRegistered();
@@ -340,12 +364,33 @@ abstract class AbstractTransactionState<T extends DataSetInformation>
             List<ExperimentUpdatesDTO> experimentUpdates = new ArrayList<ExperimentUpdatesDTO>();
 
             AtomicEntityOperationDetails<T> registrationDetails =
-                    new AtomicEntityOperationDetails<T>(getUserId(), experimentUpdates,
+                    new AtomicEntityOperationDetails<T>(getUserId(), spaceRegistrations,
+                            projectRegistrations, experimentUpdates,
                             experimentRegistrations, sampleUpdates, sampleRegistrations,
                             dataSetRegistrations);
             return registrationDetails;
         }
 
+        private List<NewProject> convertProjectsToBeRegistered()
+        {
+            List<NewProject> result = new ArrayList<NewProject>();
+            for (Project apiProject : projectsToBeRegistered)
+            {
+                result.add(ConversionUtils.convertToNewProject(apiProject));
+            }
+            return result;
+        }
+
+        private List<NewSpace> convertSpacesToBeRegistered()
+        {
+            List<NewSpace> result = new ArrayList<NewSpace>();
+            for (Space apiSpace : spacesToBeRegistered)
+            {
+                result.add(ConversionUtils.convertToNewSpace(apiSpace));
+            }
+            return result;
+        }
+
         private List<NewExperiment> convertExperimentsToBeRegistered()
         {
             List<NewExperiment> result = new ArrayList<NewExperiment>();
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java
index c10072102629d899181bc56434bb7b7a1dfadac0..c3740dc01c22f319bd3fea25825aa017fde80a92 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java
@@ -26,7 +26,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 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.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 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.SampleUpdatesDTO;
@@ -125,4 +127,16 @@ public class ConversionUtils
         return data;
     }
 
+    public static NewSpace convertToNewSpace(Space apiSpace)
+    {
+        return new NewSpace(apiSpace.getSpaceCode(), apiSpace.getDescription(),
+                apiSpace.getSpaceAdminUserId());
+    }
+
+    public static NewProject convertToNewProject(Project apiProject)
+    {
+        return new NewProject(apiProject.getProjectIdentifier(), apiProject.getDescription(),
+                apiProject.getProjectLeaderId());
+    }
+
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java
index 756f9e13cb6e23408738e5a46620b928cefdd418..b8eac75a46ef5405675703f23216b2a22855aece 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java
@@ -36,8 +36,12 @@ import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSet;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSetRegistrationTransaction;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperiment;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperimentImmutable;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.IProject;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.IProjectImmutable;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.ISample;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.ISampleImmutable;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.ISpace;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.ISpaceImmutable;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.AbstractTransactionState.CommitedTransactionState;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.AbstractTransactionState.LiveTransactionState;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.AbstractTransactionState.RolledbackTransactionState;
@@ -47,8 +51,11 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetRegistrationInformation;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory;
 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;
 
 /**
  * The implementation of a transaction. This class is designed to be used in one thread.
@@ -224,6 +231,33 @@ public class DataSetRegistrationTransaction<T extends DataSetInformation> implem
                 experimentTypeCode);
     }
 
+    public IProject createNewProject(String projectIdentifier)
+    {
+        return getStateAsLiveState().createNewProject(projectIdentifier);
+    }
+
+    public IProjectImmutable getProject(String projectIdentifierString)
+    {
+        ProjectIdentifier projectIdentifier =
+                new ProjectIdentifierFactory(projectIdentifierString).createIdentifier();
+        ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project projectOrNull =
+                openBisService.tryGetProject(projectIdentifier);
+        return (null == projectOrNull) ? null : new ProjectImmutable(projectOrNull);
+    }
+
+    public ISpace createNewSpace(String spaceCode, String spaceAdminUserId)
+    {
+        return getStateAsLiveState().createNewSpace(spaceCode, spaceAdminUserId);
+    }
+
+    public ISpaceImmutable getSpace(String spaceCode)
+    {
+        SpaceIdentifier spaceIdentifier = new SpaceIdentifier(spaceCode);
+        ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space spaceOrNull =
+                openBisService.tryGetSpace(spaceIdentifier);
+        return (null == spaceOrNull) ? null : new SpaceImmutable(spaceOrNull);
+    }
+
     public String moveFile(String src, IDataSet dst)
     {
         return getStateAsLiveState().moveFile(src, dst);
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Project.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Project.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e7b644108e7783b94876a4cc3c44724b31b58d1
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Project.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1.impl;
+
+import ch.systemsx.cisd.etlserver.registrator.api.v1.IProject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+class Project extends ProjectImmutable implements IProject
+{
+    public Project(String projectIdentifier)
+    {
+        super(new ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project(), false);
+        getProject().setIdentifier(projectIdentifier);
+    }
+
+    public void setDescription(String description)
+    {
+        getProject().setDescription(description);
+    }
+
+    public void setProjectLeaderId(String leaderId)
+    {
+        Person projectLeader = getProject().getProjectLeader();
+        if (projectLeader == null)
+        {
+            projectLeader = new Person();
+            getProject().setProjectLeader(projectLeader);
+        }
+        projectLeader.setUserId(leaderId);
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ProjectImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ProjectImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..678e9fa3f83d5b81c895cea0be202b341d192acf
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ProjectImmutable.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1.impl;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.IProjectImmutable;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+class ProjectImmutable implements IProjectImmutable
+{
+    private final ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project project;
+
+    private final boolean isExistingProject;
+
+    public ProjectImmutable(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project project)
+    {
+        this(project, true);
+    }
+
+    public ProjectImmutable(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project project,
+            boolean isExistingProject)
+    {
+        this.project = project;
+        this.isExistingProject = isExistingProject;
+    }
+
+    public String getProjectIdentifier()
+    {
+        return project.getIdentifier();
+    }
+
+    public boolean isExistingProject()
+    {
+        return isExistingProject;
+    }
+
+    /**
+     * Throw an exception if the project does not exist
+     */
+    protected void checkExists()
+    {
+        if (false == isExistingProject())
+        {
+            throw new UserFailureException("Project does not exist.");
+        }
+    }
+
+    public ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project getProject()
+    {
+        return project;
+    }
+
+    public String getDescription()
+    {
+        return project.getDescription();
+    }
+
+    public String getProjectLeaderId()
+    {
+        return (project.getProjectLeader() != null) ? project.getProjectLeader().getUserId() : null;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Space.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Space.java
new file mode 100644
index 0000000000000000000000000000000000000000..b638716340f9c0aa2b9b895013785058f8a41df4
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Space.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1.impl;
+
+import ch.systemsx.cisd.etlserver.registrator.api.v1.ISpace;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+class Space extends SpaceImmutable implements ISpace
+{
+    public Space(String code, String spaceAdminUserId)
+    {
+        super(new ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space(), false);
+        getSpace().setCode(code);
+        getSpace().setRegistrator(new Person());
+        getSpace().getRegistrator().setUserId(spaceAdminUserId);
+    }
+
+    public void setDescription(String description)
+    {
+        getSpace().setDescription(description);
+    }
+
+    public String getSpaceAdminUserId()
+    {
+        return getSpace().getRegistrator().getUserId();
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SpaceImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SpaceImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..087a5eef7b882c05440b8b983ac7fd72b6d0d97c
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SpaceImmutable.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.etlserver.registrator.api.v1.impl;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.etlserver.registrator.api.v1.ISpaceImmutable;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+class SpaceImmutable implements ISpaceImmutable
+{
+    private final ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space space;
+
+    private final boolean isExistingSpace;
+
+    public SpaceImmutable(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space space)
+    {
+        this(space, true);
+    }
+
+    public SpaceImmutable(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space space,
+            boolean isExistingSpace)
+    {
+        this.space = space;
+        this.isExistingSpace = isExistingSpace;
+
+    }
+
+    public String getSpaceCode()
+    {
+        return space.getCode();
+    }
+
+    public String getDescription()
+    {
+        return space.getDescription();
+    }
+
+    public boolean isExistingSpace()
+    {
+        return isExistingSpace;
+    }
+
+    /**
+     * Throw an exception if the project does not exist
+     */
+    protected void checkExists()
+    {
+        if (false == isExistingSpace())
+        {
+            throw new UserFailureException("Space does not exist.");
+        }
+    }
+
+    public ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space getSpace()
+    {
+        return space;
+    }
+
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
index 7c634a3036eeb07b865bb6554437aa4b6e80ff46..f6f891eab5041988583e82e97a8468bdee57d0a5 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
@@ -49,8 +49,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 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.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -62,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
 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;
 
@@ -142,6 +145,18 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
         return service.tryToGetExperiment(session.getToken(), experimentIdentifier);
     }
 
+    public Space tryGetSpace(SpaceIdentifier spaceIdentifier) throws UserFailureException
+    {
+        assert spaceIdentifier != null : "Unspecified space identifier";
+        return service.tryGetSpace(session.getToken(), spaceIdentifier);
+    }
+
+    public Project tryGetProject(ProjectIdentifier projectIdentifier) throws UserFailureException
+    {
+        assert projectIdentifier != null : "Unspecified project identifier";
+        return service.tryGetProject(session.getToken(), projectIdentifier);
+    }
+
     public List<Sample> listSamples(ListSampleCriteria criteria)
     {
         assert criteria != null : "Unspecifed criteria.";
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
index d8e410257e2ff8867e845c4f0ff8bf20ec152dd9..96d07ee66ccc1a6ff067c28229e75b74917bc715 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
@@ -37,8 +37,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 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.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -50,6 +52,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
 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;
 
@@ -105,6 +108,18 @@ public interface IEncapsulatedOpenBISService
     public Experiment tryToGetExperiment(ExperimentIdentifier experimentIdentifier)
             throws UserFailureException;
 
+    /**
+     * Tries to get the space of specified identifier or <code>null</code> if not found.
+     */
+    @ManagedAuthentication
+    public Space tryGetSpace(SpaceIdentifier spaceIdentifier) throws UserFailureException;
+
+    /**
+     * Tries to get the project of specified identifier or <code>null</code> if not found.
+     */
+    @ManagedAuthentication
+    public Project tryGetProject(ProjectIdentifier projectIdentifier) throws UserFailureException;
+
     /**
      * Gets all sample in accordance to the specified criteria.
      */
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java
index e2ede8cc826eb64b91cc5134dbc5f99fe6e7ada6..97a3896011ceccc3c116252806ae018bb12e6683 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java
@@ -21,7 +21,9 @@ import java.util.ArrayList;
 import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 
@@ -38,6 +40,10 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen
     // The userid on whose behalf the operations are done.
     private final String userIdOrNull;
 
+    private final ArrayList<NewSpace> spaceRegistrations;
+
+    private final ArrayList<NewProject> projectRegistrations;
+
     private final ArrayList<ExperimentUpdatesDTO> experimentUpdates;
 
     private final ArrayList<NewExperiment> experimentRegistrations;
@@ -48,13 +54,16 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen
 
     private final ArrayList<DataSetRegistrationInformation<T>> dataSetRegistrations;
 
-    public AtomicEntityOperationDetails(String userIdOrNull,
+    public AtomicEntityOperationDetails(String userIdOrNull, List<NewSpace> spaceRegistrations,
+            List<NewProject> projectRegistrations,
             List<ExperimentUpdatesDTO> experimentUpdates,
             List<NewExperiment> experimentRegistrations, List<SampleUpdatesDTO> sampleUpdates,
             List<NewSample> sampleRegistrations,
             List<DataSetRegistrationInformation<T>> dataSetRegistrations)
     {
         this.userIdOrNull = userIdOrNull;
+        this.spaceRegistrations = new ArrayList<NewSpace>(spaceRegistrations);
+        this.projectRegistrations = new ArrayList<NewProject>(projectRegistrations);
         this.experimentUpdates = new ArrayList<ExperimentUpdatesDTO>(experimentUpdates);
         this.experimentRegistrations = new ArrayList<NewExperiment>(experimentRegistrations);
         this.sampleUpdates = new ArrayList<SampleUpdatesDTO>(sampleUpdates);
@@ -92,4 +101,15 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen
     {
         return dataSetRegistrations;
     }
+
+    public ArrayList<NewSpace> getSpaceRegistrations()
+    {
+        return spaceRegistrations;
+    }
+
+    public ArrayList<NewProject> getProjectRegistrations()
+    {
+        return projectRegistrations;
+    }
+
 }
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java
index 104b81d00b96d5884d1f3dbc7573829c494e0cf2..4c77907a26804576db5c71b4111150648ad45841 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java
@@ -33,7 +33,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 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.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
@@ -155,7 +157,8 @@ public class EncapsulatedOpenBISServiceTest
         data.setCode("ds1");
         data.setShareId("42");
         final AtomicEntityOperationDetails operationDetails =
-                new AtomicEntityOperationDetails(null, Arrays.<NewExperiment> asList(),
+                new AtomicEntityOperationDetails(null, Arrays.<NewSpace> asList(),
+                        Arrays.<NewProject> asList(), Arrays.<NewExperiment> asList(),
                         Arrays.<SampleUpdatesDTO> asList(), Arrays.<NewSample> asList(),
                         Arrays.asList(data));
         context.checking(new Expectations()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
index 7449565102e0a3c9e262a3693a42156640ea9991..3483d41e8564e0050ac53b3e7cbeb5d4c4160146 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
@@ -37,6 +37,9 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObject
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.SimpleDataSetHelper;
@@ -63,19 +66,24 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletedDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyTypeWithVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SourceType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -95,7 +103,9 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria;
 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.NewRoleAssignment;
 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.PropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
@@ -104,10 +114,14 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory;
 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.dto.properties.EntityKind;
@@ -118,7 +132,9 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator.LoadableFields;
 import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.ExternalDataTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.translator.GroupTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.PersonTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.translator.ProjectTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTermTranslator;
@@ -393,10 +409,17 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET
 
     private SamplePE tryLoadSample(final Session session, SampleIdentifier sampleIdentifier)
     {
+        SamplePE result = null;
         final ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
-        sampleBO.tryToLoadBySampleIdentifier(sampleIdentifier);
-        final SamplePE sample = sampleBO.tryToGetSample();
-        return sample;
+        try
+        {
+            sampleBO.tryToLoadBySampleIdentifier(sampleIdentifier);
+            result = sampleBO.tryToGetSample();
+        } catch (UserFailureException ufe)
+        {
+            // sample does not exist
+        }
+        return result;
     }
 
     private void enrichWithProperties(ExperimentPE experiment)
@@ -945,11 +968,51 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET
         return samplePE;
     }
 
+    public Space tryGetSpace(String sessionToken, SpaceIdentifier spaceIdentifier)
+    {
+
+        Session session = getSession(sessionToken);
+        IGroupBO groupBO = businessObjectFactory.createGroupBO(session);
+        GroupIdentifier identifier =
+                new GroupIdentifier(spaceIdentifier.getDatabaseInstanceCode(),
+                        spaceIdentifier.getSpaceCode());
+        try
+        {
+            groupBO.load(identifier);
+            return GroupTranslator.translate(groupBO.getGroup());
+        } catch (UserFailureException ufe)
+        {
+            // space does not exist
+            return null;
+        }
+
+    }
+
+    public Project tryGetProject(String sessionToken, ProjectIdentifier projectIdentifier)
+    {
+        final Session session = getSession(sessionToken);
+        final IProjectBO bo = businessObjectFactory.createProjectBO(session);
+        try
+        {
+            bo.loadByProjectIdentifier(projectIdentifier);
+            final ProjectPE project = bo.getProject();
+            return ProjectTranslator.translate(project);
+        } catch (UserFailureException ufe)
+        {
+            // project does not exist
+            return null;
+        }
+    }
+
     public AtomicEntityOperationResult performEntityOperations(String sessionToken,
             AtomicEntityOperationDetails operationDetails)
     {
 
-        ArrayList<Experiment> experimentsCreated =
+        List<Space> spacesCreated = createSpaces(sessionToken, operationDetails);
+
+        List<Project> projectsCreated = createProjects(sessionToken, operationDetails);
+
+        List<Experiment> experimentsCreated =
                 createExperiments(sessionToken, operationDetails);
 
         List<Sample> samplesCreated = createSamples(sessionToken, operationDetails);
@@ -958,10 +1021,91 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET
 
         List<ExternalData> dataSetsCreated = createDataSets(sessionToken, operationDetails);
 
-        return new AtomicEntityOperationResult(experimentsCreated, samplesUpdated, samplesCreated,
+        return new AtomicEntityOperationResult(spacesCreated, projectsCreated, experimentsCreated,
+                samplesUpdated, samplesCreated,
                 dataSetsCreated);
     }
 
+    private List<Space> createSpaces(String sessionToken,
+            AtomicEntityOperationDetails operationDetails)
+    {
+        ArrayList<SpacePE> spacePEsCreated = new ArrayList<SpacePE>();
+        List<NewSpace> newSpaces = operationDetails.getSpaceRegistrations();
+        for (NewSpace newSpace : newSpaces)
+        {
+            SpacePE spacePE =
+                    registerSpaceInternal(sessionToken, newSpace,
+                            operationDetails.tryUserIdOrNull());
+            spacePEsCreated.add(spacePE);
+        }
+        return GroupTranslator.translate(spacePEsCreated);
+    }
+
+    private SpacePE registerSpaceInternal(String sessionToken, NewSpace newSpace,
+            String registratorUserIdOrNull)
+    {
+        // create space
+        Session session = getSession(sessionToken);
+        IGroupBO groupBO = businessObjectFactory.createGroupBO(session);
+        groupBO.define(newSpace.getCode(), newSpace.getDescription());
+        if (registratorUserIdOrNull != null)
+        {
+            groupBO.getGroup().setRegistrator(getOrCreatePerson(sessionToken, registratorUserIdOrNull));
+        }
+        groupBO.save();
+        
+        // create ADMIN role assignemnt
+        SpacePE space = groupBO.getGroup();
+        if (newSpace.getSpaceAdminUserId() != null) {
+            IRoleAssignmentTable roleTable = businessObjectFactory.createRoleAssignmentTable(session);
+            NewRoleAssignment assignment = new NewRoleAssignment();
+            SpaceIdentifier spaceIdentifier = new SpaceIdentifier(space.getCode());
+            assignment.setSpaceIdentifier(spaceIdentifier);
+            assignment.setRole(RoleCode.ADMIN);
+            Grantee grantee = Grantee.createPerson(newSpace.getSpaceAdminUserId());
+            assignment.setGrantee(grantee);
+            roleTable.add(assignment);
+            roleTable.save();
+        }
+        return space;
+
+        
+    }
+
+    private List<Project> createProjects(String sessionToken,
+            AtomicEntityOperationDetails operationDetails)
+    {
+        ArrayList<ProjectPE> projectPEsCreated = new ArrayList<ProjectPE>();
+        List<NewProject> newProjects = operationDetails.getProjectRegistrations();
+        for (NewProject newProject : newProjects)
+        {
+            ProjectPE projectPE =
+                    registerProjectInternal(sessionToken, newProject,
+                            operationDetails.tryUserIdOrNull());
+            projectPEsCreated.add(projectPE);
+        }
+        return ProjectTranslator.translate(projectPEsCreated);
+    }
+
+    private ProjectPE registerProjectInternal(String sessionToken, NewProject newProject,
+            String registratorUserIdOrNull)
+    {
+        Session session = getSession(sessionToken);
+        IProjectBO projectBO = businessObjectFactory.createProjectBO(session);
+        ProjectIdentifier identifier =
+                new ProjectIdentifierFactory(newProject.getIdentifier()).createIdentifier();
+        projectBO.define(identifier, newProject.getDescription(),
+                newProject.getLeaderId());
+        if (registratorUserIdOrNull != null)
+        {
+            projectBO.getProject().setRegistrator(
+                    getOrCreatePerson(sessionToken, registratorUserIdOrNull));
+        }
+        projectBO.save();
+
+        return projectBO.getProject();
+    }
+
     private List<Sample> createSamples(String sessionToken,
             AtomicEntityOperationDetails operationDetails)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
index ffc2041a547efccbd390b634306bcdcfb2883736..b66d36ab3546c377e351ca504df5c6ab4e673fd7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
@@ -39,8 +39,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 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.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -57,6 +59,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
+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;
 
@@ -423,4 +426,16 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLServic
         logAccess(sessionToken, "performEntityOperations", "%s", operationDetails);
         return null;
     }
+
+    public Space tryGetSpace(String sessionToken, SpaceIdentifier spaceIdentifier)
+    {
+        logAccess(sessionToken, "tryGetSpace", "%s", spaceIdentifier);
+        return null;
+    }
+
+    public Project tryGetProject(String sessionToken, ProjectIdentifier projectIdentifier)
+    {
+        logAccess(sessionToken, "tryGetProject", "%s", projectIdentifier);
+        return null;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
index fb44cf7d7a06f3ac537954a2497852130050f770..a6e1eca6b9fb416fb65734e05a193ed74e71ab9d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
@@ -31,6 +31,8 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractT
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AtomicOperationsPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.DataSetCodeCollectionPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.DataSetCodePredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ExistingSampleOwnerIdentifierPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ExistingSpaceIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSampleCriteriaPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSamplesByPropertyPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.NewExperimentPredicate;
@@ -57,9 +59,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 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.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -72,6 +76,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
 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;
 
@@ -107,7 +112,7 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
     public Experiment tryToGetExperiment(
             String sessionToken,
-            @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ExperimentIdentifier experimentIdentifier)
+            @AuthorizationGuard(guardClass = ExistingSpaceIdentifierPredicate.class) ExperimentIdentifier experimentIdentifier)
             throws UserFailureException;
 
     /**
@@ -123,7 +128,7 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
     public Sample tryGetSampleWithExperiment(
             final String sessionToken,
-            @AuthorizationGuard(guardClass = SampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier)
+            @AuthorizationGuard(guardClass = ExistingSampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier)
             throws UserFailureException;
 
     /**
@@ -597,9 +602,30 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @DatabaseUpdateModification(value =
         { ObjectKind.SAMPLE, ObjectKind.EXPERIMENT })
     @DatabaseCreateOrDeleteModification(value =
-        { ObjectKind.SAMPLE, ObjectKind.EXPERIMENT, ObjectKind.DATA_SET })
+        { ObjectKind.SPACE, ObjectKind.PROJECT, ObjectKind.SAMPLE, ObjectKind.EXPERIMENT,
+                ObjectKind.DATA_SET })
     public AtomicEntityOperationResult performEntityOperations(
             String sessionToken,
             @AuthorizationGuard(guardClass = AtomicOperationsPredicate.class) AtomicEntityOperationDetails operationDetails);
 
+    /**
+     * Tries to return the space specified by its identifier.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(value =
+        { RoleWithHierarchy.SPACE_ETL_SERVER })
+    public Space tryGetSpace(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = ExistingSpaceIdentifierPredicate.class) SpaceIdentifier spaceIdentifier);
+
+    /**
+     * Tries to return the project specified by its identifier.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(value =
+        { RoleWithHierarchy.SPACE_ETL_SERVER })
+    public Project tryGetProject(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = ExistingSpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractSpacePredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractSpacePredicate.java
index 52abfe3683ba3a81c8acdaba031e804e5295601e..416d545646b37a21b7e340230678f3c26bbe78de 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractSpacePredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AbstractSpacePredicate.java
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009 ETH Zuerich, CISD
+
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,6 +37,18 @@ public abstract class AbstractSpacePredicate<T> extends AbstractDatabaseInstance
 
     protected List<SpacePE> spaces;
 
+    protected boolean okForNonExistentSpaces;
+
+    protected AbstractSpacePredicate()
+    {
+        this(false);
+    }
+
+    protected AbstractSpacePredicate(boolean okForNonExistentSpaces)
+    {
+        this.okForNonExistentSpaces = okForNonExistentSpaces;
+    }
+
     @Override
     public void init(IAuthorizationDataProvider provider)
     {
@@ -57,8 +70,15 @@ public abstract class AbstractSpacePredicate<T> extends AbstractDatabaseInstance
     {
         if (tryFindSpace(databaseInstanceUUID, spaceCodeOrNull) == null)
         {
-            return createError(person, spaceCodeOrNull);
+            if (okForNonExistentSpaces)
+            {
+                return Status.OK;
+            } else
+            {
+                return createError(person, spaceCodeOrNull);
+            }
         }
+
         final boolean matching = isMatching(allowedRoles, databaseInstanceUUID, spaceCodeOrNull);
         if (matching)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AtomicOperationsPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AtomicOperationsPredicate.java
index 228843a5bfff26a1d98e7ad9c4814bd08113b59f..c34e69e685168a6e0a3b704cc84573e521aca5c2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AtomicOperationsPredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/AtomicOperationsPredicate.java
@@ -38,6 +38,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
  */
 public class AtomicOperationsPredicate extends AbstractPredicate<AtomicEntityOperationDetails>
 {
+
     private final NewExperimentPredicate newExperimentPredicate;
 
     private final ExperimentUpdatesPredicate experimentUpdatesPredicate;
@@ -48,7 +49,7 @@ public class AtomicOperationsPredicate extends AbstractPredicate<AtomicEntityOpe
 
     private final SampleOwnerIdentifierPredicate sampleOwnerIdentifierPredicate;
 
-    private final SpaceIdentifierPredicate experimentOwnerIdentifierPredicate;
+    private final ExistingSpaceIdentifierPredicate experimentOwnerIdentifierPredicate;
 
     public AtomicOperationsPredicate()
     {
@@ -56,8 +57,8 @@ public class AtomicOperationsPredicate extends AbstractPredicate<AtomicEntityOpe
         experimentUpdatesPredicate = new ExperimentUpdatesPredicate();
         newSamplePredicate = new NewSamplePredicate();
         sampleUpdatesPredicate = new SampleUpdatesPredicate();
-        sampleOwnerIdentifierPredicate = new SampleOwnerIdentifierPredicate();
-        experimentOwnerIdentifierPredicate = new SpaceIdentifierPredicate();
+        sampleOwnerIdentifierPredicate = new SampleOwnerIdentifierPredicate(true, true);
+        experimentOwnerIdentifierPredicate = new ExistingSpaceIdentifierPredicate();
     }
 
     public void init(IAuthorizationDataProvider provider)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/ExistingSampleOwnerIdentifierPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/ExistingSampleOwnerIdentifierPredicate.java
new file mode 100644
index 0000000000000000000000000000000000000000..71b1d3f6143ae88bd997d2802a423ebc666c4277
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/ExistingSampleOwnerIdentifierPredicate.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.authorization.predicate;
+
+/**
+ * A {@link SampleOwnerIdentifierPredicate} which evaluates to OK if the space does not exist.
+ */
+public final class ExistingSampleOwnerIdentifierPredicate extends SampleOwnerIdentifierPredicate
+{
+
+    public ExistingSampleOwnerIdentifierPredicate()
+    {
+        super(true, true);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/ExistingSpaceIdentifierPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/ExistingSpaceIdentifierPredicate.java
new file mode 100644
index 0000000000000000000000000000000000000000..182813f1bf69bbff46f7ee65a249bdf627adcf88
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/ExistingSpaceIdentifierPredicate.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.authorization.predicate;
+
+
+/**
+ * A {@link SpaceIdentifierPredicate} which evaluates to OK if the space does not exist.
+ * 
+ * @author Kaloyan Enimanev
+ */
+public class ExistingSpaceIdentifierPredicate extends SpaceIdentifierPredicate
+{
+    public ExistingSpaceIdentifierPredicate()
+    {
+        super(true);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewExperimentPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewExperimentPredicate.java
index c0af94c2d2b1e2c5923c93545655b5a911f61a52..d26c780aef2494be1377ac05d62ef5e492fafd3b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewExperimentPredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewExperimentPredicate.java
@@ -31,7 +31,7 @@ public final class NewExperimentPredicate extends
 {
     public NewExperimentPredicate()
     {
-        super(new SpaceIdentifierPredicate());
+        super(new ExistingSpaceIdentifierPredicate());
     }
 
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewSamplePredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewSamplePredicate.java
index ba71bdd66cd6fdc87a5b6f698f063f2b098ad49f..824798fcb79bb2038e9ead7c07ec7f0918b0764c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewSamplePredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/NewSamplePredicate.java
@@ -29,7 +29,7 @@ public final class NewSamplePredicate extends DelegatedPredicate<SampleOwnerIden
 {
     public NewSamplePredicate()
     {
-        super(new SampleOwnerIdentifierPredicate(false));
+        super(new SampleOwnerIdentifierPredicate(false, true));
     }
 
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleOwnerIdentifierPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleOwnerIdentifierPredicate.java
index 8d8897f01c0b76d36986cbbaaa47bec1cb426921..79929218389a29b644e5c94ea188c95fc53fa83a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleOwnerIdentifierPredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleOwnerIdentifierPredicate.java
@@ -29,7 +29,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleOwnerIdentif
  * 
  * @author Christian Ribeaud
  */
-public final class SampleOwnerIdentifierPredicate extends AbstractPredicate<SampleOwnerIdentifier>
+public class SampleOwnerIdentifierPredicate extends AbstractPredicate<SampleOwnerIdentifier>
 {
     private final SpaceIdentifierPredicate spacePredicate;
 
@@ -37,12 +37,17 @@ public final class SampleOwnerIdentifierPredicate extends AbstractPredicate<Samp
 
     public SampleOwnerIdentifierPredicate()
     {
-        this(true);
+        this(true, false);
     }
 
     public SampleOwnerIdentifierPredicate(boolean isReadAccess)
     {
-        spacePredicate = new SpaceIdentifierPredicate();
+        this(isReadAccess, false);
+    }
+
+    public SampleOwnerIdentifierPredicate(boolean isReadAccess, boolean okForNonExistentSpaces)
+    {
+        spacePredicate = new SpaceIdentifierPredicate(okForNonExistentSpaces);
         databaseInstanceIdentifierPredicate = new DatabaseInstanceIdentifierPredicate(isReadAccess);
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SpaceIdentifierPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SpaceIdentifierPredicate.java
index 1144ac5a8c7fd3680a0edaaf1556bd7420183953..619b5b0c8dca62fabfebb893350c8d193aa7b45f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SpaceIdentifierPredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SpaceIdentifierPredicate.java
@@ -36,6 +36,11 @@ public class SpaceIdentifierPredicate extends AbstractSpacePredicate<SpaceIdenti
     {
     }
 
+    public SpaceIdentifierPredicate(boolean okForNonExistentSpaces)
+    {
+        super(okForNonExistentSpaces);
+    }
+
     //
     // AbstractDatabaseInstancePredicate
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewProject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewProject.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ff852ed47afcd4c18f5a01f4a3910c782b43944
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewProject.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+public class NewProject implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private final String identifier;
+
+    private final String description;
+
+    private final String leaderId;
+
+    public NewProject(String identifier, String description, String leaderId)
+    {
+        this.identifier = identifier;
+        this.description = description;
+        this.leaderId = leaderId;
+    }
+
+    public String getIdentifier()
+    {
+        return identifier;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    public String getLeaderId()
+    {
+        return leaderId;
+    }
+
+    @Override
+    public String toString()
+    {
+        return getIdentifier();
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSpace.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSpace.java
new file mode 100644
index 0000000000000000000000000000000000000000..cafaf7a4d3ca04bdb15ecc744454eb4af41bebeb
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSpace.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+public class NewSpace implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private final String code;
+
+    private final String description;
+
+    private final String spaceAdminUserId;
+
+    public NewSpace(String code, String description, String spaceAdminUserId)
+    {
+        this.code = code;
+        this.description = description;
+        this.spaceAdminUserId = spaceAdminUserId;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    public String getSpaceAdminUserId()
+    {
+        return spaceAdminUserId;
+    }
+
+    @Override
+    public String toString()
+    {
+        return getCode();
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java
index 8e8b751a6bb2e0fd71ae30768b76c67e7a6f0c47..a894bbd314b645bcf5bb4e6564144ae8c21d8432 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java
@@ -24,7 +24,9 @@ import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 
 /**
  * An object that captures the state for performing the registration of one or many openBIS entities
@@ -43,6 +45,10 @@ public class AtomicEntityOperationDetails implements Serializable
     // the DSS
     private final ArrayList<ExperimentUpdatesDTO> experimentUpdates;
 
+    private final ArrayList<NewSpace> spaceRegistrations;
+
+    private final ArrayList<NewProject> projectRegistrations;
+
     private final ArrayList<NewExperiment> experimentRegistrations;
 
     private final ArrayList<SampleUpdatesDTO> sampleUpdates;
@@ -51,11 +57,14 @@ public class AtomicEntityOperationDetails implements Serializable
 
     private final ArrayList<NewExternalData> dataSetRegistrations;
 
-    public AtomicEntityOperationDetails(String userIdOrNull,
+    public AtomicEntityOperationDetails(String userIdOrNull, List<NewSpace> spaceRegistrations,
+            List<NewProject> projectRegistrations,
             List<NewExperiment> experimentRegistrations, List<SampleUpdatesDTO> sampleUpdates,
             List<NewSample> sampleRegistrations, List<NewExternalData> dataSetRegistrations)
     {
         this.userIdOrNull = userIdOrNull;
+        this.spaceRegistrations = new ArrayList<NewSpace>(spaceRegistrations);
+        this.projectRegistrations = new ArrayList<NewProject>(projectRegistrations);
         this.experimentUpdates = new ArrayList<ExperimentUpdatesDTO>();
         this.experimentRegistrations = new ArrayList<NewExperiment>(experimentRegistrations);
         this.sampleUpdates = new ArrayList<SampleUpdatesDTO>(sampleUpdates);
@@ -93,11 +102,23 @@ public class AtomicEntityOperationDetails implements Serializable
         return dataSetRegistrations;
     }
 
+    public ArrayList<NewSpace> getSpaceRegistrations()
+    {
+        return spaceRegistrations;
+    }
+
+    public ArrayList<NewProject> getProjectRegistrations()
+    {
+        return projectRegistrations;
+    }
+
     @Override
     public String toString()
     {
         ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
         sb.append("userIdOrNull", userIdOrNull);
+        sb.append("spaceRegistrations", spaceRegistrations);
+        sb.append("projectRegistrations", projectRegistrations);
         sb.append("experimentUpdates", experimentUpdates);
         sb.append("experimentRegistrations", experimentRegistrations);
         sb.append("sampleUpdates", sampleUpdates);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java
index 26b7cd00204faae53da7ea7c65d4bcfbd3f5d90e..af90e30306ac0349b1a93d669b5470847809b5c4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java
@@ -23,7 +23,9 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -36,6 +38,10 @@ public class AtomicEntityOperationResult implements Serializable
     // DSS.
     private final ArrayList<Experiment> experimentsUpdated;
 
+    private final ArrayList<Space> spacesCreated;
+
+    private final ArrayList<Project> projectsCreated;
+
     private final ArrayList<Experiment> experimentsCreated;
 
     private final ArrayList<Sample> samplesUpdated;
@@ -46,14 +52,18 @@ public class AtomicEntityOperationResult implements Serializable
 
     public AtomicEntityOperationResult()
     {
-        this(Collections.<Experiment> emptyList(), Collections.<Sample> emptyList(), Collections
+        this(Collections.<Space> emptyList(), Collections.<Project> emptyList(),
+                Collections.<Experiment> emptyList(), Collections.<Sample> emptyList(), Collections
                 .<Sample> emptyList(), Collections.<ExternalData> emptyList());
     }
 
-    public AtomicEntityOperationResult(List<Experiment> experimentsCreated,
+    public AtomicEntityOperationResult(List<Space> spacesCreated, List<Project> projectsCreated,
+            List<Experiment> experimentsCreated,
             List<Sample> samplesUpdated, List<Sample> samplesCreated,
             List<ExternalData> dataSetsCreated)
     {
+        this.spacesCreated = new ArrayList<Space>(spacesCreated);
+        this.projectsCreated = new ArrayList<Project>(projectsCreated);
         this.experimentsUpdated = new ArrayList<Experiment>();
         this.experimentsCreated = new ArrayList<Experiment>(experimentsCreated);
         this.samplesUpdated = new ArrayList<Sample>(samplesUpdated);
@@ -86,4 +96,14 @@ public class AtomicEntityOperationResult implements Serializable
         return dataSetsCreated;
     }
 
+    public ArrayList<Space> getSpacesCreated()
+    {
+        return spacesCreated;
+    }
+
+    public ArrayList<Project> getProjectsCreated()
+    {
+        return projectsCreated;
+    }
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java
index e03246f202fc43d2e8f4da08c1394f90b1d04227..c27e31ebf28eb667a6a84b5c967a3f7107423e17 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java
@@ -51,7 +51,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 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.NewExperiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewProject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
@@ -961,7 +963,8 @@ public class ETLServiceTest extends AbstractServerTestCase
             });
 
         AtomicEntityOperationDetails details =
-                new AtomicEntityOperationDetails(null, new ArrayList<NewExperiment>(),
+                new AtomicEntityOperationDetails(null, new ArrayList<NewSpace>(),
+                        new ArrayList<NewProject>(), new ArrayList<NewExperiment>(),
                         Collections.singletonList(sampleUpdate),
                         Collections.singletonList(newSample),
                         Collections.singletonList(externalData));
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java
index 856a3f32ee0db3c92b41359a6577731e1d42a2ea..dca2365b3a7d6dae1eec96af98401bf5a8196f9c 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java
@@ -35,6 +35,14 @@ public class AtomicEntityOperationDetailsTest extends AssertJUnit
     @Test
     public void testToString()
     {
+        ArrayList<NewSpace> spaceRegistrations = new ArrayList<NewSpace>();
+        spaceRegistrations.add(new NewSpace("SPACE1", "description", "adminUser1"));
+        spaceRegistrations.add(new NewSpace("SPACE2", "description", "adminUser2"));
+
+        ArrayList<NewProject> projectRegistrations = new ArrayList<NewProject>();
+        projectRegistrations.add(new NewProject("/SPACE/P1", "description", "leaderId1"));
+        projectRegistrations.add(new NewProject("/SPACE/P2", "description", "leaderId2"));
+
         ArrayList<NewExperiment> experimentRegistrations = new ArrayList<NewExperiment>();
         experimentRegistrations.add(new NewExperiment("/SPACE/PROJECT/EXP-ID1", "EXP-TYPE"));
         experimentRegistrations.add(new NewExperiment("/SPACE/PROJECT/EXP-ID2", "EXP-TYPE"));
@@ -55,11 +63,15 @@ public class AtomicEntityOperationDetailsTest extends AssertJUnit
         dataSetRegistrations.add(newExternalData);
 
         AtomicEntityOperationDetails details =
-                new AtomicEntityOperationDetails(null, experimentRegistrations, sampleUpdates,
+                new AtomicEntityOperationDetails(null, spaceRegistrations, projectRegistrations,
+                        experimentRegistrations, sampleUpdates,
                         sampleRegistrations, dataSetRegistrations);
 
         assertEquals(
-                "AtomicEntityOperationDetails[userIdOrNull=<null>,experimentUpdates=[]"
+                "AtomicEntityOperationDetails[userIdOrNull=<null>"
+                        + ",spaceRegistrations=[SPACE1, SPACE2]"
+                        + ",projectRegistrations=[/SPACE/P1, /SPACE/P2]"
+                        + ",experimentUpdates=[]"
                         + ",experimentRegistrations=[/SPACE/PROJECT/EXP-ID1, /SPACE/PROJECT/EXP-ID2]"
                         + ",sampleUpdates=[]"
                         + ",sampleRegistrations=[/SPACE/SAMPLE-ID1, /SPACE/SAMPLE-ID2]"