From bfa79c39620d924a62fbbb967c9a10d8ffb23712 Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Mon, 1 Oct 2012 08:14:59 +0000
Subject: [PATCH] SP-282/BIS-179: Failure of Sample Registration with
 automatically generated codes

SVN: 26862
---
 .../server/EncapsulatedOpenBISService.java    |   6 -
 .../shared/IEncapsulatedOpenBISService.java   |   9 +-
 .../openbis/generic/server/CommonServer.java  |   3 +-
 .../openbis/generic/server/ETLService.java    |  18 +--
 .../generic/server/ETLServiceLogger.java      |   8 --
 .../business/bo/EntityCodeGenerator.java      | 135 ++++++++++++++++++
 .../generic/shared/IETLLIMSService.java       |   8 --
 .../plugin/generic/server/GenericServer.java  |   9 +-
 .../systemtest/CodeGenerationTest.java        |  76 ++++++++--
 ...DataSetInfoExtractorForProteinResults.java |  52 ++++---
 ...SetInfoExtractorForProteinResultsTest.java |  58 ++++----
 11 files changed, 271 insertions(+), 111 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityCodeGenerator.java

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 4d0b6e9348e..21908a7ec16 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
@@ -439,12 +439,6 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
         return service.drawANewUniqueID(session.getSessionToken());
     }
 
-    @Override
-    public long drawANewUniqueID(EntityKind entityKind)
-    {
-        return service.drawANewUniqueID(session.getSessionToken(), entityKind);
-    }
-
     @Override
     public ExternalData tryGetDataSet(String dataSetCode) throws UserFailureException
     {
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 680b8a014ae..a6bd6e16471 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
@@ -313,13 +313,6 @@ public interface IEncapsulatedOpenBISService
     @ManagedAuthentication
     public long drawANewUniqueID();
 
-    /**
-     * Creates a new unique ID for the specified entity kind. It is guaranteed to be unique for that
-     * entity kind.
-     */
-    @ManagedAuthentication
-    public long drawANewUniqueID(EntityKind entityKind);
-    
     /**
      * Creates a list of specified size with new unique ID for the specified entity kind.
      */
@@ -409,7 +402,7 @@ public interface IEncapsulatedOpenBISService
      */
     @ManagedAuthentication
     public SessionContextDTO tryGetSession(String sessionToken);
-    
+
     /**
      * See @{link {@link IETLLIMSService#checkSession(String)}.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 5471b45a67b..dad0ccd151b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -80,6 +80,7 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SampleVal
 import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SpaceValidator;
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.DataAccessExceptionTranslator;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.EntityCodeGenerator;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.EntityTypeBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IAttachmentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IAuthorizationGroupBO;
@@ -2046,7 +2047,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
     public String generateCode(String sessionToken, String prefix, EntityKind entityKind)
     {
         checkSession(sessionToken);
-        return prefix + getDAOFactory().getCodeSequenceDAO().getNextCodeSequenceId(entityKind);
+        return new EntityCodeGenerator(getDAOFactory()).generateCode(prefix, entityKind);
     }
 
     @Override
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 fc548f5534c..95a8432b189 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
@@ -73,6 +73,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.IDataStoreServiceFactory
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
 import ch.systemsx.cisd.openbis.generic.server.business.IServiceConversationClientManagerLocal;
 import ch.systemsx.cisd.openbis.generic.server.business.IServiceConversationServerManagerLocal;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.EntityCodeGenerator;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataSetTable;
@@ -371,16 +372,6 @@ public class ETLService extends AbstractCommonServer<IETLLIMSService> implements
         return daoFactory.getCodeSequenceDAO().getNextCodeSequenceId();
     }
 
-    @Override
-    @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
-    public long drawANewUniqueID(String sessionToken,
-            ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind entityKind)
-            throws UserFailureException
-    {
-        checkSession(sessionToken);
-        return daoFactory.getCodeSequenceDAO().getNextCodeSequenceId(entityKind);
-    }
-
     @Override
     @RolesAllowed(
         { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER })
@@ -1154,12 +1145,7 @@ public class ETLService extends AbstractCommonServer<IETLLIMSService> implements
             ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind entityKind, int number)
     {
         checkSession(sessionToken);
-        ArrayList<String> result = new ArrayList<String>();
-        for (int i = 0; i < number; i++)
-        {
-            result.add(prefix + daoFactory.getCodeSequenceDAO().getNextCodeSequenceId(entityKind));
-        }
-        return result;
+        return new EntityCodeGenerator(daoFactory).generateCodes(prefix, entityKind, number);
     }
 
     @Override
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 947bb398f80..8739e429b87 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
@@ -102,14 +102,6 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLLIMSSe
         return 0;
     }
 
-    @Override
-    public long drawANewUniqueID(String sessionToken, EntityKind entityKind)
-            throws UserFailureException
-    {
-        logTracking(sessionToken, "drawANewUniqueID", "ENTITY_KIND(%s)", entityKind);
-        return 0;
-    }
-
     @Override
     public DatabaseInstance getHomeDatabaseInstance(String sessionToken)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityCodeGenerator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityCodeGenerator.java
new file mode 100644
index 00000000000..8b2ebe4d21b
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityCodeGenerator.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 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.server.business.bo;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.lemnik.eodsql.BaseQuery;
+import net.lemnik.eodsql.QueryTool;
+import net.lemnik.eodsql.Select;
+
+import ch.systemsx.cisd.openbis.generic.server.business.bo.common.DatabaseContextUtils;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.dto.TableNames;
+
+/**
+ * Generates unique codes for openBIS entities. It uses database sequences as a base for the code
+ * generation. Moreover it verifies that the generated codes are in fact unique (i.e. entities with
+ * such codes do not exist yet). If it finds that the new generated code is already used by an
+ * existing entity (e.g. the entity code was manually entered by a user) then it regenerates the
+ * code until it is unique.
+ * 
+ * @author pkupczyk
+ */
+public class EntityCodeGenerator
+{
+
+    private IDAOFactory daoFactory;
+
+    private Query query;
+
+    public EntityCodeGenerator(IDAOFactory daoFactory)
+    {
+        this.daoFactory = daoFactory;
+    }
+
+    public String generateCode(String codePrefix, EntityKind entityKind)
+    {
+        return generateCodes(codePrefix, entityKind, 1).get(0);
+    }
+
+    /**
+     * Generate unique codes for openBIS entities.
+     * 
+     * @param codePrefix Prefix for the generated codes (e.g. when "ABC-" then codes will be
+     *            "ABC-1", "ABC-2", ...)
+     * @param entityKind Kind of an entity the codes should be generated for (different kinds of
+     *            entities use different database sequences).
+     * @param numberOfCodes Number of codes to be generated.
+     */
+    public List<String> generateCodes(String codePrefix, EntityKind entityKind, int numberOfCodes)
+    {
+        String[] codes = new String[numberOfCodes];
+
+        query = QueryTool.getQuery(DatabaseContextUtils.getConnection(daoFactory), Query.class);
+
+        for (int i = 0; i < numberOfCodes; i++)
+        {
+            long sequenceValue;
+            String code;
+
+            do
+            {
+                sequenceValue = daoFactory.getCodeSequenceDAO().getNextCodeSequenceId(entityKind);
+                code = codePrefix + sequenceValue;
+
+            } while (isCodeUsed(code, entityKind));
+
+            codes[i] = code;
+        }
+
+        return Arrays.asList(codes);
+    }
+
+    private boolean isCodeUsed(String code, EntityKind entityKind)
+    {
+        int count;
+
+        if (EntityKind.EXPERIMENT.equals(entityKind))
+        {
+            count = query.getExperimentCount(code);
+        } else if (EntityKind.SAMPLE.equals(entityKind))
+        {
+            count = query.getSampleCount(code);
+        } else if (EntityKind.DATA_SET.equals(entityKind))
+        {
+            count = query.getDataSetCount(code);
+        } else if (EntityKind.MATERIAL.equals(entityKind))
+        {
+            count = query.getMaterialsCount(code);
+        } else
+        {
+            throw new IllegalArgumentException("Unsupported entity kind: " + entityKind);
+        }
+
+        return count > 0;
+    }
+
+    private interface Query extends BaseQuery
+    {
+
+        public final static String PREFIX = "SELECT count(*) FROM ";
+
+        public final static String SUFFIX = " WHERE code = ?{1}";
+
+        @Select(sql = PREFIX + TableNames.EXPERIMENTS_ALL_TABLE + SUFFIX)
+        public int getExperimentCount(String code);
+
+        @Select(sql = PREFIX + TableNames.SAMPLES_ALL_TABLE + SUFFIX)
+        public int getSampleCount(String code);
+
+        @Select(sql = PREFIX + TableNames.DATA_ALL_TABLE + SUFFIX)
+        public int getDataSetCount(String code);
+
+        @Select(sql = PREFIX + TableNames.MATERIALS_TABLE + SUFFIX)
+        public int getMaterialsCount(String code);
+
+    }
+
+}
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 93444f92c7e..a35af5f43d8 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
@@ -331,14 +331,6 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @Transactional
     public long drawANewUniqueID(String sessionToken) throws UserFailureException;
 
-    /**
-     * Draw a new unique ID for the specified entity kind. The returned value is guaranteed to be
-     * unique.
-     */
-    @Transactional
-    public long drawANewUniqueID(String sessionToken, EntityKind entityKind)
-            throws UserFailureException;
-
     /**
      * Lists samples codes filtered by specified criteria, see {@link ListSamplesByPropertyCriteria}
      * to see the details.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
index 4c43ca49159..128f1f42f2e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
@@ -56,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.UpdatedEx
 import ch.systemsx.cisd.openbis.generic.server.batch.BatchOperationExecutor;
 import ch.systemsx.cisd.openbis.generic.server.batch.IBatchOperation;
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.EntityCodeGenerator;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
@@ -698,13 +699,7 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
             ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind entityKind, int number)
     {
         checkSession(sessionToken);
-        ArrayList<String> result = new ArrayList<String>();
-        for (int i = 0; i < number; i++)
-        {
-            result.add(prefix
-                    + getDAOFactory().getCodeSequenceDAO().getNextCodeSequenceId(entityKind));
-        }
-        return result;
+        return new EntityCodeGenerator(getDAOFactory()).generateCodes(prefix, entityKind, number);
     }
 
     @Override
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CodeGenerationTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CodeGenerationTest.java
index 6fbcc453e50..777a1dfd557 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CodeGenerationTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/CodeGenerationTest.java
@@ -18,10 +18,13 @@ package ch.systemsx.cisd.openbis.systemtest;
 
 import static org.testng.AssertJUnit.assertEquals;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
+import junit.framework.Assert;
+
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -44,9 +47,24 @@ public class CodeGenerationTest extends SystemTestCase
     @BeforeMethod
     public void setSequences()
     {
-        simpleJdbcTemplate.queryForLong("select setval('code_seq', 8)");
-        simpleJdbcTemplate.queryForLong("select setval('experiment_code_seq', 100)");
-        simpleJdbcTemplate.queryForLong("select setval('sample_code_seq', 200)");
+        setCodeSequence(8);
+        setExperimentCodeSequence(100);
+        setSampleCodeSequence(200);
+    }
+
+    private void setCodeSequence(int value)
+    {
+        simpleJdbcTemplate.queryForLong("select setval('code_seq', " + value + ")");
+    }
+
+    private void setExperimentCodeSequence(int value)
+    {
+        simpleJdbcTemplate.queryForLong("select setval('experiment_code_seq', " + value + ")");
+    }
+
+    private void setSampleCodeSequence(int value)
+    {
+        simpleJdbcTemplate.queryForLong("select setval('sample_code_seq', " + value + ")");
     }
 
     @Test
@@ -60,6 +78,34 @@ public class CodeGenerationTest extends SystemTestCase
         assertEquals("S-202", commonClientService.generateCode("S-", EntityKind.SAMPLE));
     }
 
+    @Test
+    public void testCommonClientServiceGenerateCodeWhenSomeCodesAreAlreadyUsed()
+    {
+        logIntoCommonClientService();
+
+        // Experiments EXP10 and EXP11 already exist
+        setExperimentCodeSequence(10);
+        assertEquals("EXP12", commonClientService.generateCode("EXP", EntityKind.EXPERIMENT));
+        assertEquals("EXP13", commonClientService.generateCode("EXP", EntityKind.EXPERIMENT));
+
+        // Samples A10 .. A22 already exist
+        setSampleCodeSequence(10);
+        assertEquals("A23", commonClientService.generateCode("A", EntityKind.SAMPLE));
+        assertEquals("A24", commonClientService.generateCode("A", EntityKind.SAMPLE));
+
+        // Materials AD3 and AD5 already exist
+        setCodeSequence(3);
+        assertEquals("AD4", commonClientService.generateCode("AD", EntityKind.MATERIAL));
+        assertEquals("AD6", commonClientService.generateCode("AD", EntityKind.MATERIAL));
+
+        // Data sets 20120628092259000-22 .. 20120628092259000-25 already exist
+        setCodeSequence(22);
+        assertEquals("20120628092259000-26",
+                commonClientService.generateCode("20120628092259000-", EntityKind.DATA_SET));
+        assertEquals("20120628092259000-27",
+                commonClientService.generateCode("20120628092259000-", EntityKind.DATA_SET));
+    }
+
     @Test
     public void testGenericServerGenerateCodes()
     {
@@ -77,11 +123,21 @@ public class CodeGenerationTest extends SystemTestCase
                         .toString());
     }
 
+    @Test(timeOut = 1000)
+    public void testGenericServerGenerateManyCodesWhenSomeCodesAreAlreadyUsed()
+    {
+        setSampleCodeSequence(10);
+        genericServer.generateCodes(systemSessionToken, "A", EntityKind.SAMPLE, 1000);
+    }
+
     @Test
-    public void testETLServiceDrawANewUniqueID()
+    public void testGenericServerGenerateCodesWhenSomeCodesAreAlreadyUsed()
     {
-        assertEquals(9, etlService.drawANewUniqueID(systemSessionToken));
-        assertEquals(201, etlService.drawANewUniqueID(systemSessionToken, EntityKind.SAMPLE));
+        // Samples A10 .. A22 already exist
+        setSampleCodeSequence(10);
+        List<String> codes =
+                genericServer.generateCodes(systemSessionToken, "A", EntityKind.SAMPLE, 5);
+        Assert.assertEquals(Arrays.asList("A23", "A24", "A25", "A26", "A27"), codes);
     }
 
     @Test
@@ -95,11 +151,14 @@ public class CodeGenerationTest extends SystemTestCase
     @Test
     public void testAutomaticCreationOfSampleCodesInBatchSampleRegistration()
     {
+        // Samples A10 .. A22 already exist
+        setSampleCodeSequence(10);
+
         String sessionID = logIntoCommonClientService().getSessionID();
         uploadFile("testAutomaticCreationOfSampleCodesInBatchSampleRegistration.txt",
                 "experiment\tCOMMENT\n" + "/CISD/NEMO/EXP1\tA\n" + "/CISD/NEMO/EXP1\tB\n");
         SampleType sampleType = new SampleType();
-        sampleType.setGeneratedCodePrefix("SAMPLE-");
+        sampleType.setGeneratedCodePrefix("A");
         sampleType.setCode("CELL_PLATE");
 
         genericClientService.registerSamples(sampleType, SESSION_KEY, "/CISD", false);
@@ -124,7 +183,6 @@ public class CodeGenerationTest extends SystemTestCase
             builder.append(sample.getIdentifier()).append(":").append(sample.getProperties());
             builder.append("\n");
         }
-        assertEquals("/CISD/SAMPLE-201:[COMMENT: A]\n" + "/CISD/SAMPLE-202:[COMMENT: B]\n",
-                builder.toString());
+        assertEquals("/CISD/A23:[COMMENT: A]\n" + "/CISD/A24:[COMMENT: B]\n", builder.toString());
     }
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResults.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResults.java
index 016aa43ef68..477e1a547c5 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResults.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResults.java
@@ -41,25 +41,38 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifi
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class DataSetInfoExtractorForProteinResults extends AbstractDataSetInfoExtractorWithService
 {
-    @Private static final String EXPERIMENT_TYPE_CODE_KEY = "experiment-type-code";
-    @Private static final String EXPERIMENT_PROPERTIES_FILE_NAME_KEY = "experiment-properties-file-name";
-    @Private static final String DEFAULT_EXPERIMENT_TYPE_CODE = "MS_SEARCH";
-    @Private static final String SEPARATOR_KEY = "separator";
-    @Private static final String DEFAULT_SEPARATOR = "&";
-    @Private static final String DEFAULT_EXPERIMENT_PROPERTIES_FILE_NAME = "search.properties";
+    @Private
+    static final String EXPERIMENT_TYPE_CODE_KEY = "experiment-type-code";
+
+    @Private
+    static final String EXPERIMENT_PROPERTIES_FILE_NAME_KEY = "experiment-properties-file-name";
+
+    @Private
+    static final String DEFAULT_EXPERIMENT_TYPE_CODE = "MS_SEARCH";
+
+    @Private
+    static final String SEPARATOR_KEY = "separator";
+
+    @Private
+    static final String DEFAULT_SEPARATOR = "&";
+
+    @Private
+    static final String DEFAULT_EXPERIMENT_PROPERTIES_FILE_NAME = "search.properties";
+
     static final String PARENT_DATA_SET_CODES = "parent-data-set-codes";
+
     static final String EXPERIMENT_IDENTIFIER_KEY = "base-experiment";
-    
+
     private final String separator;
+
     private final String experimentPropertiesFileName;
+
     private final String experimentTypeCode;
-    
+
     public DataSetInfoExtractorForProteinResults(Properties properties)
     {
         this(properties, ServiceProvider.getOpenBISService());
@@ -72,7 +85,8 @@ public class DataSetInfoExtractorForProteinResults extends AbstractDataSetInfoEx
         experimentPropertiesFileName =
                 properties.getProperty(EXPERIMENT_PROPERTIES_FILE_NAME_KEY,
                         DEFAULT_EXPERIMENT_PROPERTIES_FILE_NAME);
-        experimentTypeCode = properties.getProperty(EXPERIMENT_TYPE_CODE_KEY, DEFAULT_EXPERIMENT_TYPE_CODE);
+        experimentTypeCode =
+                properties.getProperty(EXPERIMENT_TYPE_CODE_KEY, DEFAULT_EXPERIMENT_TYPE_CODE);
     }
 
     @Override
@@ -85,13 +99,13 @@ public class DataSetInfoExtractorForProteinResults extends AbstractDataSetInfoEx
         if (items.length < 2)
         {
             throw new UserFailureException(
-                    "The name of the data set should have at least two parts separated by '" + separator
-                            + "': " + name);
+                    "The name of the data set should have at least two parts separated by '"
+                            + separator + "': " + name);
         }
         ProjectIdentifier projectIdentifier = new ProjectIdentifier(items[0], items[1]);
+        String experimentCode = service.generateCodes("E", EntityKind.EXPERIMENT, 1).get(0);
         ExperimentIdentifier experimentIdentifier =
-                new ExperimentIdentifier(projectIdentifier, "E"
-                        + service.drawANewUniqueID(EntityKind.EXPERIMENT));
+                new ExperimentIdentifier(projectIdentifier, experimentCode);
         NewExperiment experiment =
                 new NewExperiment(experimentIdentifier.toString(), experimentTypeCode);
         ExperimentType experimentType = service.getExperimentType(experimentTypeCode);
@@ -117,8 +131,8 @@ public class DataSetInfoExtractorForProteinResults extends AbstractDataSetInfoEx
     }
 
     /**
-     * Returns data set codes either from the first argument or if <code>null</code> from
-     * the data sets of the specified experiment. 
+     * Returns data set codes either from the first argument or if <code>null</code> from the data
+     * sets of the specified experiment.
      */
     static ParentDataSetCodes getParentDataSetCodes(String parentDataSetCodesOrNull,
             String baseExperimentIdentifier, IEncapsulatedOpenBISService service)
@@ -160,7 +174,7 @@ public class DataSetInfoExtractorForProteinResults extends AbstractDataSetInfoEx
         String errorMessage = builder.length() > 0 ? builder.toString() : null;
         return new ParentDataSetCodes(parentDataSetCodes, errorMessage);
     }
-    
+
     private String getProperty(Properties properties, String key)
     {
         String property = properties.getProperty(key);
@@ -170,7 +184,7 @@ public class DataSetInfoExtractorForProteinResults extends AbstractDataSetInfoEx
         }
         return property;
     }
-    
+
     private Properties loadSearchProperties(File propertiesFile)
     {
         Properties properties;
diff --git a/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResultsTest.java b/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResultsTest.java
index ebb19d4b60d..b7d50683735 100644
--- a/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResultsTest.java
+++ b/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/etlserver/proteomics/DataSetInfoExtractorForProteinResultsTest.java
@@ -56,20 +56,20 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifi
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
-@Friend(toClasses=DataSetInfoExtractorForProteinResults.class)
+@Friend(toClasses = DataSetInfoExtractorForProteinResults.class)
 public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSystemTestCase
 {
     private static final String PARENT_DATA_SET_CODES_KEY =
             DataSetInfoExtractorForProteinResults.PARENT_DATA_SET_CODES.toUpperCase();
 
     private Mockery context;
+
     private IEncapsulatedOpenBISService service;
+
     private File dataSet;
-    
+
     @BeforeMethod
     public void beforeMethod()
     {
@@ -78,7 +78,7 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
         dataSet = new File(workingDirectory, "space1&project1");
         dataSet.mkdirs();
     }
-    
+
     @AfterMethod
     public void afterMethod()
     {
@@ -86,7 +86,7 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
         // Otherwise one do not known which test failed.
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testWithNonDefaultExperimentTypeAndPropertiesFileName()
     {
@@ -111,14 +111,14 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
             });
 
         IDataSetInfoExtractor extractor = createExtractor(properties);
-        
+
         DataSetInformation info = extractor.getDataSetInformation(dataSet, service);
-        
+
         assertEquals("/SPACE1/PROJECT1/E4711", info.getExperimentIdentifier().toString());
         assertEquals("[1, 2, 3, 4]", info.getParentDataSetCodes().toString());
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testRegistrationWithOneMandatoryProperty()
     {
@@ -142,8 +142,8 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
                                 if (item instanceof NewExperiment)
                                 {
                                     NewExperiment experiment = (NewExperiment) item;
-                                    assertEquals(DEFAULT_EXPERIMENT_TYPE_CODE, experiment
-                                            .getExperimentTypeCode());
+                                    assertEquals(DEFAULT_EXPERIMENT_TYPE_CODE,
+                                            experiment.getExperimentTypeCode());
                                     IEntityProperty[] properties = experiment.getProperties();
                                     assertEquals(1, properties.length);
                                     assertEquals("answer", properties[0].getPropertyType()
@@ -174,7 +174,7 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
     public void testRegistrationWithMissingMandatoryProperty()
     {
         prepare(DEFAULT_EXPERIMENT_TYPE_CODE);
-        
+
         IDataSetInfoExtractor extractor = createExtractor(new Properties());
         try
         {
@@ -184,10 +184,10 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
         {
             assertEquals("The following mandatory properties are missed: [answer]", ex.getMessage());
         }
-        
+
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testWithParentDataSetsDefinedByBaseExperiment()
     {
@@ -207,25 +207,25 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
                                     "EXP1"));
                     Experiment experiment = new ExperimentBuilder().id(123789L).getExperiment();
                     will(returnValue(experiment));
-                    
+
                     one(service).listDataSetsByExperimentID(experiment.getId());
                     ExternalData ds1 = new DataSetBuilder().code("ds1").getDataSet();
                     ExternalData ds2 = new DataSetBuilder().code("ds2").getDataSet();
                     will(returnValue(Arrays.asList(ds1, ds2)));
-                    
+
                     one(service).registerExperiment(with(any(NewExperiment.class)));
                 }
             });
 
         IDataSetInfoExtractor extractor = createExtractor(properties);
-        
+
         DataSetInformation info = extractor.getDataSetInformation(dataSet, service);
-        
+
         assertEquals("/SPACE1/PROJECT1/E4711", info.getExperimentIdentifier().toString());
         assertEquals("[ds1, ds2]", info.getParentDataSetCodes().toString());
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testWithUnkownBaseExperiment()
     {
@@ -247,9 +247,9 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
 
                 }
             });
-        
+
         IDataSetInfoExtractor extractor = createExtractor(properties);
-        
+
         try
         {
             extractor.getDataSetInformation(dataSet, service);
@@ -260,7 +260,7 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
         }
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testWithUnkownParentDataSets()
     {
@@ -289,7 +289,7 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
         }
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testWithParentDataSetsSeparatedBySpaces()
     {
@@ -348,15 +348,15 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
         assertEquals("[ds1, ds2]", info.getParentDataSetCodes().toString());
         context.assertIsSatisfied();
     }
-    
+
     private void prepare(final String experimentType)
     {
         context.checking(new Expectations()
             {
                 {
-                    one(service).drawANewUniqueID(EntityKind.EXPERIMENT);
+                    one(service).generateCodes("E", EntityKind.EXPERIMENT, 1);
                     will(returnValue(4711L));
-                    
+
                     one(service).getExperimentType(experimentType);
                     ExperimentType type = new ExperimentType();
                     ExperimentTypePropertyType etpt = new ExperimentTypePropertyType();
@@ -369,12 +369,12 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
                 }
             });
     }
-    
+
     private void prepareGetDataSet(final String dataSetCode)
     {
         prepareGetDataSet(dataSetCode, new DataSetBuilder().code(dataSetCode).getDataSet());
     }
-    
+
     private void prepareGetDataSet(final String dataSetCode, final ExternalData data)
     {
         context.checking(new Expectations()
@@ -385,7 +385,7 @@ public class DataSetInfoExtractorForProteinResultsTest extends AbstractFileSyste
                 }
             });
     }
-    
+
     private IDataSetInfoExtractor createExtractor(Properties properties)
     {
         return new DataSetInfoExtractorForProteinResults(properties, service);
-- 
GitLab