From 55f78d74fbfacb4a48cd41b36c4ca1c1adf4179a Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Mon, 14 Sep 2009 13:50:04 +0000
Subject: [PATCH] LMS-1165 server and service method added which retrieves
 experiment for specified experiment identifier, change method names in
 DataSetInformation and add setExperiment()

SVN: 12579
---
 .../AbstractDelegatingStorageProcessor.java   | 11 ++-
 ...DelegatingStorageProcessorWithDropbox.java | 11 ++-
 ...AbstractStrorageProcessorWithUploader.java | 11 ++-
 .../cisd/etlserver/BDSStorageProcessor.java   | 10 +--
 .../cisd/etlserver/CifexStorageProcessor.java | 10 +--
 .../cisd/etlserver/DataStrategyStore.java     | 90 +++++++++++--------
 .../etlserver/DefaultStorageProcessor.java    |  7 +-
 .../cisd/etlserver/IStorageProcessor.java     | 13 ++-
 .../etlserver/TransferredDataSetHandler.java  | 13 ++-
 .../server/EncapsulatedOpenBISService.java    | 32 ++++++-
 .../shared/IEncapsulatedOpenBISService.java   |  8 ++
 .../shared/dto/DataSetInformation.java        | 21 ++---
 ...stractStorageProcessorWithDropboxTest.java |  8 +-
 .../etlserver/BDSStorageProcessorTest.java    | 16 ++--
 .../etlserver/CifexStorageProcessorTest.java  |  6 +-
 .../DefaultStorageProcessorTest.java          | 10 +--
 .../TransferredDataSetHandlerTest.java        | 16 ++--
 17 files changed, 167 insertions(+), 126 deletions(-)

diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessor.java
index 9251d252912..498d563d2ad 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessor.java
@@ -30,7 +30,6 @@ import ch.systemsx.cisd.common.utilities.ClassUtils;
 import ch.systemsx.cisd.common.utilities.ExtendedProperties;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat;
 
 /**
@@ -93,12 +92,12 @@ abstract public class AbstractDelegatingStorageProcessor implements IStorageProc
     // delegation
     //
 
-    public File storeData(final Sample sample, final DataSetInformation dataSetInformation,
-            final ITypeExtractor typeExtractor, final IMailClient mailClient,
-            final File incomingDataSetDirectory, final File rootDir)
+    public File storeData(final DataSetInformation dataSetInformation, final ITypeExtractor typeExtractor,
+            final IMailClient mailClient, final File incomingDataSetDirectory,
+            final File rootDir)
     {
-        return delegate.storeData(sample, dataSetInformation, typeExtractor, mailClient,
-                incomingDataSetDirectory, rootDir);
+        return delegate.storeData(dataSetInformation, typeExtractor, mailClient, incomingDataSetDirectory,
+                rootDir);
     }
 
     public UnstoreDataAction unstoreData(final File incomingDataSetDirectory,
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessorWithDropbox.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessorWithDropbox.java
index 43eb99d2900..fe985f40af0 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessorWithDropbox.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractDelegatingStorageProcessorWithDropbox.java
@@ -25,7 +25,6 @@ import ch.systemsx.cisd.common.filesystem.IFileOperations;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.AbstractDatasetDropboxHandler;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 
 /**
  * Storage processor which is able to create a copy of incoming data for additional processing.
@@ -66,13 +65,13 @@ abstract public class AbstractDelegatingStorageProcessorWithDropbox extends
     //
 
     @Override
-    public final File storeData(final Sample sample, final DataSetInformation dataSetInformation,
-            final ITypeExtractor typeExtractor, final IMailClient mailClient,
-            final File incomingDataSetDirectory, final File rootDir)
+    public final File storeData(final DataSetInformation dataSetInformation, final ITypeExtractor typeExtractor,
+            final IMailClient mailClient, final File incomingDataSetDirectory,
+            final File rootDir)
     {
         File storeData =
-                super.storeData(sample, dataSetInformation, typeExtractor, mailClient,
-                        incomingDataSetDirectory, rootDir);
+                super.storeData(dataSetInformation, typeExtractor, mailClient, incomingDataSetDirectory,
+                        rootDir);
         File originalData = super.tryGetProprietaryData(storeData);
         dropboxHandler.handle(originalData, dataSetInformation);
         return storeData;
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java
index 3a91aa377ed..1a2d01888c6 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java
@@ -21,7 +21,6 @@ import java.util.Properties;
 
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 
 /**
  * Storage processor which uses an {@link IDataSetUploader} after data set has been stored by
@@ -50,13 +49,13 @@ public abstract class AbstractStrorageProcessorWithUploader extends AbstractDele
     }
     
     @Override
-    public File storeData(final Sample sample, final DataSetInformation dataSetInformation,
-            final ITypeExtractor typeExtractor, final IMailClient mailClient,
-            final File incomingDataSetDirectory, final File rootDir)
+    public File storeData(final DataSetInformation dataSetInformation, final ITypeExtractor typeExtractor,
+            final IMailClient mailClient, final File incomingDataSetDirectory,
+            final File rootDir)
     {
         File storeData =
-                super.storeData(sample, dataSetInformation, typeExtractor, mailClient,
-                        incomingDataSetDirectory, rootDir);
+                super.storeData(dataSetInformation, typeExtractor, mailClient, incomingDataSetDirectory,
+                        rootDir);
         File originalData = super.tryGetProprietaryData(storeData);
         uploader.upload(originalData, dataSetInformation);
         return storeData;
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/BDSStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/BDSStorageProcessor.java
index 6f9072ecb7c..cd70428da46 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/BDSStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/BDSStorageProcessor.java
@@ -401,10 +401,9 @@ public final class BDSStorageProcessor extends AbstractStorageProcessor implemen
     //
 
     public final File storeData(
-            final ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample sample,
-            final DataSetInformation dataSetInformation, final ITypeExtractor typeExtractor,
-            final IMailClient mailClient, final File incomingDataSetDirectory,
-            final File rootDirectory)
+            final DataSetInformation dataSetInformation,
+            final ITypeExtractor typeExtractor, final IMailClient mailClient,
+            final File incomingDataSetDirectory, final File rootDirectory)
     {
         checkDataSetInformation(dataSetInformation);
         assert rootDirectory != null : "Root directory can not be null.";
@@ -414,7 +413,8 @@ public final class BDSStorageProcessor extends AbstractStorageProcessor implemen
         dataStructureDir = rootDirectory;
         dataStructureDir.mkdirs();
         dataStructure =
-                createDataStructure(sample.getExperiment(), dataSetInformation, typeExtractor,
+                createDataStructure(dataSetInformation.tryToGetExperiment(),
+                        dataSetInformation, typeExtractor,
                         incomingDataSetDirectory, dataStructureDir);
         final IFormattedData formattedData = dataStructure.getFormattedData();
         if (formattedData instanceof IHCSImageFormattedData)
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java
index c6ab6ca3180..ffafcc2df4c 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java
@@ -35,7 +35,6 @@ import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat;
 
 /**
@@ -85,13 +84,12 @@ public class CifexStorageProcessor extends AbstractStorageProcessor
         return StorageFormat.PROPRIETARY;
     }
 
-    public File storeData(Sample sample, DataSetInformation dataSetInformation,
-            ITypeExtractor typeExtractor, IMailClient mailClient, File incomingDataSetDirectory,
-            File rootDir)
+    public File storeData(DataSetInformation dataSetInformation, ITypeExtractor typeExtractor,
+            IMailClient mailClient, File incomingDataSetDirectory, File rootDir)
     {
         File result =
-                delegate.storeData(sample, dataSetInformation, typeExtractor, mailClient,
-                        incomingDataSetDirectory, rootDir);
+                delegate.storeData(dataSetInformation, typeExtractor, mailClient, incomingDataSetDirectory,
+                        rootDir);
         if (StringUtils.isBlank(keppFileRegex) == false)
         {
             clean(delegate.tryGetProprietaryData(rootDir), keppFileRegex);
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataStrategyStore.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataStrategyStore.java
index 2bd210effbc..601609a3c02 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataStrategyStore.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataStrategyStore.java
@@ -129,54 +129,68 @@ final class DataStrategyStore implements IDataStrategyStore
         {
             return dataStoreStrategies.get(DataStoreStrategyKey.UNIDENTIFIED);
         }
+        ExperimentIdentifier experimentIdentifier = dataSetInfo.getExperimentIdentifier();
         final SampleIdentifier sampleIdentifier = dataSetInfo.getSampleIdentifier();
-        final Sample sample = tryGetSample(sampleIdentifier);
-        final Experiment experiment = (sample == null) ? null : sample.getExperiment();
-        if (experiment == null)
+        if (experimentIdentifier != null)
         {
-            notificationLog.error(createNotificationMessage(dataSetInfo, incomingDataSetPath));
-            return dataStoreStrategies.get(DataStoreStrategyKey.UNIDENTIFIED);
-        } else if (experiment.getInvalidation() != null)
-        {
-            notificationLog.error("Data set for sample '" + sampleIdentifier
-                    + "' can not be registered because experiment '" + experiment.getCode()
-                    + "' has been invalidated.");
-            return dataStoreStrategies.get(DataStoreStrategyKey.UNIDENTIFIED);
-        }
-        dataSetInfo.setSample(sample);
-        final ExperimentIdentifier experimentIdentifier = createExperimentIdentifier(experiment);
-        dataSetInfo.setExperimentIdentifier(experimentIdentifier);
-
-        final IEntityProperty[] properties =
-                limsService.getPropertiesOfTopSampleRegisteredFor(sampleIdentifier);
-        if (properties == null)
+            Experiment experiment = limsService.tryToGetExperiment(experimentIdentifier);
+            if (experiment == null)
+            {
+                notificationLog.error("Unknown experiment identifier '" + experimentIdentifier + "'.");
+                return dataStoreStrategies.get(DataStoreStrategyKey.UNIDENTIFIED);
+            }
+            dataSetInfo.setExperiment(experiment);
+        } else
         {
-            final Person registrator = experiment.getRegistrator();
-            assert registrator != null : "Registrator must be known";
-            final String message = createInvalidSampleCodeMessage(dataSetInfo);
-            final String recipientMail = registrator.getEmail();
-            if (StringUtils.isNotBlank(recipientMail))
+            final Sample sample = tryGetSample(sampleIdentifier);
+            final Experiment experiment = (sample == null) ? null : sample.getExperiment();
+            if (experiment == null)
+            {
+                notificationLog.error(createNotificationMessage(dataSetInfo, incomingDataSetPath));
+                return dataStoreStrategies.get(DataStoreStrategyKey.UNIDENTIFIED);
+            } else if (experiment.getInvalidation() != null)
             {
-                sendEmail(message, experimentIdentifier, recipientMail);
-            } else
+                notificationLog.error("Data set for sample '" + sampleIdentifier
+                        + "' can not be registered because experiment '" + experiment.getCode()
+                        + "' has been invalidated.");
+                return dataStoreStrategies.get(DataStoreStrategyKey.UNIDENTIFIED);
+            }
+            dataSetInfo.setSample(sample);
+            experimentIdentifier = createExperimentIdentifier(experiment);
+            dataSetInfo.setExperimentIdentifier(experimentIdentifier);
+            
+            final IEntityProperty[] properties =
+                limsService.getPropertiesOfTopSampleRegisteredFor(sampleIdentifier);
+            if (properties == null)
             {
-                notificationLog.error("The registrator '" + registrator
-                        + "' has a blank email, sending the following email failed:\n" + message);
+                final Person registrator = experiment.getRegistrator();
+                assert registrator != null : "Registrator must be known";
+                final String message = createInvalidSampleCodeMessage(dataSetInfo);
+                final String recipientMail = registrator.getEmail();
+                if (StringUtils.isNotBlank(recipientMail))
+                {
+                    sendEmail(message, experimentIdentifier, recipientMail);
+                } else
+                {
+                    notificationLog.error("The registrator '" + registrator
+                            + "' has a blank email, sending the following email failed:\n" + message);
+                }
+                operationLog.error(String.format("Incoming data set '%s' claims to "
+                        + "belong to experiment '%s' and sample"
+                        + " identifier '%s', but according to the openBIS server "
+                        + "there is no such sample for this "
+                        + "experiment (it has maybe been invalidated?). We thus consider it invalid.",
+                        incomingDataSetPath, experimentIdentifier, sampleIdentifier));
+                return dataStoreStrategies.get(DataStoreStrategyKey.INVALID);
             }
-            operationLog.error(String.format("Incoming data set '%s' claims to "
-                    + "belong to experiment '%s' and sample"
-                    + " identifier '%s', but according to the openBIS server "
-                    + "there is no such sample for this "
-                    + "experiment (it has maybe been invalidated?). We thus consider it invalid.",
-                    incomingDataSetPath, experimentIdentifier, sampleIdentifier));
-            return dataStoreStrategies.get(DataStoreStrategyKey.INVALID);
+            dataSetInfo.setProperties(properties);
         }
-        dataSetInfo.setProperties(properties);
 
         if (operationLog.isInfoEnabled())
         {
-            operationLog.info("Identified that database knows experiment '" + experimentIdentifier
-                    + "' and sample '" + sampleIdentifier + "'.");
+            operationLog.info("Identified that database knows experiment '"
+                    + experimentIdentifier + "'"
+                    + (sampleIdentifier == null ? "." : " and sample '" + sampleIdentifier + "'."));
         }
         return dataStoreStrategies.get(DataStoreStrategyKey.IDENTIFIED);
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java
index c0ef00e1b17..cde68a619e5 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java
@@ -24,7 +24,6 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat;
 
 /**
@@ -48,9 +47,9 @@ public class DefaultStorageProcessor extends AbstractStorageProcessor
     // AbstractStorageProcessor
     //
 
-    public final File storeData(final Sample sample, final DataSetInformation dataSetInformation,
-            final ITypeExtractor typeExtractor, final IMailClient mailClient,
-            final File incomingDataSetDirectory, final File rootDir)
+    public final File storeData(final DataSetInformation dataSetInformation, final ITypeExtractor typeExtractor,
+            final IMailClient mailClient, final File incomingDataSetDirectory,
+            final File rootDir)
     {
         checkParameters(incomingDataSetDirectory, rootDir);
         File originalDir = getOriginalDirectory(rootDir);
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/IStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/IStorageProcessor.java
index d92ed351ec5..9f219081728 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/IStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/IStorageProcessor.java
@@ -21,7 +21,6 @@ import java.util.Properties;
 
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat;
 
 /**
@@ -45,22 +44,20 @@ public interface IStorageProcessor extends IStoreRootDirectoryHolder
      * Do not try/catch exceptions that could occur here. Preferably let the upper layer handle
      * them.
      * </p>
-     * 
-     * @param sample Sample connected to a dataset, enriched with properties, connected experiment
-     *            and its properties.
      * @param dataSetInformation Information about the data set.
      * @param typeExtractor the {@link ITypeExtractor} implementation.
      * @param mailClient mail client.
      * @param incomingDataSetDirectory folder to store. Do not remove it after the implementation
      *            has finished processing. {@link TransferredDataSetHandler} takes care of this.
      * @param rootDir directory to whom the data will be stored.
+     * 
      * @return folder which contains the stored data. This folder <i>must</i> be below the
      *         <var>rootDir</var>. Never returns <code>null</code> but prefers to throw an exception
      *         in case of unexpected behavior.
      */
-    public File storeData(final Sample sample, final DataSetInformation dataSetInformation,
-            final ITypeExtractor typeExtractor, final IMailClient mailClient,
-            final File incomingDataSetDirectory, final File rootDir);
+    public File storeData(final DataSetInformation dataSetInformation, final ITypeExtractor typeExtractor,
+            final IMailClient mailClient, final File incomingDataSetDirectory,
+            final File rootDir);
 
     /**
      * Instructs the dataset handler what to do with the data in incoming directory if there was an
@@ -80,7 +77,7 @@ public interface IStorageProcessor extends IStoreRootDirectoryHolder
 
     /**
      * Performs a rollback of
-     * {@link #storeData(Sample, DataSetInformation, ITypeExtractor, IMailClient, File, File)} The
+     * {@link #storeData(DataSetInformation, ITypeExtractor, IMailClient, File, File)} The
      * data created in <code>directory</code> will also be removed.
      * <p>
      * Call to this method is safe as implementations should try/catch exceptions that could occur
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java
index 543016e76b4..2e7f006dcb4 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java
@@ -59,7 +59,6 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 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.StorageFormat;
@@ -415,12 +414,11 @@ public final class TransferredDataSetHandler implements IPathHandler, ISelfTesta
          */
         final List<DataSetInformation> registerDataSet()
         {
-            final Sample sample = dataSetInformation.getSample();
             String processorID = typeExtractor.getProcessorType(incomingDataSetFile);
             try
             {
-                registerDataSetAndInitiateProcessing(sample, processorID);
-                logAndNotifySuccessfulRegistration(sample.getExperiment().getRegistrator()
+                registerDataSetAndInitiateProcessing(processorID);
+                logAndNotifySuccessfulRegistration(dataSetInformation.tryToGetExperiment().getRegistrator()
                         .getEmail());
                 if (fileOperations.exists(incomingDataSetFile)
                         && fileOperations.removeRecursivelyQueueing(incomingDataSetFile) == false)
@@ -481,8 +479,7 @@ public final class TransferredDataSetHandler implements IPathHandler, ISelfTesta
         /**
          * Registers the data set.
          */
-        private void registerDataSetAndInitiateProcessing(final Sample sample,
-                final String procedureTypeCode)
+        private void registerDataSetAndInitiateProcessing(final String procedureTypeCode)
         {
             final File markerFile = createProcessingMarkerFile();
             try
@@ -496,8 +493,8 @@ public final class TransferredDataSetHandler implements IPathHandler, ISelfTesta
                 watch.start();
                 NewExternalData data = createExternalData();
                 File dataFile =
-                        storageProcessor.storeData(sample, dataSetInformation, typeExtractor,
-                                mailClient, incomingDataSetFile, baseDirectoryHolder
+                        storageProcessor.storeData(dataSetInformation, typeExtractor, mailClient,
+                                incomingDataSetFile, baseDirectoryHolder
                                         .getBaseDirectory());
                 if (operationLog.isInfoEnabled())
                 {
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 d6cc2dc12d4..dc74a12dc6e 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
@@ -33,6 +33,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;
 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.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
@@ -42,6 +43,7 @@ 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.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.SampleIdentifier;
 
 /**
@@ -175,6 +177,11 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
             authenticate();
         }
     }
+    
+    private Experiment primTryToGetExperiment(ExperimentIdentifier experimentIdentifier)
+    {
+        return service.tryToGetExperiment(sessionToken, experimentIdentifier);
+    }
 
     private final Sample primTryGetSampleWithExperiment(final SampleIdentifier sampleIdentifier)
     {
@@ -184,7 +191,15 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
     private final void primRegisterDataSet(final DataSetInformation dataSetInformation,
             final NewExternalData data)
     {
-        service.registerDataSet(sessionToken, dataSetInformation.getSampleIdentifier(), data);
+        ExperimentIdentifier experimentIdentifier = dataSetInformation.getExperimentIdentifier();
+        if (experimentIdentifier != null)
+        {
+            service.registerDataSet(sessionToken, experimentIdentifier, data);
+        } else
+        {
+            SampleIdentifier sampleIdentifier = dataSetInformation.getSampleIdentifier();
+            service.registerDataSet(sessionToken, sampleIdentifier, data);
+        }
     }
 
     private final IEntityProperty[] primGetPropertiesOfSampleRegisteredFor(
@@ -208,6 +223,21 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
     // IEncapsulatedOpenBISService
     //
 
+    synchronized public Experiment tryToGetExperiment(ExperimentIdentifier experimentIdentifier)
+    {
+        assert experimentIdentifier != null : " Unspecified experiment identifier.";
+        
+        checkSessionToken();
+        try
+        {
+            return primTryToGetExperiment(experimentIdentifier);
+        } catch (InvalidSessionException ex)
+        {
+            authenticate();
+            return primTryToGetExperiment(experimentIdentifier);
+        }
+    }
+    
     synchronized public final Sample tryGetSampleWithExperiment(
             final SampleIdentifier sampleIdentifier)
     {
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 521f32a7aad..ba481bd5e46 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
@@ -23,12 +23,14 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;
 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.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 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.SimpleDataSetInformationDTO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 
 /**
@@ -46,6 +48,12 @@ public interface IEncapsulatedOpenBISService
     public ExternalData tryGetDataSet(final String sessionToken, final String dataSetCode)
             throws UserFailureException;
 
+    /**
+     * Tries to get the experiment of specified identifier or <code>null</code> if not found.
+     */
+    public Experiment tryToGetExperiment(ExperimentIdentifier experimentIdentifier)
+            throws UserFailureException;
+    
     /**
      * Gets a sample with the specified identifier. Sample is enriched with properties and the
      * experiment with properties.
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 ca6db23c3f2..d193444f46c 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
@@ -71,6 +71,8 @@ public class DataSetInformation implements Serializable
 
     /** sample with properties, enriched with connected experiment with properties. */
     private transient Sample sample;
+    
+    private transient Experiment experiment;
 
     private BooleanOrUnknown isCompleteFlag = BooleanOrUnknown.U;
 
@@ -119,7 +121,7 @@ public class DataSetInformation implements Serializable
      */
     public final IEntityProperty[] getProperties()
     {
-        return properties;
+        return properties == null ? new IEntityProperty[0] : properties;
     }
 
     public final void setProperties(final IEntityProperty[] properties)
@@ -166,18 +168,17 @@ public class DataSetInformation implements Serializable
     /**
      * Returns the basic information about the experiment.
      */
-    public Experiment getExperiment()
+    public Experiment tryToGetExperiment()
     {
-        return sample == null ? null : sample.getExperiment();
+        return experiment == null ? (sample == null ? null : sample.getExperiment()) : experiment;
+    }
+    
+    public void setExperiment(Experiment experiment)
+    {
+        this.experiment = experiment;
     }
 
-    /**
-     * NOTE: may be NULL
-     * 
-     * @deprecated remove deprecation when all use cases are rewritten in a NULL safe way
-     */
-    @Deprecated
-    public Sample getSample()
+    public Sample tryToGetSample()
     {
         return sample;
     }
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/AbstractStorageProcessorWithDropboxTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/AbstractStorageProcessorWithDropboxTest.java
index ab3006e0b64..440a20b8f35 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/AbstractStorageProcessorWithDropboxTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/AbstractStorageProcessorWithDropboxTest.java
@@ -53,8 +53,8 @@ public class AbstractStorageProcessorWithDropboxTest extends AbstractFileSystemT
         context.checking(new Expectations()
             {
                 {
-                    one(delegateStorageProcessor).storeData(null, dataSetInfo, null, null,
-                            incomingDirectory, null);
+                    one(delegateStorageProcessor).storeData(dataSetInfo, null, null, incomingDirectory,
+                            null);
                     will(returnValue(incomingDirectory));
 
                     File dropboxIncomingDir = new File(dropboxIncomingDirName);
@@ -77,7 +77,7 @@ public class AbstractStorageProcessorWithDropboxTest extends AbstractFileSystemT
 
         AbstractDelegatingStorageProcessorWithDropbox storageProcessor =
                 new StorageProcessorWithDropboxTest(props, delegateStorageProcessor, fileOperations);
-        storageProcessor.storeData(null, dataSetInfo, null, null, incomingDirectory, null);
+        storageProcessor.storeData(dataSetInfo, null, null, incomingDirectory, null);
 
         context.assertIsSatisfied();
     }
@@ -195,7 +195,7 @@ public class AbstractStorageProcessorWithDropboxTest extends AbstractFileSystemT
         File store = new File(workingDirectory, "store");
         store.mkdirs();
 
-        processor.storeData(null, dataSetInfo, null, null, dataSetFile, store);
+        processor.storeData(dataSetInfo, null, null, dataSetFile, store);
 
         File storeData = new File(store, "original/data.txt");
         assertEquals(true, storeData.exists());
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/BDSStorageProcessorTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/BDSStorageProcessorTest.java
index 04b417dd60c..1b272f635f0 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/BDSStorageProcessorTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/BDSStorageProcessorTest.java
@@ -354,8 +354,8 @@ public final class BDSStorageProcessorTest extends AbstractFileSystemTestCase
         final DataSetInformation dataSetInformation = createDataSetInformation();
         prepareMailClient(format);
         final File dataFile =
-                storageProcessor.storeData(baseSample, dataSetInformation, TYPE_EXTRACTOR,
-                        mailClient, incomingDataSetDirectory, new File(workingDirectory,
+                storageProcessor.storeData(dataSetInformation, TYPE_EXTRACTOR, mailClient,
+                        incomingDataSetDirectory, new File(workingDirectory,
                                 STORE_ROOT_DIR));
         assertEquals(new File(workingDirectory, STORE_ROOT_DIR).getAbsolutePath(), dataFile
                 .getAbsolutePath());
@@ -412,8 +412,8 @@ public final class BDSStorageProcessorTest extends AbstractFileSystemTestCase
         prepareMailClient(format);
         final File storeRootDir = new File(workingDirectory, STORE_ROOT_DIR);
         final File dataStore =
-                storageAdapter.storeData(baseSample, dataSetInformation, TYPE_EXTRACTOR,
-                        mailClient, incomingDirectoryData, storeRootDir);
+                storageAdapter.storeData(dataSetInformation, TYPE_EXTRACTOR, mailClient,
+                        incomingDirectoryData, storeRootDir);
         assertEquals(true, dataStore.isDirectory());
         assertEquals(false, incomingDirectoryData.exists());
         storageAdapter.unstoreData(incomingDirectoryData, storeRootDir, null);
@@ -433,8 +433,8 @@ public final class BDSStorageProcessorTest extends AbstractFileSystemTestCase
         final DataSetInformation dataSetInformation = createDataSetInformation();
         prepareMailClient(format);
         final File storeData =
-                storageProcessor.storeData(baseSample, dataSetInformation, TYPE_EXTRACTOR,
-                        mailClient, incomingDirectoryData, workingDirectory);
+                storageProcessor.storeData(dataSetInformation, TYPE_EXTRACTOR, mailClient,
+                        incomingDirectoryData, workingDirectory);
         final File originalDataSet = storageProcessor.tryGetProprietaryData(storeData);
         assertNotNull(originalDataSet);
         assertEquals(INCOMING_DATA_SET_DIR, originalDataSet.getName());
@@ -462,8 +462,8 @@ public final class BDSStorageProcessorTest extends AbstractFileSystemTestCase
         final DataSetInformation dataSetInformation = createDataSetInformation();
         prepareMailClient(HCSImageFormatV1_0.HCS_IMAGE_1_0);
         final File storeData =
-                storageProcessor.storeData(baseSample, dataSetInformation, TYPE_EXTRACTOR,
-                        mailClient, incomingDirectoryData, workingDirectory);
+                storageProcessor.storeData(dataSetInformation, TYPE_EXTRACTOR, mailClient,
+                        incomingDirectoryData, workingDirectory);
         logRecorder.resetLogContent();
         final File originalDataSet = storageProcessor.tryGetProprietaryData(storeData);
         assertEquals(null, originalDataSet);
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/CifexStorageProcessorTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/CifexStorageProcessorTest.java
index 0b57f1aac60..700569e9887 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/CifexStorageProcessorTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/CifexStorageProcessorTest.java
@@ -68,8 +68,8 @@ public class CifexStorageProcessorTest extends AbstractFileSystemTestCase
         FileUtilities.writeToFile(new File(incomingDataSetDirectory, "read.me"), "hello world");
         final File rootDir = createDirectory("root");
         final File storeData =
-                storageProcessor.storeData(null, null, TYPE_EXTRACTOR, null,
-                        incomingDataSetDirectory, rootDir);
+                storageProcessor.storeData(null, TYPE_EXTRACTOR, null, incomingDataSetDirectory,
+                        rootDir);
         assertEquals(false, incomingDataSetDirectory.exists());
         assertEquals(true, storeData.isDirectory());
         assertEquals(rootDir.getAbsolutePath(), storeData.getAbsolutePath());
@@ -87,7 +87,7 @@ public class CifexStorageProcessorTest extends AbstractFileSystemTestCase
         FileUtilities.writeToFile(incoming, "hello world");
         final File rootDir = createDirectory("root");
         final File storeData =
-                storageProcessor.storeData(null, null, TYPE_EXTRACTOR, null, incoming, rootDir);
+                storageProcessor.storeData(null, TYPE_EXTRACTOR, null, incoming, rootDir);
         assertEquals(false, incoming.exists());
         assertEquals(true, storeData.isDirectory());
         File fileName = new File(rootDir, DefaultStorageProcessor.ORIGINAL_DIR + "/read.me");
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessorTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessorTest.java
index 796dd33234f..324630df94a 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessorTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessorTest.java
@@ -63,7 +63,7 @@ public final class DefaultStorageProcessorTest extends AbstractFileSystemTestCas
         final DefaultStorageProcessor storageProcessor = createStorageProcessor();
         try
         {
-            storageProcessor.storeData(null, null, null, null, null, null);
+            storageProcessor.storeData(null, null, null, null, null);
             fail("Null values not accepted");
         } catch (final AssertionError e)
         {
@@ -73,8 +73,8 @@ public final class DefaultStorageProcessorTest extends AbstractFileSystemTestCas
         FileUtilities.writeToFile(new File(incomingDataSetDirectory, "read.me"), "hello world");
         final File rootDir = createDirectory("root");
         final File storeData =
-                storageProcessor.storeData(null, null, TYPE_EXTRACTOR, null,
-                        incomingDataSetDirectory, rootDir);
+                storageProcessor.storeData(null, TYPE_EXTRACTOR, null, incomingDataSetDirectory,
+                        rootDir);
         assertEquals(false, incomingDataSetDirectory.exists());
         assertEquals(true, storeData.isDirectory());
         assertEquals(rootDir.getAbsolutePath(), storeData.getAbsolutePath());
@@ -108,8 +108,8 @@ public final class DefaultStorageProcessorTest extends AbstractFileSystemTestCas
         File readMeFile = new File(incomingDataSetDirectory, "read.me");
         FileUtilities.writeToFile(readMeFile, "hi");
         final File storeData =
-                storageProcessor.storeData(null, null, TYPE_EXTRACTOR, null,
-                        incomingDataSetDirectory, root);
+                storageProcessor.storeData(null, TYPE_EXTRACTOR, null, incomingDataSetDirectory,
+                        root);
         assertEquals(true, storeData.exists());
         assertEquals(false, incomingDataSetDirectory.exists());
         storageProcessor.unstoreData(incomingDataSetDirectory, root, null);
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java
index 51ec503c86e..c7677e1f263 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java
@@ -560,8 +560,8 @@ public final class TransferredDataSetHandlerTest extends AbstractFileSystemTestC
 
                     allowing(storageProcessor).getStorageFormat();
                     will(returnValue(StorageFormat.BDS_DIRECTORY));
-                    one(storageProcessor).storeData(baseSample, dataSetInformation, typeExtractor,
-                            mailClient, data1, baseDir);
+                    one(storageProcessor).storeData(dataSetInformation, typeExtractor, mailClient,
+                            data1, baseDir);
                     final File finalDataSetPath = new File(baseDir, DATA1_NAME);
                     will(returnValue(finalDataSetPath));
                 }
@@ -602,8 +602,8 @@ public final class TransferredDataSetHandlerTest extends AbstractFileSystemTestC
 
                     allowing(storageProcessor).getStorageFormat();
                     will(returnValue(StorageFormat.BDS_DIRECTORY));
-                    one(storageProcessor).storeData(baseSample, dataSetInformation, typeExtractor,
-                            mailClient, data1, baseDir);
+                    one(storageProcessor).storeData(dataSetInformation, typeExtractor, mailClient,
+                            data1, baseDir);
                     final File finalDataSetPath = new File(baseDir, DATA1_NAME);
                     will(returnValue(finalDataSetPath));
                 }
@@ -696,8 +696,8 @@ public final class TransferredDataSetHandlerTest extends AbstractFileSystemTestC
                     one(typeExtractor).getProcessorType(folder);
                     will(returnValue(EXAMPLE_PROCESSOR_ID));
 
-                    one(storageProcessor).storeData(baseSample, dataSetInformation, typeExtractor,
-                            mailClient, folder, baseDir);
+                    one(storageProcessor).storeData(dataSetInformation, typeExtractor, mailClient,
+                            folder, baseDir);
                     UserFailureException exception =
                             new UserFailureException("Could store data by storage processor");
                     will(throwException(exception));
@@ -755,8 +755,8 @@ public final class TransferredDataSetHandlerTest extends AbstractFileSystemTestC
         context.checking(new Expectations()
             {
                 {
-                    one(storageProcessor).storeData(baseSample, dataSetInformation, typeExtractor,
-                            mailClient, folder, baseDir);
+                    one(storageProcessor).storeData(dataSetInformation, typeExtractor, mailClient,
+                            folder, baseDir);
                     will(returnValue(new File(baseDir, DATA1_NAME)));
 
                     one(limsService).registerDataSet(with(equal(SESSION_TOKEN)),
-- 
GitLab