diff --git a/deep_sequencing_unit/.classpath b/deep_sequencing_unit/.classpath index 1bdaf2704e297950b0150d5586117489a17d0f60..99c204da58b5c2982409fe3351ea360722baf353 100644 --- a/deep_sequencing_unit/.classpath +++ b/deep_sequencing_unit/.classpath @@ -12,5 +12,6 @@ <classpathentry kind="lib" path="/libraries/jmock/hamcrest/hamcrest-library.jar"/> <classpathentry kind="lib" path="/libraries/jmock/objenesis/objenesis-1.0.jar"/> <classpathentry kind="lib" path="/libraries/jmock/jmock.jar"/> + <classpathentry kind="lib" path="/libraries/log4j/log4j.jar" sourcepath="/libraries/log4j/src.zip"/> <classpathentry kind="output" path="targets/classes"/> </classpath> diff --git a/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java b/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java index 144306f2bb868ad3b2f26d20cac0840915e581ee..4b01c89a8268bb1b312a37b08a45498bb16ad3e4 100644 --- a/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java +++ b/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java @@ -19,10 +19,15 @@ package ch.ethz.bsse.cisd.dsu.dss; import java.io.File; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; +import java.util.Map.Entry; + +import org.apache.log4j.Logger; import ch.systemsx.cisd.common.Constants; import ch.systemsx.cisd.common.TimingParameters; @@ -33,6 +38,9 @@ import ch.systemsx.cisd.common.filesystem.FileOperations; import ch.systemsx.cisd.common.filesystem.FileUtilities; import ch.systemsx.cisd.common.filesystem.IFileOperations; import ch.systemsx.cisd.common.filesystem.IImmutableCopier; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.common.utilities.ExtendedProperties; import ch.systemsx.cisd.common.utilities.PropertyUtils; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.IPostRegistrationDatasetHandler; @@ -41,6 +49,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureE import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; @@ -53,15 +62,21 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa */ class FlowLineFeeder implements IPostRegistrationDatasetHandler { + static final String TRANSFER_PREFIX = "transfer."; + static final String AFFILIATION_KEY = "AFFILIATION"; static final String META_DATA_FILE_NAME = "meta-data.tsv"; static final String FLOW_LINE_DROP_BOX_TEMPLATE = "flow-line-drop-box-template"; static final String FILE_TYPE = ".srf"; + private final static Logger operationLog = + LogFactory.getLogger(LogCategory.OPERATION, FlowLineFeeder.class); + private final IEncapsulatedOpenBISService service; private final MessageFormat flowLineDropBoxTemplate; private final IImmutableCopier copier; private final IFileOperations fileOperations; - private final List<File> flowLineDataSets = new ArrayList<File>(); + private final List<File> createdFiles = new ArrayList<File>(); + private final Map<String, File> transferDropBoxes = new HashMap<String, File>(); FlowLineFeeder(Properties properties, IEncapsulatedOpenBISService service) { @@ -71,6 +86,21 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler FLOW_LINE_DROP_BOX_TEMPLATE)); copier = FastRecursiveHardLinkMaker.tryCreate(TimingParameters.getDefaultParameters()); fileOperations = FileOperations.getInstance(); + Properties transferDropBoxMapping = + ExtendedProperties.getSubset(properties, TRANSFER_PREFIX, true); + Set<Entry<Object, Object>> entries = transferDropBoxMapping.entrySet(); + for (Entry<Object, Object> entry : entries) + { + String affiliation = entry.getKey().toString(); + String dropBoxPath = entry.getValue().toString(); + File dropBox = new File(dropBoxPath); + if (dropBox.isDirectory() == false) + { + throw new EnvironmentFailureException("Transfer drop box for " + affiliation + + " doen't exist or isn't a folder: " + dropBox.getAbsolutePath()); + } + transferDropBoxes.put(affiliation, dropBox); + } } public void handle(File originalData, DataSetInformation dataSetInformation) @@ -90,24 +120,24 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler throw new EnvironmentFailureException("There is already a data set for flow line " + flowLine + "."); } - flowLineDataSets.add(flowLineDataSet); + createdFiles.add(flowLineDataSet); boolean success = flowLineDataSet.mkdir(); if (success == false) { throw new EnvironmentFailureException("Couldn't create folder '" + flowLineDataSet.getAbsolutePath() + "'."); } - createMetaDataFile(flowLineDataSet, flowLineSampleMap, flowLine); - success = copier.copyImmutably(file, flowLineDataSet, null); - if (success == false) - { - throw new EnvironmentFailureException("Couldn't create a hard-link copy of '" - + file.getAbsolutePath() + "' in folder '" - + flowLineDataSet.getAbsolutePath() + "'."); - } + createHartLink(file, flowLineDataSet); + createMetaDataFileAndHartLinkInTransferDropBox(flowLineDataSet, flowLineSampleMap, flowLine); File markerFile = new File(dropBox, Constants.IS_FINISHED_PREFIX + fileName); - flowLineDataSets.add(markerFile); + createdFiles.add(markerFile); FileUtilities.writeToFile(markerFile, ""); + if (operationLog.isInfoEnabled()) + { + operationLog.info("Flow line file '" + file + + "' successfully dropped into drop box '" + dropBox + + "' as '" + flowLineDataSet.getName() + "'."); + } } } @@ -131,8 +161,8 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler return flowLineSampleMap; } - private void createMetaDataFile(File flowLineDataSet, Map<String, Sample> flowLineSampleMap, - String flowLine) + private void createMetaDataFileAndHartLinkInTransferDropBox(File flowLineDataSet, + Map<String, Sample> flowLineSampleMap, String flowLine) { Sample flowLineSample = flowLineSampleMap.get(flowLine); if (flowLineSample == null) @@ -145,11 +175,28 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler addLine(builder, "Contact Person Email", flowLineSample.getRegistrator().getEmail()); SampleIdentifier identifier = SampleIdentifierFactory.parse(flowLineSample.getIdentifier()); IEntityProperty[] properties = service.getPropertiesOfTopSampleRegisteredFor(identifier); + File dropBox = null; for (IEntityProperty property : properties) { - addLine(builder, property.getPropertyType().getLabel(), property.tryGetAsString()); + PropertyType propertyType = property.getPropertyType(); + String value = property.tryGetAsString(); + addLine(builder, propertyType.getLabel(), value); + if (propertyType.getCode().equals(AFFILIATION_KEY)) + { + dropBox = transferDropBoxes.get(value); + } } FileUtilities.writeToFile(new File(flowLineDataSet, META_DATA_FILE_NAME), builder.toString()); + if (dropBox != null) + { + createHartLink(flowLineDataSet, dropBox); + createdFiles.add(new File(dropBox, flowLineDataSet.getName())); + if (operationLog.isInfoEnabled()) + { + operationLog.info("Flow line data set '" + flowLineDataSet.getName() + + "' successfully transfered to drop box '" + dropBox + "'"); + } + } } private void addLine(StringBuilder builder, String key, String value) @@ -157,6 +204,18 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler builder.append(key).append('\t').append(value).append('\n'); } + private void createHartLink(File file, File folder) + { + boolean success; + success = copier.copyImmutably(file, folder, null); + if (success == false) + { + throw new EnvironmentFailureException("Couldn't create a hard-link copy of '" + + file.getAbsolutePath() + "' in folder '" + + folder.getAbsolutePath() + "'."); + } + } + private File createDropBoxFile(String flowLine) { File dropBox = new File(flowLineDropBoxTemplate.format(new Object[] {flowLine})); @@ -201,7 +260,12 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler public void undoLastOperation() { - for (File file : flowLineDataSets) + if (operationLog.isInfoEnabled()) + { + operationLog.info("Undo last operation by deleting following files: " + createdFiles); + } + + for (File file : createdFiles) { if (file.exists()) { diff --git a/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java b/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java index b91f946efd50575487485cc63d4f22dc3ed45f2b..52bbe053e41a282565e42eba709d1c7a571b1310 100644 --- a/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java +++ b/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java @@ -17,6 +17,7 @@ package ch.ethz.bsse.cisd.dsu.dss; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -34,12 +35,15 @@ import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; import ch.systemsx.cisd.common.Constants; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.filesystem.FileUtilities; +import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.test.AssertionUtil; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GenericValueEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; @@ -51,6 +55,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa */ public class FlowLineFeederTest extends AbstractFileSystemTestCase { + private static final String AFFILIATION = "fmi"; + private static final String TRANSFER_DROP_BOX = "transfer-drop-box"; private static final Sample EXAMPLE_FLOW_CELL_SAMPLE = createFlowCellSample(); private static final DataSetInformation EXAMPLE_DATA_SET_INFO = createDataSetInfo(); private static final String SAMPLE_CODE = "fc"; @@ -74,20 +80,30 @@ public class FlowLineFeederTest extends AbstractFileSystemTestCase private FlowLineFeeder flowLineFeeder; private Mockery context; private IEncapsulatedOpenBISService service; + private File dropBox1; + private File dropBox2; + private File transferDropBox; @Override @BeforeMethod public void setUp() throws IOException { super.setUp(); + LogInitializer.init(); context = new Mockery(); service = context.mock(IEncapsulatedOpenBISService.class); - assertEquals(true, new File(workingDirectory, DROP_BOX_PREFIX + "1").mkdirs()); - assertEquals(true, new File(workingDirectory, DROP_BOX_PREFIX + "2").mkdirs()); + FileUtilities.deleteRecursively(workingDirectory); + dropBox1 = new File(workingDirectory, DROP_BOX_PREFIX + "1"); + assertEquals(true, dropBox1.mkdirs()); + dropBox2 = new File(workingDirectory, DROP_BOX_PREFIX + "2"); + assertEquals(true, dropBox2.mkdirs()); + transferDropBox = new File(workingDirectory, TRANSFER_DROP_BOX); + assertEquals(true, transferDropBox.mkdirs()); Properties properties = new Properties(); properties.setProperty(FlowLineFeeder.FLOW_LINE_DROP_BOX_TEMPLATE, new File( workingDirectory, DROP_BOX_PREFIX).getAbsolutePath() + "{0}"); + properties.setProperty(FlowLineFeeder.TRANSFER_PREFIX + AFFILIATION, transferDropBox.getAbsolutePath()); flowLineFeeder = new FlowLineFeeder(properties, service); } @@ -180,20 +196,42 @@ public class FlowLineFeederTest extends AbstractFileSystemTestCase checkFlowLineDataSet(originalFlowLine1, "1"); checkFlowLineDataSet(originalFlowLine2, "2"); + File[] transferedFiles = transferDropBox.listFiles(); + assertEquals(1, transferedFiles.length); + assertEquals("abc_2", transferedFiles[0].getName()); + getFile(transferedFiles[0], FlowLineFeeder.META_DATA_FILE_NAME); + assertHardLinkOnSameFile(originalFlowLine2, getFile(transferedFiles[0], "2.srf")); + context.assertIsSatisfied(); } + private File getFile(File folder, final String fileName) + { + File[] files = folder.listFiles(new FilenameFilter() + { + + public boolean accept(File dir, String name) + { + return fileName.equals(name); + } + }); + assertEquals(1, files.length); + return files[0]; + } + @Test public void testUndoLastOperation() { testHappyCase(); - assertEquals(2, new File(workingDirectory, DROP_BOX_PREFIX + "1").list().length); - assertEquals(2, new File(workingDirectory, DROP_BOX_PREFIX + "2").list().length); + assertEquals(2, dropBox1.list().length); + assertEquals(2, dropBox2.list().length); + assertEquals(1, transferDropBox.list().length); flowLineFeeder.undoLastOperation(); - assertEquals(0, new File(workingDirectory, DROP_BOX_PREFIX + "1").list().length); - assertEquals(0, new File(workingDirectory, DROP_BOX_PREFIX + "2").list().length); + assertEquals(0, dropBox1.list().length); + assertEquals(0, dropBox2.list().length); + assertEquals(0, transferDropBox.list().length); } private void prepareLoadFlowCellSample(final Sample flowCellSample) @@ -238,6 +276,16 @@ public class FlowLineFeederTest extends AbstractFileSystemTestCase SampleIdentifier identifier = SampleIdentifierFactory.parse(sample.getIdentifier()); one(service).getPropertiesOfTopSampleRegisteredFor(identifier); + if (sample.getSubCode().equals("2")) + { + GenericValueEntityProperty p = new GenericValueEntityProperty(); + p.setValue(AFFILIATION); + PropertyType propertyType = new PropertyType(); + propertyType.setCode(FlowLineFeeder.AFFILIATION_KEY); + propertyType.setLabel(FlowLineFeeder.AFFILIATION_KEY.toLowerCase()); + p.setPropertyType(propertyType); + will(returnValue(new GenericValueEntityProperty[] {p})); + } } } }); @@ -254,13 +302,18 @@ public class FlowLineFeederTest extends AbstractFileSystemTestCase assertEquals(true, flowLine.isFile()); assertEquals(FileUtilities.loadToString(originalFlowLine), FileUtilities .loadToString(flowLine)); - // check hard-link copy by changing last-modified date of one file should change - // last-modified date of the other file. - originalFlowLine.setLastModified(4711000); - assertEquals(4711000, flowLine.lastModified()); + assertHardLinkOnSameFile(originalFlowLine, flowLine); assertEquals(true, new File(ds, FlowLineFeeder.META_DATA_FILE_NAME).exists()); assertEquals(true, new File(dropBox, Constants.IS_FINISHED_PREFIX + fileName).exists()); } + + private void assertHardLinkOnSameFile(File file1, File file2) + { + // check hard-link copy by changing last-modified date of one file should change + // last-modified date of the other file. + file1.setLastModified(4711000); + assertEquals(4711000, file2.lastModified()); + } private Sample createFlowLineSample(int flowLineNumber) {