diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/RelationshipService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/RelationshipService.java index 4641cba9989c202fb1fc2d4a986b3d6fc254f8d7..4ce46b299834cbe05e8f86a03b4f456612ce4844 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/RelationshipService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/RelationshipService.java @@ -89,6 +89,7 @@ public class RelationshipService implements IRelationshipService } sample.setExperiment(experiment); + RelationshipUtils.updateModificationDateAndModifier(experiment, session); for (DataPE dataset : sample.getDatasets()) { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/util/RelationshipUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/util/RelationshipUtils.java index 361832750e0a2577234ea39d044516c9888d4a9e..65481fe00916c5e530aecc2d0e7d413fc5bdea53 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/util/RelationshipUtils.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/util/RelationshipUtils.java @@ -67,15 +67,15 @@ public class RelationshipUtils { if (stackTraceElement.getClassName().contains("OptimisticLockingTest")) { - System.err.println("===== UPDATE modification date and modifier ===== " + System.out.println("===== UPDATE modification date and modifier ===== " + stackTraceElement.getMethodName()); - System.err.println("bean: " + beanOrNull); - System.err.println("user: " + session.tryGetPerson()); - System.err.println("\t" + stackTrace[3]); - System.err.println("\t" + stackTrace[4]); - System.err.println("\t" + stackTrace[5]); - System.err.println("\t..."); - System.err.println("\t" + stackTraceElement); + System.out.println("bean: " + beanOrNull); + System.out.println("user: " + session.tryGetPerson()); + System.out.println("\t" + stackTrace[3]); + System.out.println("\t" + stackTrace[4]); + System.out.println("\t" + stackTrace[5]); + System.out.println("\t..."); + System.out.println("\t" + stackTraceElement); break; } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/util/TimeIntervalChecker.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/util/TimeIntervalChecker.java index 8c26dfcb61f26101720fff65624853de0062f948..be77acedf6e7ac0dfcbfbc1c3d4e99500de0ba92 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/util/TimeIntervalChecker.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/util/TimeIntervalChecker.java @@ -42,11 +42,11 @@ public class TimeIntervalChecker extends AssertJUnit } /** - * Creates an instance for now minus specified shift in seconds. + * Creates an instance for now minus specified shift in milliseconds. */ - public TimeIntervalChecker(long shiftInSeconds) + public TimeIntervalChecker(long shiftInMillisecond) { - notBeforeDate = new Date(System.currentTimeMillis() - shiftInSeconds * 1000); + notBeforeDate = new Date(System.currentTimeMillis() - shiftInMillisecond); } /** diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ExperimentOptimisticLockingTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ExperimentOptimisticLockingTest.java index 1f796860efb87e8c08de66f86f13e5ce3b142443..0cb3e1bca2436ea6adb122a40b8fce4436b38dac 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ExperimentOptimisticLockingTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ExperimentOptimisticLockingTest.java @@ -20,41 +20,25 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.fail; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import org.apache.log4j.Logger; import org.testng.annotations.Test; -import ch.systemsx.cisd.common.concurrent.MessageChannel; -import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder; import ch.systemsx.cisd.common.exception.UserFailureException; -import ch.systemsx.cisd.common.logging.LogCategory; -import ch.systemsx.cisd.common.logging.LogFactory; -import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext; -import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener; import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker; -import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType; 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.FileFormatType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType; -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.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.SampleTypeBuilder; import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.NewDataSet; -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.StorageFormat; import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; @@ -64,36 +48,13 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa */ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase { - private static final String DATA_STORE_CODE = "STANDARD"; - - private static final LocatorType LOCATOR_TYPE = new LocatorType( - LocatorType.DEFAULT_LOCATOR_TYPE_CODE); - - private static final FileFormatType FILE_FORMAT_TYPE = new FileFormatType("XML"); - - private static final DataSetType DATA_SET_TYPE = new DataSetType("UNKNOWN"); - - private static final List<IEntityProperty> NO_PROPERTIES = Collections - .<IEntityProperty> emptyList(); - - private static final List<NewAttachment> NO_ATTACHMENTS = Collections - .<NewAttachment> emptyList(); - - private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, - ExperimentOptimisticLockingTest.class); - - private static final String REGISTERED = "registered"; - - private static final String FIRST_REGISTERED = "First registered"; - - protected static final String SAMPLE_TYPE_CODE = "NORMAL"; @Test public void testRegisterExperiment() { - NewExperiment experiment = experiment(1); + NewExperiment experiment = toolBox.experiment(1); logIntoCommonClientService(); - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1000); genericClientService.registerExperiment(SESSION_KEY, SESSION_KEY, experiment); @@ -110,14 +71,14 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase @Test public void testChangePropertyOfAnExistingExperiment() { - Experiment experiment = createAndLoadExperiment(1); + Experiment experiment = toolBox.createAndLoadExperiment(1); String sessionToken = logIntoCommonClientService().getSessionID(); ExperimentUpdatesDTO updates = new ExperimentUpdatesDTO(); updates.setVersion(experiment.getVersion()); updates.setExperimentId(new TechId(experiment)); - updates.setProjectIdentifier(createProjectIdentifier(experiment.getProject() + updates.setProjectIdentifier(toolBox.createProjectIdentifier(experiment.getProject() .getIdentifier())); - updates.setAttachments(NO_ATTACHMENTS); + updates.setAttachments(ToolBox.NO_ATTACHMENTS); List<IEntityProperty> properties = new ArrayList<IEntityProperty>(); properties.addAll(experiment.getProperties()); properties.get(0).setValue("testChangePropertyOfAnExistingExperiment"); @@ -126,7 +87,7 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase genericServer.updateExperiment(sessionToken, updates); - Experiment retrievedExperiment = loadExperiment(experiment); + Experiment retrievedExperiment = toolBox.loadExperiment(experiment); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, retrievedExperiment, "test"); assertEquals("DESCRIPTION: testChangePropertyOfAnExistingExperiment", retrievedExperiment @@ -136,14 +97,15 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase @Test public void testChangeProjectOfAnExistingExperiment() { - Experiment experiment = createAndLoadExperiment(1); - assertEquals(project1.getIdentifier(), experiment.getProject().getIdentifier()); + Experiment experiment = toolBox.createAndLoadExperiment(1); + assertEquals(toolBox.project1.getIdentifier(), experiment.getProject().getIdentifier()); String sessionToken = logIntoCommonClientService().getSessionID(); ExperimentUpdatesDTO updates = new ExperimentUpdatesDTO(); updates.setVersion(experiment.getVersion()); updates.setExperimentId(new TechId(experiment)); - updates.setProjectIdentifier(createProjectIdentifier(project2.getIdentifier())); - updates.setAttachments(NO_ATTACHMENTS); + updates.setProjectIdentifier(toolBox.createProjectIdentifier(toolBox.project2 + .getIdentifier())); + updates.setAttachments(ToolBox.NO_ATTACHMENTS); updates.setProperties(experiment.getProperties()); TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); @@ -153,19 +115,21 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase commonServer.getExperimentInfo(systemSessionToken, new TechId(experiment)); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, retrievedExperiment, "test"); - assertEquals(project2.getIdentifier(), retrievedExperiment.getProject().getIdentifier()); + assertEquals(toolBox.project2.getIdentifier(), retrievedExperiment.getProject() + .getIdentifier()); } @Test public void testUpdateExperimentWithOldVersion() { - Experiment experiment = createAndLoadExperiment(1); + Experiment experiment = toolBox.createAndLoadExperiment(1); String sessionToken = logIntoCommonClientService().getSessionID(); ExperimentUpdatesDTO updates = new ExperimentUpdatesDTO(); updates.setVersion(experiment.getVersion()); updates.setExperimentId(new TechId(experiment)); - updates.setProjectIdentifier(createProjectIdentifier(project2.getIdentifier())); - updates.setAttachments(NO_ATTACHMENTS); + updates.setProjectIdentifier(toolBox.createProjectIdentifier(toolBox.project2 + .getIdentifier())); + updates.setAttachments(ToolBox.NO_ATTACHMENTS); updates.setProperties(experiment.getProperties()); genericServer.updateExperiment(sessionToken, updates); @@ -180,98 +144,38 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase } } - @Test - public void testRegisterSamplesForSameExperimentInTwoThreads() - { - final NewExperiment experiment = experiment(1); - genericServer.registerExperiment(systemSessionToken, experiment, NO_ATTACHMENTS); - final MessageChannel messageChannelMain = - new MessageChannelBuilder(10000).name("samples main").logger(operationLog) - .getChannel(); - final MessageChannel messageChannelSecond = - new MessageChannelBuilder(10000).name("samples second").logger(operationLog) - .getChannel(); - final IServiceConversationProgressListener listener = - new AbstractServiceConversationProgressListener(operationLog) - { - @Override - public void handleProgress(String phaseName, int totalItemsToProcess, - int numItemsProcessed) - { - logger.info(phaseName + " " + numItemsProcessed + "/" - + totalItemsToProcess); - if (phaseName.equals("createContainerSamples") - && numItemsProcessed == 1 && totalItemsToProcess == 2) - { - messageChannelMain.send(FIRST_REGISTERED); - } - } - }; - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); - new Thread(new Runnable() - { - @Override - public void run() - { - NewSample sample3 = sample(3, experiment); - - String sessionToken = - genericServer.tryToAuthenticate("test", "a").getSessionToken(); - messageChannelMain.assertNextMessage(FIRST_REGISTERED); - genericServer.registerSample(sessionToken, sample3, NO_ATTACHMENTS); - messageChannelSecond.send(REGISTERED); - } - }).start(); - ServiceConversationsThreadContext.setProgressListener(listener); - AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); - builder.user(USER_ID).batchSize(1); - NewSample sample1 = sample(1, experiment); - NewSample sample2 = sample(2, experiment); - builder.sample(sample1).sample(sample2); - - etlService.performEntityOperations(systemSessionToken, builder.getDetails()); - messageChannelSecond.assertNextMessage(REGISTERED); - - Experiment experimentInfo = loadExperiment(experiment); - List<Sample> samples = - commonServer.listSamples(systemSessionToken, - ListSampleCriteria.createForExperiment(new TechId(experimentInfo))); - assertEquals("[OLT-S1, OLT-S2, OLT-S3]", extractCodes(samples).toString()); - checkModifierAndModificationDateOfExperiment(timeIntervalChecker, experimentInfo, "test"); - } - @Test public void testMoveSampleBetweenExperiments() { - Experiment experiment1 = createAndLoadExperiment(1); - Experiment experiment2 = createAndLoadExperiment(2); - NewSample sample = sample(1, experiment1); - genericServer.registerSample(systemSessionToken, sample, NO_ATTACHMENTS); - Sample loadedSample = loadSample(sample); + Experiment experiment1 = toolBox.createAndLoadExperiment(1); + Experiment experiment2 = toolBox.createAndLoadExperiment(2); + NewSample sample = toolBox.sample(1, experiment1); + genericServer.registerSample(systemSessionToken, sample, ToolBox.NO_ATTACHMENTS); + Sample loadedSample = toolBox.loadSample(sample); SampleUpdatesDTO sampleUpdate = - new SampleUpdatesDTO(new TechId(loadedSample), NO_PROPERTIES, + new SampleUpdatesDTO(new TechId(loadedSample), ToolBox.NO_PROPERTIES, ExperimentIdentifierFactory.parse(experiment2.getIdentifier()), - NO_ATTACHMENTS, loadedSample.getModificationDate(), + ToolBox.NO_ATTACHMENTS, loadedSample.getModificationDate(), SampleIdentifierFactory.parse(sample), null, null); sampleUpdate.setUpdateExperimentLink(true); AtomicEntityOperationDetails details = - new AtomicEntityOperationDetailsBuilder().user(USER_ID).sampleUpdate(sampleUpdate) - .getDetails(); + new AtomicEntityOperationDetailsBuilder().user(ToolBox.USER_ID) + .sampleUpdate(sampleUpdate).getDetails(); String sessionToken = logIntoCommonClientService().getSessionID(); TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); etlService.performEntityOperations(sessionToken, details); - Experiment loadedExperiment1 = loadExperiment(experiment1); + Experiment loadedExperiment1 = toolBox.loadExperiment(experiment1); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment1, - USER_ID); + ToolBox.USER_ID); List<Sample> samples1 = commonServer.listSamples(systemSessionToken, ListSampleCriteria.createForExperiment(new TechId(loadedExperiment1))); assertEquals("[]", samples1.toString()); - Experiment loadedExperiment2 = loadExperiment(experiment2); + Experiment loadedExperiment2 = toolBox.loadExperiment(experiment2); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment2, - USER_ID); + ToolBox.USER_ID); List<Sample> samples2 = commonServer.listSamples(systemSessionToken, ListSampleCriteria.createForExperiment(new TechId(loadedExperiment2))); @@ -281,21 +185,22 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase @Test public void testRemoveSampleFromExperiment() { - Experiment experiment = createAndLoadExperiment(1); - NewSample sample = sample(1, experiment); - genericServer.registerSample(systemSessionToken, sample, NO_ATTACHMENTS); + Experiment experiment = toolBox.createAndLoadExperiment(1); + NewSample sample = toolBox.sample(1, experiment); + genericServer.registerSample(systemSessionToken, sample, ToolBox.NO_ATTACHMENTS); ExperimentUpdatesDTO update = new ExperimentUpdatesDTO(); update.setExperimentId(new TechId(experiment)); update.setSampleCodes(new String[0]); - update.setProperties(NO_PROPERTIES); - update.setAttachments(NO_ATTACHMENTS); - update.setProjectIdentifier(createProjectIdentifier(experiment.getProject().getIdentifier())); + update.setProperties(ToolBox.NO_PROPERTIES); + update.setAttachments(ToolBox.NO_ATTACHMENTS); + update.setProjectIdentifier(toolBox.createProjectIdentifier(experiment.getProject() + .getIdentifier())); String sessionToken = logIntoCommonClientService().getSessionID(); TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); genericServer.updateExperiment(sessionToken, update); - Experiment loadedExperiment = loadExperiment(experiment); + Experiment loadedExperiment = toolBox.loadExperiment(experiment); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment, "test"); List<Sample> samples = commonServer.listSamples(systemSessionToken, @@ -306,10 +211,10 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase @Test public void testMoveDataSetBetweenExperiments() { - Experiment exp1 = createAndLoadExperiment(1); - Experiment exp2 = createAndLoadExperiment(2); + Experiment exp1 = toolBox.createAndLoadExperiment(1); + Experiment exp2 = toolBox.createAndLoadExperiment(2); AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); - NewDataSet dataSet = dataSet("DS-1", exp1); + NewDataSet dataSet = toolBox.dataSet("DS-1", exp1); builder.dataSet(dataSet); etlService.performEntityOperations(systemSessionToken, builder.getDetails()); List<ExternalData> dataSets = @@ -320,80 +225,25 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase update.setDatasetId(new TechId(loadedDataSet)); update.setVersion(loadedDataSet.getModificationDate()); update.setExperimentIdentifierOrNull(ExperimentIdentifierFactory.parse(exp2.getIdentifier())); - update.setProperties(NO_PROPERTIES); + update.setProperties(ToolBox.NO_PROPERTIES); update.setFileFormatTypeCode(dataSet.getFileFormatType().getCode()); String sessionToken = logIntoCommonClientService().getSessionID(); TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); genericServer.updateDataSet(sessionToken, update); - Experiment loadedExperiment1 = loadExperiment(exp1); + Experiment loadedExperiment1 = toolBox.loadExperiment(exp1); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment1, "test"); List<ExternalData> dataSets1 = etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(exp1)); assertEquals("[]", dataSets1.toString()); - Experiment loadedExperiment2 = loadExperiment(exp2); + Experiment loadedExperiment2 = toolBox.loadExperiment(exp2); checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment2, "test"); List<ExternalData> dataSets2 = etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(exp2)); assertEquals(dataSet.getCode(), dataSets2.get(0).getCode()); } - @Test - public void testRegisterDataSetsForSameExperimentInTwoThreads() - { - final Experiment experiment = createAndLoadExperiment(1); - final MessageChannel messageChannelMain = - new MessageChannelBuilder(10000).name("data sets main").logger(operationLog) - .getChannel(); - final MessageChannel messageChannelSecond = - new MessageChannelBuilder(10000).name("data sets second").logger(operationLog) - .getChannel(); - final IServiceConversationProgressListener listener = - new AbstractServiceConversationProgressListener(operationLog) - { - @Override - public void handleProgress(String phaseName, int totalItemsToProcess, - int numItemsProcessed) - { - if (phaseName.equals("createDataSets") && numItemsProcessed == 1 - && totalItemsToProcess == 2) - { - messageChannelMain.send(FIRST_REGISTERED); - System.out.println(loadExperiment(experiment).getModifier() - .getUserId()); - } - } - }; - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); - new Thread(new Runnable() - { - @Override - public void run() - { - messageChannelMain.assertNextMessage(FIRST_REGISTERED); - AtomicEntityOperationDetails details = - new AtomicEntityOperationDetailsBuilder().user("test") - .dataSet(dataSet("DS3", experiment)).getDetails(); - etlService.performEntityOperations(systemSessionToken, details); - messageChannelSecond.send(REGISTERED); - } - }).start(); - ServiceConversationsThreadContext.setProgressListener(listener); - AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); - builder.user(USER_ID).batchSize(1); - builder.dataSet(dataSet("DS1", experiment)).dataSet(dataSet("DS2", experiment)); - - etlService.performEntityOperations(systemSessionToken, builder.getDetails()); - messageChannelSecond.assertNextMessage(REGISTERED); - - Experiment loadedExperiment = loadExperiment(experiment); - List<ExternalData> dataSets = - etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(experiment)); - assertEquals("[DS1, DS2, DS3]", extractCodes(dataSets).toString()); - checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment, "test"); - } - private void checkModifierAndModificationDateOfExperiment( TimeIntervalChecker timeIntervalChecker, Experiment experiment, String userId) { @@ -401,60 +251,4 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase timeIntervalChecker.assertDateInInterval(experiment.getModificationDate()); } - private Experiment createAndLoadExperiment(int number) - { - NewExperiment experiment = experiment(number); - genericServer.registerExperiment(systemSessionToken, experiment, NO_ATTACHMENTS); - return loadExperiment(experiment); - } - - private Experiment loadExperiment(final IIdentifierHolder experiment) - { - return commonServer.getExperimentInfo(systemSessionToken, - ExperimentIdentifierFactory.parse(experiment.getIdentifier())); - } - - private NewSample sample(int number, IIdentifierHolder experiment) - { - NewSample sample = sample(number); - sample.setExperimentIdentifier(experiment.getIdentifier()); - return sample; - } - - private NewSample sample(int number) - { - NewSample sample = new NewSample(); - sample.setIdentifier("/" + SPACE_1 + "/OLT-S" + number); - sample.setSampleType(new SampleTypeBuilder().code(SAMPLE_TYPE_CODE).getSampleType()); - return sample; - } - - private Sample loadSample(IIdentifierHolder sample) - { - return etlService.tryGetSampleWithExperiment(systemSessionToken, - SampleIdentifierFactory.parse(sample.getIdentifier())); - } - - private NewDataSet dataSet(String code, Experiment experiment) - { - NewDataSet dataSet = dataSet(code); - dataSet.setExperimentIdentifierOrNull(ExperimentIdentifierFactory.parse(experiment - .getIdentifier())); - return dataSet; - } - - private NewDataSet dataSet(String code) - { - NewDataSet dataSet = new NewDataSet(); - dataSet.setCode(code); - dataSet.setDataSetType(DATA_SET_TYPE); - dataSet.setFileFormatType(FILE_FORMAT_TYPE); - dataSet.setDataSetProperties(Collections.<NewProperty> emptyList()); - dataSet.setLocation("a/b/c/" + code); - dataSet.setLocatorType(LOCATOR_TYPE); - dataSet.setStorageFormat(StorageFormat.PROPRIETARY); - dataSet.setDataStoreCode(DATA_STORE_CODE); - return dataSet; - } - } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadExperimentOptimisticLockingTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadExperimentOptimisticLockingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3ff192795ad96d0537f51a903bba826e1160addb --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadExperimentOptimisticLockingTest.java @@ -0,0 +1,173 @@ +/* + * 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.systemtest.optimistic_locking; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.common.concurrent.MessageChannel; +import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext; +import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener; +import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker; +import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; +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.ListSampleCriteria; +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.Sample; +import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails; +import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder; + +/** + * @author Franz-Josef Elmer + */ +public class MultiThreadExperimentOptimisticLockingTest extends + MultiThreadOptimisticLockingTestCase +{ + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + MultiThreadExperimentOptimisticLockingTest.class); + + @Test + public void testRegisterSamplesForSameExperimentInTwoThreads() + { + final NewExperiment experiment = toolBox.experiment(1); + genericServer.registerExperiment(systemSessionToken, experiment, ToolBox.NO_ATTACHMENTS); + final MessageChannel messageChannelMain = + new MessageChannelBuilder(10000).name("samples main").logger(operationLog) + .getChannel(); + final MessageChannel messageChannelSecond = + new MessageChannelBuilder(10000).name("samples second").logger(operationLog) + .getChannel(); + final IServiceConversationProgressListener listener = + new AbstractServiceConversationProgressListener(operationLog) + { + @Override + public void handleProgress(String phaseName, int totalItemsToProcess, + int numItemsProcessed) + { + logger.info(phaseName + " " + numItemsProcessed + "/" + + totalItemsToProcess); + if (phaseName.equals("createContainerSamples") + && numItemsProcessed == 1 && totalItemsToProcess == 2) + { + messageChannelMain.send(ToolBox.FIRST_REGISTERED); + } + } + }; + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); + new Thread(new Runnable() + { + @Override + public void run() + { + NewSample sample3 = toolBox.sample(3, experiment); + + String sessionToken = + genericServer.tryToAuthenticate("test", "a").getSessionToken(); + messageChannelMain.assertNextMessage(ToolBox.FIRST_REGISTERED); + genericServer.registerSample(sessionToken, sample3, ToolBox.NO_ATTACHMENTS); + messageChannelSecond.send(ToolBox.REGISTERED); + } + }).start(); + ServiceConversationsThreadContext.setProgressListener(listener); + AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); + builder.user(ToolBox.USER_ID).batchSize(1); + NewSample sample1 = toolBox.sample(1, experiment); + NewSample sample2 = toolBox.sample(2, experiment); + builder.sample(sample1).sample(sample2); + + etlService.performEntityOperations(systemSessionToken, builder.getDetails()); + messageChannelSecond.assertNextMessage(ToolBox.REGISTERED); + + Experiment experimentInfo = toolBox.loadExperiment(experiment); + List<Sample> samples = + commonServer.listSamples(systemSessionToken, + ListSampleCriteria.createForExperiment(new TechId(experimentInfo))); + assertEquals("[OLT-S1, OLT-S2, OLT-S3]", toolBox.extractCodes(samples).toString()); + checkModifierAndModificationDateOfExperiment(timeIntervalChecker, experimentInfo, "test"); + } + + @Test + public void testRegisterDataSetsForSameExperimentInTwoThreads() + { + final Experiment experiment = toolBox.createAndLoadExperiment(1); + final MessageChannel messageChannelMain = + new MessageChannelBuilder(10000).name("data sets main").logger(operationLog) + .getChannel(); + final MessageChannel messageChannelSecond = + new MessageChannelBuilder(10000).name("data sets second").logger(operationLog) + .getChannel(); + final IServiceConversationProgressListener listener = + new AbstractServiceConversationProgressListener(operationLog) + { + @Override + public void handleProgress(String phaseName, int totalItemsToProcess, + int numItemsProcessed) + { + if (phaseName.equals("createDataSets") && numItemsProcessed == 1 + && totalItemsToProcess == 2) + { + messageChannelMain.send(ToolBox.FIRST_REGISTERED); + } + } + }; + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); + new Thread(new Runnable() + { + @Override + public void run() + { + messageChannelMain.assertNextMessage(ToolBox.FIRST_REGISTERED); + AtomicEntityOperationDetails details = + new AtomicEntityOperationDetailsBuilder().user("test") + .dataSet(toolBox.dataSet("DS3", experiment)).getDetails(); + etlService.performEntityOperations(systemSessionToken, details); + messageChannelSecond.send(ToolBox.REGISTERED); + } + }).start(); + ServiceConversationsThreadContext.setProgressListener(listener); + AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); + builder.user(ToolBox.USER_ID).batchSize(1); + builder.dataSet(toolBox.dataSet("DS1", experiment)).dataSet( + toolBox.dataSet("DS2", experiment)); + + etlService.performEntityOperations(systemSessionToken, builder.getDetails()); + messageChannelSecond.assertNextMessage(ToolBox.REGISTERED); + + Experiment loadedExperiment = toolBox.loadExperiment(experiment); + List<ExternalData> dataSets = + etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(experiment)); + assertEquals("[DS1, DS2, DS3]", toolBox.extractCodes(dataSets).toString()); + checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment, "test"); + } + + private void checkModifierAndModificationDateOfExperiment( + TimeIntervalChecker timeIntervalChecker, Experiment experiment, String userId) + { + assertEquals(userId, experiment.getModifier().getUserId()); + timeIntervalChecker.assertDateInInterval(experiment.getModificationDate()); + } + +} diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadOptimisticLockingTestCase.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadOptimisticLockingTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..727ffdce1defdd5cfbf83c51ebcb51882730e54f --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadOptimisticLockingTestCase.java @@ -0,0 +1,46 @@ +/* + * 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.systemtest.optimistic_locking; + +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; + +import ch.systemsx.cisd.openbis.systemtest.PersistentSystemTestCase; + +/** + * Super class of system test doing commit after each service operation. Can be used to write tests + * with more than one Thread. + * + * @author Franz-Josef Elmer + */ +public class MultiThreadOptimisticLockingTestCase extends PersistentSystemTestCase +{ + protected ToolBox toolBox; + + @BeforeMethod + public void createSpacesAndProjects() + { + toolBox = new ToolBox(commonServer, genericServer, etlService, systemSessionToken); + toolBox.createSpacesAndProjects(); + } + + @AfterMethod + public void deleteSpaces() + { + toolBox.deleteSpaces(); + } +} diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadProjectOptimisticLockingTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadProjectOptimisticLockingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..169bec53c75c4bb697b4671ce5010af4af800a26 --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/MultiThreadProjectOptimisticLockingTest.java @@ -0,0 +1,120 @@ +/* + * 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.systemtest.optimistic_locking; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.Collections; +import java.util.List; + +import org.apache.log4j.Logger; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.common.concurrent.MessageChannel; +import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext; +import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener; +import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +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.builders.ExperimentTypeBuilder; +import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails; +import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder; + +/** + * @author Franz-Josef Elmer + */ +public class MultiThreadProjectOptimisticLockingTest extends MultiThreadOptimisticLockingTestCase +{ + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + MultiThreadProjectOptimisticLockingTest.class); + + private static final String CREATE_EXPERIMENTS_PHASE = "createExperiments"; + + /* + * This test registers three experiments for the same project. Two of them are registered by the + * main thread using performEntityOperations(). A second thread registers an experiment between + * the registration of the two other experiments. This is done by using a + * IServiceConversationProgressListener together with two message channels to coordinate the + * order of actions in both threads. + */ + @Test + public void testRegisterExperimentsInTwoThreads() + { + assertEquals("system", toolBox.project1.getModifier().getUserId()); + final StringBuilder stringBuilder = new StringBuilder(); + final MessageChannel messageChannelMain = + new MessageChannelBuilder(10000).name("main").logger(operationLog).getChannel(); + final MessageChannel messageChannelSecond = + new MessageChannelBuilder(10000).name("second").logger(operationLog).getChannel(); + final IServiceConversationProgressListener listener = + new AbstractServiceConversationProgressListener(operationLog) + { + @Override + public void handleProgress(String phaseName, int totalItemsToProcess, + int numItemsProcessed) + { + stringBuilder.append(phaseName).append(" ").append(numItemsProcessed) + .append("/").append(totalItemsToProcess).append("\n"); + if (phaseName.equals(CREATE_EXPERIMENTS_PHASE) + && numItemsProcessed == 1 && totalItemsToProcess == 2) + { + messageChannelMain.send(ToolBox.FIRST_REGISTERED); + } + } + }; + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); + + new Thread(new Runnable() + { + @Override + public void run() + { + NewExperiment experiment3 = toolBox.experiment(3); + String sessionToken = + genericServer.tryToAuthenticate("test", "a").getSessionToken(); + messageChannelMain.assertNextMessage(ToolBox.FIRST_REGISTERED); + genericServer.registerExperiment(sessionToken, experiment3, + Collections.<NewAttachment> emptyList()); + messageChannelSecond.send(ToolBox.REGISTERED); + } + }).start(); + + ServiceConversationsThreadContext.setProgressListener(listener); + AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); + builder.user(ToolBox.USER_ID); + builder.experiment(toolBox.experiment(1)).experiment(toolBox.experiment(2)); + AtomicEntityOperationDetails details = builder.getDetails(); + + etlService.performEntityOperations(systemSessionToken, details); + + messageChannelSecond.assertNextMessage(ToolBox.REGISTERED); + + List<Experiment> experiments = + commonServer.listExperiments(systemSessionToken, + new ExperimentTypeBuilder().code(ToolBox.EXPERIMENT_TYPE_CODE) + .getExperimentType(), toolBox + .createProjectIdentifier(toolBox.project1.getIdentifier())); + assertEquals("[OLT-E1, OLT-E2, OLT-E3]", toolBox.extractCodes(experiments).toString()); + toolBox.checkModifierAndModificationDateOfProject1(timeIntervalChecker); + assertEquals("authorize 1/2\n" + "authorize 2/2\n" + "createExperiments 1/2\n" + + "createExperiments 2/2\n", stringBuilder.toString()); + } +} diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/OptimisticLockingTestCase.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/OptimisticLockingTestCase.java index afbfc621ea92e987a238a3397139c58ce9ea6474..f9efe8cbe0c693bbff3187fe582fee3c4aeb553e 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/OptimisticLockingTestCase.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/OptimisticLockingTestCase.java @@ -16,221 +16,23 @@ package ch.systemsx.cisd.openbis.systemtest.optimistic_locking; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; -import ch.systemsx.cisd.openbis.generic.shared.basic.ICodeHolder; -import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; -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.ListSampleCriteria; -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.Person; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project; -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.Space; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PropertyBuilder; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier; -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.SpaceIdentifierFactory; -import ch.systemsx.cisd.openbis.systemtest.PersistentSystemTestCase; +import ch.systemsx.cisd.openbis.systemtest.SystemTestCase; /** + * Super class of system tests with rollback after each test. + * * @author Franz-Josef Elmer */ -public class OptimisticLockingTestCase extends PersistentSystemTestCase +public class OptimisticLockingTestCase extends SystemTestCase { - protected static final String USER_ID = "optimist"; - - protected static final String SPACE_1 = "OPTIMISTIC_LOCKING_1"; - - protected static final String SPACE_2 = "OPTIMISTIC_LOCKING_2"; - - protected static final String EXPERIMENT_TYPE_CODE = "SIRNA_HCS"; - - protected Space space1; - - protected Space space2; - - protected Project project1; - - protected Project project2; + protected ToolBox toolBox; @BeforeMethod public void createSpacesAndProjects() { - space1 = findOrCreateSpace(SPACE_1); - space2 = findOrCreateSpace(SPACE_2); - project1 = findOrCreateProject("/" + SPACE_1 + "/P1"); - project2 = findOrCreateProject("/" + SPACE_2 + "/P2"); - createInstanceAdmin(USER_ID); - } - - @AfterMethod - public void deleteSpaces() - { - deleteSpace(space1); - deleteSpace(space2); - } - - private void deleteSpace(Space space) - { - trashExperiments(space); - trashSamples(space); - emptyTrashCan(); - deleteProjects(space); - commonServer.deleteSpaces(systemSessionToken, Arrays.asList(new TechId(space.getId())), - "cleanup"); - } - - private void deleteProjects(Space space) - { - List<Project> projects = commonServer.listProjects(systemSessionToken); - List<TechId> projectIds = new ArrayList<TechId>(); - for (Project project : projects) - { - if (project.getSpace().getCode().equals(space.getCode())) - { - projectIds.add(new TechId(project)); - } - } - commonServer.deleteProjects(systemSessionToken, projectIds, "cleanup"); - } - - private void emptyTrashCan() - { - List<Deletion> deletions = commonServer.listDeletions(systemSessionToken, false); - commonServer.deletePermanently(systemSessionToken, TechId.createList(deletions)); - } - - private void trashSamples(Space space) - { - ListSampleCriteria criteria = new ListSampleCriteria(); - criteria.setSampleType(SampleType.createAllSampleType(Collections.<SampleType> emptyList(), - false)); - criteria.setSpaceCode(space.getCode()); - criteria.setIncludeSpace(true); - criteria.setIncludeInstance(false); - criteria.setExcludeWithoutExperiment(false); - List<Sample> samples = commonServer.listSamples(systemSessionToken, criteria); - commonServer.deleteSamples(systemSessionToken, TechId.createList(samples), "cleanup", - DeletionType.TRASH); - } - - private void trashExperiments(Space space) - { - List<Experiment> experiments = - commonServer.listExperiments(systemSessionToken, - new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(), - new SpaceIdentifierFactory(space.getIdentifier()).createIdentifier()); - commonServer.deleteExperiments(systemSessionToken, TechId.createList(experiments), - "cleanup", DeletionType.TRASH); + toolBox = new ToolBox(commonServer, genericServer, etlService, systemSessionToken); + toolBox.createSpacesAndProjects(); } - - private void createInstanceAdmin(String userId) - { - List<Person> persons = commonServer.listPersons(systemSessionToken); - for (Person person : persons) - { - if (person.getUserId().equals(userId)) - { - return; - } - } - commonServer.registerPerson(systemSessionToken, userId); - commonServer.registerInstanceRole(systemSessionToken, RoleCode.ADMIN, - Grantee.createPerson(userId)); - } - - protected Project findOrCreateProject(String projectIdentifier) - { - Project project = tryToFindProject(projectIdentifier); - if (project != null) - { - return project; - } - commonServer.registerProject(systemSessionToken, new ProjectIdentifierFactory( - projectIdentifier).createIdentifier(), "A test project", null, Collections - .<NewAttachment> emptyList()); - return tryToFindProject(projectIdentifier); - } - - protected Project tryToFindProject(String projectIdentifier) - { - List<Project> projects = commonServer.listProjects(systemSessionToken); - for (Project project : projects) - { - if (project.getIdentifier().equals(projectIdentifier)) - { - return project; - } - } - return null; - } - - protected Space findOrCreateSpace(String spaceCode) - { - Space space = tryToFindSpace(spaceCode); - if (space != null) - { - return space; - } - commonServer.registerSpace(systemSessionToken, spaceCode, "A test space"); - return tryToFindSpace(spaceCode); - } - - protected Space tryToFindSpace(String spaceCode) - { - DatabaseInstanceIdentifier identifier = new DatabaseInstanceIdentifier(null); - List<Space> spaces = commonServer.listSpaces(systemSessionToken, identifier); - for (Space space : spaces) - { - if (space.getCode().equals(spaceCode)) - { - return space; - } - } - return null; - } - - protected NewExperiment experiment(int number) - { - NewExperiment experiment = - new NewExperiment(project1.getIdentifier() + "/OLT-E" + number, - EXPERIMENT_TYPE_CODE); - experiment.setAttachments(Collections.<NewAttachment> emptyList()); - experiment.setProperties(new IEntityProperty[] - { new PropertyBuilder("DESCRIPTION").value("hello " + number).getProperty() }); - return experiment; - } - - protected List<String> extractCodes(List<? extends ICodeHolder> codeHolders) - { - List<String> result = new ArrayList<String>(); - for (ICodeHolder codeHolder : codeHolders) - { - result.add(codeHolder.getCode()); - } - Collections.sort(result); - return result; - } - - protected ProjectIdentifier createProjectIdentifier(String identifier) - { - return new ProjectIdentifierFactory(identifier).createIdentifier(); - } - } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ProjectOptimisticLockingTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ProjectOptimisticLockingTest.java index f1fb28eb17867a09473609f929f6d8a1cc10b785..d1d75fc9f9d5c3ada1db20b0b06902e4ff5009ed 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ProjectOptimisticLockingTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ProjectOptimisticLockingTest.java @@ -22,15 +22,8 @@ import static org.testng.AssertJUnit.fail; import java.util.Collections; import java.util.List; -import org.apache.log4j.Logger; import org.testng.annotations.Test; -import ch.systemsx.cisd.common.concurrent.MessageChannel; -import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder; -import ch.systemsx.cisd.common.logging.LogCategory; -import ch.systemsx.cisd.common.logging.LogFactory; -import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext; -import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener; import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; @@ -42,7 +35,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ProjectUpdates; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PropertyBuilder; -import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails; import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; @@ -51,32 +43,23 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; */ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase { - private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, - ProjectOptimisticLockingTest.class); - - private static final String REGISTERED = "registered"; - - private static final String FIRST_REGISTERED = "First registered"; - - private static final String CREATE_EXPERIMENTS_PHASE = "createExperiments"; - @Test public void testCreateProject() { Project project = new Project(); project.setCode("POLT-1"); - String identifier = "/" + space1.getCode() + "/POLT-1"; + String identifier = "/" + toolBox.space1.getCode() + "/POLT-1"; project.setIdentifier(identifier); project.setDescription("ProjectOptimisticLockingTest test"); - project.setSpace(space1); + project.setSpace(toolBox.space1); logIntoCommonClientService(); - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1); + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1000); commonClientService.registerProject(SESSION_KEY, project); Project p = - commonServer - .getProjectInfo(systemSessionToken, createProjectIdentifier(identifier)); + commonServer.getProjectInfo(systemSessionToken, + toolBox.createProjectIdentifier(identifier)); assertEquals(project.getDescription(), p.getDescription()); assertEquals("test", p.getRegistrator().getUserId()); assertEquals("test", p.getModifier().getUserId()); @@ -87,7 +70,8 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase @Test public void testUpdateProjectAndCheckModificationDateAndModifier() { - ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier()); + ProjectIdentifier projectIdentifier = + toolBox.createProjectIdentifier(toolBox.project1.getIdentifier()); Project p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier); ProjectUpdates updates = new ProjectUpdates(); updates.setVersion(p.getVersion()); @@ -96,12 +80,12 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase updates.setAttachments(Collections.<NewAttachment> emptyList()); updates.setAttachmentSessionKey(SESSION_KEY); logIntoCommonClientService(); - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1); + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); commonClientService.updateProject(updates); p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier); - assertEquals(project1.getDescription() + " 2", p.getDescription()); + assertEquals(toolBox.project1.getDescription() + " 2", p.getDescription()); assertEquals("system", p.getRegistrator().getUserId()); assertEquals("test", p.getModifier().getUserId()); timeIntervalChecker.assertDateInInterval(p.getModificationDate()); @@ -111,7 +95,8 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase @Test public void testUpdateProjectWithOldVersion() { - ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier()); + ProjectIdentifier projectIdentifier = + toolBox.createProjectIdentifier(toolBox.project1.getIdentifier()); Project currentProject = commonServer.getProjectInfo(systemSessionToken, projectIdentifier); ProjectUpdates updates = new ProjectUpdates(); updates.setVersion(currentProject.getVersion()); @@ -138,121 +123,37 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase { String sessionToken = logIntoCommonClientService().getSessionID(); NewExperiment experiment = - new NewExperiment(project1.getIdentifier() + "/POLT-1", EXPERIMENT_TYPE_CODE); + new NewExperiment(toolBox.project1.getIdentifier() + "/POLT-1", + ToolBox.EXPERIMENT_TYPE_CODE); experiment.setAttachments(Collections.<NewAttachment> emptyList()); experiment.setProperties(new IEntityProperty[] { new PropertyBuilder("DESCRIPTION").value("hello").getProperty() }); - assertEquals("system", project1.getModifier().getUserId()); - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1); + assertEquals("system", toolBox.project1.getModifier().getUserId()); + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); genericServer.registerExperiment(sessionToken, experiment, Collections.<NewAttachment> emptyList()); - checkModifierAndModificationDateOfProject1(timeIntervalChecker); + toolBox.checkModifierAndModificationDateOfProject1(timeIntervalChecker); } @Test public void testRegisterExperiments() { - assertEquals("system", project1.getModifier().getUserId()); + assertEquals("system", toolBox.project1.getModifier().getUserId()); AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); - builder.user(USER_ID); - builder.experiment(experiment(1)).experiment(experiment(2)); - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1); + builder.user(ToolBox.USER_ID); + builder.experiment(toolBox.experiment(1)).experiment(toolBox.experiment(2)); + TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(); etlService.performEntityOperations(systemSessionToken, builder.getDetails()); List<Experiment> experiments = commonServer.listExperiments(systemSessionToken, - new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(), - createProjectIdentifier(project1.getIdentifier())); - assertEquals("[OLT-E1, OLT-E2]", extractCodes(experiments).toString()); - checkModifierAndModificationDateOfProject1(timeIntervalChecker, USER_ID); - } - - /* - * This test registers three experiments for the same project. Two of them are registered by the - * main thread using performEntityOperations(). A second thread registers an experiment between - * the registration of the two other experiments. This is done by using a - * IServiceConversationProgressListener together with two message channels to coordinate the - * order of actions in both threads. - */ - @Test - public void testRegisterExperimentsInTwoThreads() - { - assertEquals("system", project1.getModifier().getUserId()); - final StringBuilder stringBuilder = new StringBuilder(); - final MessageChannel messageChannelMain = - new MessageChannelBuilder(10000).name("main").logger(operationLog).getChannel(); - final MessageChannel messageChannelSecond = - new MessageChannelBuilder(10000).name("second").logger(operationLog).getChannel(); - final IServiceConversationProgressListener listener = - new AbstractServiceConversationProgressListener(operationLog) - { - @Override - public void handleProgress(String phaseName, int totalItemsToProcess, - int numItemsProcessed) - { - stringBuilder.append(phaseName).append(" ").append(numItemsProcessed) - .append("/").append(totalItemsToProcess).append("\n"); - if (phaseName.equals(CREATE_EXPERIMENTS_PHASE) - && numItemsProcessed == 1 && totalItemsToProcess == 2) - { - messageChannelMain.send(FIRST_REGISTERED); - } - } - }; - TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1); - - new Thread(new Runnable() - { - @Override - public void run() - { - NewExperiment experiment3 = experiment(3); - String sessionToken = - genericServer.tryToAuthenticate("test", "a").getSessionToken(); - messageChannelMain.assertNextMessage(FIRST_REGISTERED); - genericServer.registerExperiment(sessionToken, experiment3, - Collections.<NewAttachment> emptyList()); - messageChannelSecond.send(REGISTERED); - } - }).start(); - - ServiceConversationsThreadContext.setProgressListener(listener); - AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder(); - builder.user(USER_ID); - builder.experiment(experiment(1)).experiment(experiment(2)); - AtomicEntityOperationDetails details = builder.getDetails(); - - etlService.performEntityOperations(systemSessionToken, details); - - messageChannelSecond.assertNextMessage(REGISTERED); - - List<Experiment> experiments = - commonServer.listExperiments(systemSessionToken, - new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(), - createProjectIdentifier(project1.getIdentifier())); - assertEquals("[OLT-E1, OLT-E2, OLT-E3]", extractCodes(experiments).toString()); - checkModifierAndModificationDateOfProject1(timeIntervalChecker); - assertEquals("authorize 1/2\n" + "authorize 2/2\n" + "createExperiments 1/2\n" - + "createExperiments 2/2\n", stringBuilder.toString()); + new ExperimentTypeBuilder().code(ToolBox.EXPERIMENT_TYPE_CODE) + .getExperimentType(), toolBox + .createProjectIdentifier(toolBox.project1.getIdentifier())); + assertEquals("[OLT-E1, OLT-E2]", toolBox.extractCodes(experiments).toString()); + toolBox.checkModifierAndModificationDateOfProject1(timeIntervalChecker, ToolBox.USER_ID); } - - private void checkModifierAndModificationDateOfProject1(TimeIntervalChecker timeIntervalChecker) - { - checkModifierAndModificationDateOfProject1(timeIntervalChecker, "test"); - } - - private void checkModifierAndModificationDateOfProject1( - TimeIntervalChecker timeIntervalChecker, String modifier) - { - ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier()); - Project p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier); - assertEquals("system", p.getRegistrator().getUserId()); - assertEquals(project1.getRegistrationDate(), p.getRegistrationDate()); - assertEquals(modifier, p.getModifier().getUserId()); - timeIntervalChecker.assertDateInInterval(p.getModificationDate()); - } - } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ToolBox.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ToolBox.java new file mode 100644 index 0000000000000000000000000000000000000000..2ac92f5a1c602ea45facb8b93d67c374dada3079 --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/optimistic_locking/ToolBox.java @@ -0,0 +1,358 @@ +/* + * 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.systemtest.optimistic_locking; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker; +import ch.systemsx.cisd.openbis.generic.shared.ICommonServer; +import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; +import ch.systemsx.cisd.openbis.generic.shared.basic.ICodeHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType; +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.NewSample; +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.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.Space; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PropertyBuilder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.SampleTypeBuilder; +import ch.systemsx.cisd.openbis.generic.shared.dto.NewDataSet; +import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; +import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier; +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.SampleIdentifierFactory; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifierFactory; +import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer; + +/** + * @author Franz-Josef Elmer + */ +public class ToolBox +{ + public static final String USER_ID = "optimist"; + + public static final String SPACE_1 = "OPTIMISTIC_LOCKING_1"; + + public static final String SPACE_2 = "OPTIMISTIC_LOCKING_2"; + + public static final String EXPERIMENT_TYPE_CODE = "SIRNA_HCS"; + + public static final String SAMPLE_TYPE_CODE = "NORMAL"; + + public static final String DATA_STORE_CODE = "STANDARD"; + + public static final String REGISTERED = "registered"; + + public static final String FIRST_REGISTERED = "First registered"; + + public static final List<IEntityProperty> NO_PROPERTIES = Collections + .<IEntityProperty> emptyList(); + + public static final List<NewAttachment> NO_ATTACHMENTS = Collections + .<NewAttachment> emptyList(); + + private static final LocatorType LOCATOR_TYPE = new LocatorType( + LocatorType.DEFAULT_LOCATOR_TYPE_CODE); + + private static final FileFormatType FILE_FORMAT_TYPE = new FileFormatType("XML"); + + private static final DataSetType DATA_SET_TYPE = new DataSetType("UNKNOWN"); + + private final ICommonServer commonServer; + + private final IGenericServer genericServer; + + private final IETLLIMSService etlService; + + private final String systemSessionToken; + + public Space space1; + + public Space space2; + + public Project project1; + + public Project project2; + + public ToolBox(ICommonServer commonServer, IGenericServer genericServer, + IETLLIMSService etlService, String systemSessionToken) + { + this.commonServer = commonServer; + this.genericServer = genericServer; + this.etlService = etlService; + this.systemSessionToken = systemSessionToken; + + } + + void createSpacesAndProjects() + { + space1 = findOrCreateSpace(SPACE_1); + space2 = findOrCreateSpace(SPACE_2); + project1 = findOrCreateProject("/" + SPACE_1 + "/P1"); + project2 = findOrCreateProject("/" + SPACE_2 + "/P2"); + createInstanceAdmin(USER_ID); + } + + void deleteSpaces() + { + deleteSpace(space1); + deleteSpace(space2); + } + + private void deleteSpace(Space space) + { + trashExperiments(space); + trashSamples(space); + emptyTrashCan(); + deleteProjects(space); + commonServer.deleteSpaces(systemSessionToken, Arrays.asList(new TechId(space.getId())), + "cleanup"); + } + + private void deleteProjects(Space space) + { + List<Project> projects = commonServer.listProjects(systemSessionToken); + List<TechId> projectIds = new ArrayList<TechId>(); + for (Project project : projects) + { + if (project.getSpace().getCode().equals(space.getCode())) + { + projectIds.add(new TechId(project)); + } + } + commonServer.deleteProjects(systemSessionToken, projectIds, "cleanup"); + } + + private void emptyTrashCan() + { + List<Deletion> deletions = commonServer.listDeletions(systemSessionToken, false); + commonServer.deletePermanently(systemSessionToken, TechId.createList(deletions)); + } + + private void trashSamples(Space space) + { + ListSampleCriteria criteria = new ListSampleCriteria(); + criteria.setSampleType(SampleType.createAllSampleType(Collections.<SampleType> emptyList(), + false)); + criteria.setSpaceCode(space.getCode()); + criteria.setIncludeSpace(true); + criteria.setIncludeInstance(false); + criteria.setExcludeWithoutExperiment(false); + List<Sample> samples = commonServer.listSamples(systemSessionToken, criteria); + commonServer.deleteSamples(systemSessionToken, TechId.createList(samples), "cleanup", + DeletionType.TRASH); + } + + private void trashExperiments(Space space) + { + List<Experiment> experiments = + commonServer.listExperiments(systemSessionToken, + new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(), + new SpaceIdentifierFactory(space.getIdentifier()).createIdentifier()); + commonServer.deleteExperiments(systemSessionToken, TechId.createList(experiments), + "cleanup", DeletionType.TRASH); + } + + public void createInstanceAdmin(String userId) + { + List<Person> persons = commonServer.listPersons(systemSessionToken); + for (Person person : persons) + { + if (person.getUserId().equals(userId)) + { + return; + } + } + commonServer.registerPerson(systemSessionToken, userId); + commonServer.registerInstanceRole(systemSessionToken, RoleCode.ADMIN, + Grantee.createPerson(userId)); + } + + public Project findOrCreateProject(String projectIdentifier) + { + Project project = tryToFindProject(projectIdentifier); + if (project != null) + { + return project; + } + commonServer.registerProject(systemSessionToken, new ProjectIdentifierFactory( + projectIdentifier).createIdentifier(), "A test project", null, Collections + .<NewAttachment> emptyList()); + return tryToFindProject(projectIdentifier); + } + + public Project tryToFindProject(String projectIdentifier) + { + List<Project> projects = commonServer.listProjects(systemSessionToken); + for (Project project : projects) + { + if (project.getIdentifier().equals(projectIdentifier)) + { + return project; + } + } + return null; + } + + public Space findOrCreateSpace(String spaceCode) + { + Space space = tryToFindSpace(spaceCode); + if (space != null) + { + return space; + } + commonServer.registerSpace(systemSessionToken, spaceCode, "A test space"); + return tryToFindSpace(spaceCode); + } + + public Space tryToFindSpace(String spaceCode) + { + DatabaseInstanceIdentifier identifier = new DatabaseInstanceIdentifier(null); + List<Space> spaces = commonServer.listSpaces(systemSessionToken, identifier); + for (Space space : spaces) + { + if (space.getCode().equals(spaceCode)) + { + return space; + } + } + return null; + } + + NewExperiment experiment(int number) + { + NewExperiment experiment = + new NewExperiment(project1.getIdentifier() + "/OLT-E" + number, + EXPERIMENT_TYPE_CODE); + experiment.setAttachments(Collections.<NewAttachment> emptyList()); + experiment.setProperties(new IEntityProperty[] + { new PropertyBuilder("DESCRIPTION").value("hello " + number).getProperty() }); + return experiment; + } + + public List<String> extractCodes(List<? extends ICodeHolder> codeHolders) + { + List<String> result = new ArrayList<String>(); + for (ICodeHolder codeHolder : codeHolders) + { + result.add(codeHolder.getCode()); + } + Collections.sort(result); + return result; + } + + public ProjectIdentifier createProjectIdentifier(String identifier) + { + return new ProjectIdentifierFactory(identifier).createIdentifier(); + } + + public Experiment createAndLoadExperiment(int number) + { + NewExperiment experiment = experiment(number); + genericServer.registerExperiment(systemSessionToken, experiment, NO_ATTACHMENTS); + return loadExperiment(experiment); + } + + public Experiment loadExperiment(final IIdentifierHolder experiment) + { + return commonServer.getExperimentInfo(systemSessionToken, + ExperimentIdentifierFactory.parse(experiment.getIdentifier())); + } + + public NewSample sample(int number, IIdentifierHolder experiment) + { + NewSample sample = sample(number); + sample.setExperimentIdentifier(experiment.getIdentifier()); + return sample; + } + + public NewSample sample(int number) + { + NewSample sample = new NewSample(); + sample.setIdentifier("/" + ToolBox.SPACE_1 + "/OLT-S" + number); + sample.setSampleType(new SampleTypeBuilder().code(SAMPLE_TYPE_CODE).getSampleType()); + return sample; + } + + public Sample loadSample(IIdentifierHolder sample) + { + return etlService.tryGetSampleWithExperiment(systemSessionToken, + SampleIdentifierFactory.parse(sample.getIdentifier())); + } + + public NewDataSet dataSet(String code, Experiment experiment) + { + NewDataSet dataSet = dataSet(code); + dataSet.setExperimentIdentifierOrNull(ExperimentIdentifierFactory.parse(experiment + .getIdentifier())); + return dataSet; + } + + private NewDataSet dataSet(String code) + { + NewDataSet dataSet = new NewDataSet(); + dataSet.setCode(code); + dataSet.setDataSetType(DATA_SET_TYPE); + dataSet.setFileFormatType(FILE_FORMAT_TYPE); + dataSet.setDataSetProperties(Collections.<NewProperty> emptyList()); + dataSet.setLocation("a/b/c/" + code); + dataSet.setLocatorType(LOCATOR_TYPE); + dataSet.setStorageFormat(StorageFormat.PROPRIETARY); + dataSet.setDataStoreCode(DATA_STORE_CODE); + return dataSet; + } + + public void checkModifierAndModificationDateOfProject1(TimeIntervalChecker timeIntervalChecker) + { + checkModifierAndModificationDateOfProject1(timeIntervalChecker, "test"); + } + + public void checkModifierAndModificationDateOfProject1(TimeIntervalChecker timeIntervalChecker, + String modifier) + { + ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier()); + Project p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier); + assertEquals("system", p.getRegistrator().getUserId()); + assertEquals(project1.getRegistrationDate(), p.getRegistrationDate()); + assertEquals(modifier, p.getModifier().getUserId()); + timeIntervalChecker.assertDateInInterval(p.getModificationDate()); + } + +}