diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTask.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTask.java index 5a3329ebe48ce98d5c8b10faca63363cb53fbc99..9066602c7e092adfdd828054a397b1eaf9981c31 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTask.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTask.java @@ -16,21 +16,20 @@ package ch.systemsx.cisd.etlserver.plugins; -import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Properties; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; -import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; @@ -44,6 +43,7 @@ import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.maintenance.IMaintenanceTask; import ch.systemsx.cisd.common.process.ProcessExecutionHelper; import ch.systemsx.cisd.common.process.ProcessResult; +import ch.systemsx.cisd.common.properties.PropertyUtils; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContentNode; import ch.systemsx.cisd.openbis.dss.generic.shared.IConfigProvider; @@ -51,18 +51,20 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider; import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PhysicalDataSet; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria; /** - * This maintenance task creates a BLAST database for all files + * This maintenance task creates a BLAST database for all files with defined file types of data set with + * matching data set types. * * @author Franz-Josef Elmer */ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask { + static final String DATASET_TYPES_PROPERTY = "dataset-types"; static final String BLAST_TOOLS_DIRECTORY_PROPERTY = "blast-tools-directory"; static final String BLAST_DATABASES_FOLDER_PROPERTY = "blast-databases-folder"; + static final String BLAST_TEMP_FOLDER_PROPERTY = "blast-temp-folder"; static final String LAST_SEEN_DATA_SET_FILE_PROPERTY = "last-seen-data-set-file"; static final String FILE_TYPES_PROPERTY = "file-types"; @@ -77,6 +79,7 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask private File lastSeenDataSetFile; + private List<Pattern> dataSetTypePatterns; private List<String> fileTypes; private File blastDatabasesFolder; private File tmpFolder; @@ -86,17 +89,24 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask @Override public void setUp(String pluginName, Properties properties) { + List<String> dataSetTypeRegexs = PropertyUtils.getMandatoryList(properties, DATASET_TYPES_PROPERTY); + dataSetTypePatterns = new ArrayList<Pattern>(); + for (String regex : dataSetTypeRegexs) + { + try + { + dataSetTypePatterns.add(Pattern.compile(regex)); + } catch (PatternSyntaxException ex) + { + throw new ConfigurationFailureException("Property '" + DATASET_TYPES_PROPERTY + + "' has invalid regular expression '" + regex + "': " + ex.getMessage()); + } + } fileTypes = Arrays.asList(properties.getProperty(FILE_TYPES_PROPERTY, DEFAULT_FILE_TYPES).split(" +")); operationLog.info("File types: " + fileTypes); lastSeenDataSetFile = getFile(properties, LAST_SEEN_DATA_SET_FILE_PROPERTY, DEFAULT_LAST_SEEN_DATA_SET_FILE); - blastDatabasesFolder = getFile(properties, BLAST_DATABASES_FOLDER_PROPERTY, DEFAULT_BLAST_DATABASES_FOLDER); - operationLog.info("BLAST databases folder: " + blastDatabasesFolder); - tmpFolder = new File(blastDatabasesFolder, "tmp"); - FileUtilities.deleteRecursively(tmpFolder); - if (tmpFolder.mkdirs() == false) - { - throw new ConfigurationFailureException("Couldn't create folder '" + tmpFolder + "'."); - } + setUpBlastDatabasesFolder(properties); + setUpBlastTempFolder(properties); String blastToolDirectory = getBLASTToolDirectory(properties); makeblastdb = blastToolDirectory + "makeblastdb"; if (process(makeblastdb, "-version") == false) @@ -107,7 +117,53 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask makembindex = blastToolDirectory + "makembindex"; } + + private void setUpBlastDatabasesFolder(Properties properties) + { + blastDatabasesFolder = getFile(properties, BLAST_DATABASES_FOLDER_PROPERTY, DEFAULT_BLAST_DATABASES_FOLDER); + operationLog.info("BLAST databases folder: " + blastDatabasesFolder); + if (blastDatabasesFolder.exists()) + { + if (blastDatabasesFolder.isFile()) + { + throw new ConfigurationFailureException("BLAST databases folder '" + blastDatabasesFolder + + "' is an existing file."); + } + } else + { + if (blastDatabasesFolder.mkdirs() == false) + { + throw new ConfigurationFailureException("Couldn't create BLAST databases folder '" + + blastDatabasesFolder + "'."); + } + } + } + private void setUpBlastTempFolder(Properties properties) + { + String tempFolderProperty = properties.getProperty(BLAST_TEMP_FOLDER_PROPERTY); + if (tempFolderProperty == null) + { + tmpFolder = new File(blastDatabasesFolder, "tmp"); + } else + { + tmpFolder = new File(tempFolderProperty); + } + if (tmpFolder.exists()) + { + boolean success = FileUtilities.deleteRecursively(tmpFolder); + if (success == false) + { + operationLog.warn("Couldn't delete temp folder '" + tmpFolder + "'."); + } + } + if (tmpFolder.mkdirs() == false) + { + throw new ConfigurationFailureException("Couldn't create temp folder '" + tmpFolder + "'."); + } + operationLog.info("Temp folder '" + tmpFolder + "' created."); + } + private File getFile(Properties properties, String pathProperty, String defaultPath) { String path = properties.getProperty(pathProperty); @@ -136,7 +192,7 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask } for (AbstractExternalData dataSet : dataSets) { - if (dataSet.tryGetAsDataSet() != null && dataSet.isAvailable()) + if (dataSet.tryGetAsDataSet() != null && dataSet.isAvailable() && dataSetTypeMatches(dataSet)) { try { @@ -150,6 +206,19 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask updateLastSeenEventId(dataSet.getId()); } } + + private boolean dataSetTypeMatches(AbstractExternalData dataSet) + { + String dataSetType = dataSet.getDataSetType().getCode(); + for (Pattern pattern : dataSetTypePatterns) + { + if (pattern.matcher(dataSetType).matches()) + { + return true; + } + } + return false; + } private void createBlastDatabase(AbstractExternalData dataSet, IHierarchicalContentProvider contentProvider) { @@ -175,6 +244,8 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask "-title", databaseName, "-out", databaseFile); if (success == false) { + operationLog.error("Creation of BLAST database failed for data set '" + dataSetCode + + "'. Temporary fasta file: " + fastaFile); break; } File databaseSeqFile = new File(databaseFile + ".nsq"); @@ -197,7 +268,7 @@ public class BlastDatabaseCreationMaintenanceTask implements IMaintenanceTask return process(Arrays.asList(command)); } - private boolean process(List<String> command) + boolean process(List<String> command) { ProcessResult processResult = ProcessExecutionHelper.run(command, operationLog, machineLog); if (processResult.isOK()) diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTaskTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTaskTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0adc1099d30fd5f4547c9515de12375317eaf873 --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/BlastDatabaseCreationMaintenanceTaskTest.java @@ -0,0 +1,447 @@ +/* + * Copyright 2014 ETH Zuerich, SIS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.etlserver.plugins; + +import static ch.systemsx.cisd.etlserver.plugins.BlastDatabaseCreationMaintenanceTask.BLAST_DATABASES_FOLDER_PROPERTY; +import static ch.systemsx.cisd.etlserver.plugins.BlastDatabaseCreationMaintenanceTask.BLAST_TEMP_FOLDER_PROPERTY; +import static ch.systemsx.cisd.etlserver.plugins.BlastDatabaseCreationMaintenanceTask.BLAST_TOOLS_DIRECTORY_PROPERTY; +import static ch.systemsx.cisd.etlserver.plugins.BlastDatabaseCreationMaintenanceTask.DATASET_TYPES_PROPERTY; +import static ch.systemsx.cisd.etlserver.plugins.BlastDatabaseCreationMaintenanceTask.FILE_TYPES_PROPERTY; +import static ch.systemsx.cisd.etlserver.plugins.BlastDatabaseCreationMaintenanceTask.LAST_SEEN_DATA_SET_FILE_PROPERTY; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; + +import org.apache.log4j.Level; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; +import ch.systemsx.cisd.common.filesystem.FileUtilities; +import ch.systemsx.cisd.common.logging.BufferedAppender; +import ch.systemsx.cisd.common.test.RecordingMatcher; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.DefaultFileBasedHierarchicalContentFactory; +import ch.systemsx.cisd.openbis.dss.generic.shared.IConfigProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ContainerDataSetBuilder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.DataSetBuilder; + +import de.schlichtherle.io.File; + +/** + * @author Franz-Josef Elmer + */ +public class BlastDatabaseCreationMaintenanceTaskTest extends AbstractFileSystemTestCase +{ + private static final String INFO_PREFIX = "INFO OPERATION." + BlastDatabaseCreationMaintenanceTask.class.getSimpleName() + " - "; + private static final String ERROR_PREFIX = "ERROR OPERATION." + BlastDatabaseCreationMaintenanceTask.class.getSimpleName() + " - "; + + private static final class MockMaintenanceTask extends BlastDatabaseCreationMaintenanceTask + { + private final List<List<String>> commands = new ArrayList<List<String>>(); + + private final IConfigProvider configProvider; + + private final IEncapsulatedOpenBISService service; + + private final IHierarchicalContentProvider contentProvider; + + private boolean[] processSuccesses; + + private int indexOfNextProcessSuccessValue; + + MockMaintenanceTask(IConfigProvider configProvider, IEncapsulatedOpenBISService service, + IHierarchicalContentProvider contentProvider) + { + this.configProvider = configProvider; + this.service = service; + this.contentProvider = contentProvider; + + } + + void setProcessSuccesses(boolean... processSuccesses) + { + this.processSuccesses = processSuccesses; + indexOfNextProcessSuccessValue = 0; + } + + @Override + boolean process(List<String> command) + { + commands.add(command); + return processSuccesses[indexOfNextProcessSuccessValue++ % processSuccesses.length]; + } + + String getCommands() + { + StringBuilder builder = new StringBuilder(); + for (List<String> command : commands) + { + for (int i = 0; i < command.size(); i++) + { + if (i > 0) + { + builder.append(' '); + } + builder.append(command.get(i)); + } + builder.append('\n'); + } + return builder.toString(); + } + + @Override + IConfigProvider getConfigProvider() + { + return configProvider; + } + + @Override + IEncapsulatedOpenBISService getOpenBISService() + { + return service; + } + + @Override + IHierarchicalContentProvider getContentProvider() + { + return contentProvider; + } + } + + private BufferedAppender logRecorder; + + private Mockery context; + + private IConfigProvider configProvider; + + private IEncapsulatedOpenBISService service; + + private IHierarchicalContentProvider contentProvider; + + private MockMaintenanceTask maintenanceTask; + + private File store; + + @BeforeMethod + public void setUpTask() + { + logRecorder = new BufferedAppender("%-5p %c - %m%n", Level.INFO); + context = new Mockery(); + configProvider = context.mock(IConfigProvider.class); + service = context.mock(IEncapsulatedOpenBISService.class); + contentProvider = context.mock(IHierarchicalContentProvider.class); + maintenanceTask = new MockMaintenanceTask(configProvider, service, contentProvider); + maintenanceTask.setProcessSuccesses(true); + store = new File(workingDirectory, "store"); + store.mkdirs(); + context.checking(new Expectations() + { + { + allowing(configProvider).getStoreRoot(); + will(returnValue(store)); + } + }); + } + + @AfterMethod + public void tearDown() + { + context.assertIsSatisfied(); + } + + @Test + public void testSetUpMissingDataSetTypesProperty() + { + try + { + maintenanceTask.setUp("", new Properties()); + fail("ConfigurationFailureException expected."); + } catch (ConfigurationFailureException ex) + { + assertEquals("Given key '" + BlastDatabaseCreationMaintenanceTask.DATASET_TYPES_PROPERTY + + "' not found in properties '[]'", ex.getMessage()); + } + context.assertIsSatisfied(); + } + + @Test + public void testSetUpInvalidDataSetTypeRegex() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, "[a-z"); + try + { + maintenanceTask.setUp("", properties); + fail("ConfigurationFailureException expected."); + } catch (ConfigurationFailureException ex) + { + assertEquals("Property '" + DATASET_TYPES_PROPERTY + "' has invalid regular expression '[A-Z': " + + "Unclosed character class near index 3\n[A-Z\n ^", ex.getMessage()); + } + context.assertIsSatisfied(); + } + + @Test + public void testWrongBlastToolsFolder() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, ".+"); + maintenanceTask.setProcessSuccesses(false); + + maintenanceTask.setUp("", properties); + + assertEquals(INFO_PREFIX + "File types: [.fasta, .fa, .fsa]\n" + + INFO_PREFIX + "BLAST databases folder: " + store + "/blast-databases\n" + + INFO_PREFIX + "Temp folder '" + store + "/blast-databases/tmp' created.\n" + + ERROR_PREFIX + "BLAST isn't installed or property '" + BLAST_TOOLS_DIRECTORY_PROPERTY + + "' hasn't been correctly specified.", logRecorder.getLogContent()); + context.assertIsSatisfied(); + } + + @Test + public void testMinimumSetUp() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, ".+"); + + maintenanceTask.setUp("BLAST databases creation", properties); + + assertEquals(INFO_PREFIX + "File types: [.fasta, .fa, .fsa]\n" + + INFO_PREFIX + "BLAST databases folder: " + store + "/blast-databases\n" + + INFO_PREFIX + "Temp folder '" + store + "/blast-databases/tmp' created.", + logRecorder.getLogContent()); + assertEquals("makeblastdb -version\n", maintenanceTask.getCommands()); + context.assertIsSatisfied(); + } + + @Test + public void testExecuteOneDataSetWithThreeFastaFiles() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, "BLAST.*"); + maintenanceTask.setUp("", properties); + AbstractExternalData ds1 = new ContainerDataSetBuilder(1L).type("BLAST_CONTAINER").code("DS-1").getContainerDataSet(); + AbstractExternalData ds2 = new DataSetBuilder(2L).type("NOBLAST").code("DS-2") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + AbstractExternalData ds3 = new DataSetBuilder(3L).type("BLAST").code("DS-3") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + AbstractExternalData ds4 = new DataSetBuilder(3L).type("BLAST").code("DS-4") + .status(DataSetArchivingStatus.ARCHIVED).getDataSet(); + RecordingMatcher<TrackingDataSetCriteria> lastSeenIdMatcher = prepareListNewerDataSet(ds4, ds2, ds3, ds1); + File dataSetFolder1 = new File(workingDirectory, "data-set-example1"); + File dataFolder = new File(dataSetFolder1, "data"); + dataFolder.mkdirs(); + FileUtilities.writeToFile(new File(dataSetFolder1, "fasta.txt"), ">1\nGATTACA\n"); + FileUtilities.writeToFile(new File(dataSetFolder1, "fasta1.fa"), ">2\nGATTACA\nGATTACA\n"); + FileUtilities.writeToFile(new File(dataFolder, "fasta2.fa"), ">3\nIJAB\n"); + prepareContentProvider(ds3, dataSetFolder1); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < 11e5; i++) + { + stringBuilder.append("GATTACA".charAt(i % 7)); + } + // Creating a big sequence dummy file in order to trigger index creation + FileUtilities.writeToFile(new File(store, "blast-databases/DS-3-prot.nsq"), stringBuilder.toString()); + + maintenanceTask.execute(); + + assertEquals(INFO_PREFIX + "File types: [.fasta, .fa, .fsa]\n" + + INFO_PREFIX + "BLAST databases folder: " + store + "/blast-databases\n" + + INFO_PREFIX + "Temp folder '" + store + "/blast-databases/tmp' created.\n" + + INFO_PREFIX + "Scan 4 data sets for creating BLAST databases.", logRecorder.getLogContent()); + assertEquals("makeblastdb -version\n" + + "makeblastdb -in " + store.getAbsolutePath() + "/blast-databases/tmp/DS-3-nucl.fa" + + " -dbtype nucl -title DS-3-nucl -out " + store.getAbsolutePath() + "/blast-databases/DS-3-nucl\n" + + "makeblastdb -in " + store.getAbsolutePath() + "/blast-databases/tmp/DS-3-prot.fa" + + " -dbtype prot -title DS-3-prot -out " + store.getAbsolutePath() + "/blast-databases/DS-3-prot\n" + + "makembindex -iformat blastdb -input " + store.getAbsolutePath() + "/blast-databases/DS-3-prot" + + " -old_style_index false\n", + maintenanceTask.getCommands()); + assertEquals("TITLE all-nucl\nDBLIST DS-3-nucl", + FileUtilities.loadToString(new File(store, "blast-databases/all-nucl.nal")).trim()); + assertEquals("TITLE all-prot\nDBLIST DS-3-prot", + FileUtilities.loadToString(new File(store, "blast-databases/all-prot.nal")).trim()); + assertEquals("[]", Arrays.asList(new File(store, "blast-databases/tmp").listFiles()).toString()); + assertEquals(0L, lastSeenIdMatcher.recordedObject().getLastSeenDataSetId()); + context.assertIsSatisfied(); + } + + @Test + public void testExecuteThreeDataSetsWhereTwoHaveFastaFiles() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, ".*"); + maintenanceTask.setUp("", properties); + AbstractExternalData ds1 = new DataSetBuilder(1L).type("NOBLAST").code("DS1") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + AbstractExternalData ds2 = new DataSetBuilder(2L).type("BLAST").code("DS2") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + AbstractExternalData ds3 = new DataSetBuilder(3L).type("BLAST").code("DS3") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + RecordingMatcher<TrackingDataSetCriteria> lastSeenIdMatcher = prepareListNewerDataSet(ds3, ds2, ds1); + File dataSetFolder1 = new File(workingDirectory, "data-set-example1"); + dataSetFolder1.mkdirs(); + FileUtilities.writeToFile(new File(dataSetFolder1, "fasta.txt"), ">1\nGATTACA\n"); + prepareContentProvider(ds1, dataSetFolder1); + File dataSetFolder2 = new File(workingDirectory, "data-set-example2"); + dataSetFolder2.mkdirs(); + FileUtilities.writeToFile(new File(dataSetFolder2, "fasta.fa"), ">2\nGATTACA\nGATTACA\n"); + prepareContentProvider(ds2, dataSetFolder2); + File dataSetFolder3 = new File(workingDirectory, "data-set-example3"); + dataSetFolder3.mkdirs(); + FileUtilities.writeToFile(new File(dataSetFolder3, "fasta.fasta"), ">3\nGATTACA\nGATTACA\nGATTACA\n"); + prepareContentProvider(ds3, dataSetFolder3); + + maintenanceTask.execute(); + + assertEquals(INFO_PREFIX + "File types: [.fasta, .fa, .fsa]\n" + + INFO_PREFIX + "BLAST databases folder: " + store + "/blast-databases\n" + + INFO_PREFIX + "Temp folder '" + store + "/blast-databases/tmp' created.\n" + + INFO_PREFIX + "Scan 3 data sets for creating BLAST databases.", logRecorder.getLogContent()); + assertEquals("makeblastdb -version\n" + + "makeblastdb -in " + store.getAbsolutePath() + "/blast-databases/tmp/DS2-nucl.fa" + + " -dbtype nucl -title DS2-nucl -out " + store.getAbsolutePath() + "/blast-databases/DS2-nucl\n" + + "makeblastdb -in " + store.getAbsolutePath() + "/blast-databases/tmp/DS3-nucl.fa" + + " -dbtype nucl -title DS3-nucl -out " + store.getAbsolutePath() + "/blast-databases/DS3-nucl\n", + maintenanceTask.getCommands()); + assertEquals("TITLE all-nucl\nDBLIST DS2-nucl DS3-nucl", + FileUtilities.loadToString(new File(store, "blast-databases/all-nucl.nal")).trim()); + assertEquals(false, new File(store, "blast-databases/all-prot.nal").exists()); + assertEquals("[]", Arrays.asList(new File(store, "blast-databases/tmp").listFiles()).toString()); + assertEquals(0L, lastSeenIdMatcher.recordedObject().getLastSeenDataSetId()); + context.assertIsSatisfied(); + } + + @Test + public void testExecuteFaileds() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, ".*"); + maintenanceTask.setUp("", properties); + AbstractExternalData ds1 = new DataSetBuilder(1L).type("BLAST").code("DS1") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + RecordingMatcher<TrackingDataSetCriteria> lastSeenIdMatcher = prepareListNewerDataSet(ds1); + File dataSetFolder1 = new File(workingDirectory, "data-set-example1"); + dataSetFolder1.mkdirs(); + FileUtilities.writeToFile(new File(dataSetFolder1, "fasta.fa"), ">1\nGATTACA\n"); + prepareContentProvider(ds1, dataSetFolder1); + maintenanceTask.setProcessSuccesses(false); + + maintenanceTask.execute(); + + assertEquals(INFO_PREFIX + "File types: [.fasta, .fa, .fsa]\n" + + INFO_PREFIX + "BLAST databases folder: " + store + "/blast-databases\n" + + INFO_PREFIX + "Temp folder '" + store + "/blast-databases/tmp' created.\n" + + INFO_PREFIX + "Scan 1 data sets for creating BLAST databases.\n" + + ERROR_PREFIX + "Creation of BLAST database failed for data set 'DS1'. Temporary fasta file: " + + store + "/blast-databases/tmp/DS1-nucl.fa", logRecorder.getLogContent()); + assertEquals("makeblastdb -version\n" + + "makeblastdb -in " + store.getAbsolutePath() + "/blast-databases/tmp/DS1-nucl.fa" + + " -dbtype nucl -title DS1-nucl -out " + store.getAbsolutePath() + "/blast-databases/DS1-nucl\n", + maintenanceTask.getCommands()); + assertEquals(false, new File(store, "blast-databases/all-nucl.nal").exists()); + assertEquals(false, new File(store, "blast-databases/all-prot.nal").exists()); + assertEquals("[]", Arrays.asList(new File(store, "blast-databases/tmp").listFiles()).toString()); + assertEquals(0L, lastSeenIdMatcher.recordedObject().getLastSeenDataSetId()); + context.assertIsSatisfied(); + } + + @Test + public void testExecuteTwiceWithNonDefaultParameters() + { + Properties properties = new Properties(); + properties.setProperty(DATASET_TYPES_PROPERTY, ".*"); + File blastDatabasesFolder = new File(workingDirectory, "blast-dbs"); + properties.setProperty(BLAST_DATABASES_FOLDER_PROPERTY, blastDatabasesFolder.toString()); + File tempFolder = new File(workingDirectory, "temp"); + properties.setProperty(BLAST_TEMP_FOLDER_PROPERTY, tempFolder.toString()); + properties.setProperty(BLAST_TOOLS_DIRECTORY_PROPERTY, "/usr/bin/blast"); + properties.setProperty(FILE_TYPES_PROPERTY, ".txt .f"); + File lastSeenFile = new File(workingDirectory, "last.txt"); + properties.setProperty(LAST_SEEN_DATA_SET_FILE_PROPERTY, lastSeenFile.toString()); + maintenanceTask.setUp("", properties); + AbstractExternalData ds1 = new DataSetBuilder(11L).type("BLAST").code("DS1") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + RecordingMatcher<TrackingDataSetCriteria> lastSeenIdMatcher = prepareListNewerDataSet(ds1); + File dataSetFolder1 = new File(workingDirectory, "data-set-example1"); + dataSetFolder1.mkdirs(); + FileUtilities.writeToFile(new File(dataSetFolder1, "fasta.txt"), ">1\nGATTACA\n"); + prepareContentProvider(ds1, dataSetFolder1); + maintenanceTask.execute(); + AbstractExternalData ds2 = new DataSetBuilder(12L).type("BLAST").code("DS2") + .status(DataSetArchivingStatus.AVAILABLE).getDataSet(); + lastSeenIdMatcher = prepareListNewerDataSet(ds2); + prepareContentProvider(ds2, dataSetFolder1); + + maintenanceTask.execute(); + + assertEquals(INFO_PREFIX + "File types: [.txt, .f]\n" + + INFO_PREFIX + "BLAST databases folder: " + blastDatabasesFolder + "\n" + + INFO_PREFIX + "Temp folder '" + tempFolder + "' created.\n" + + INFO_PREFIX + "Scan 1 data sets for creating BLAST databases.\n" + + INFO_PREFIX + "Scan 1 data sets for creating BLAST databases.", logRecorder.getLogContent()); + assertEquals("/usr/bin/blast/makeblastdb -version\n" + + "/usr/bin/blast/makeblastdb -in " + tempFolder.getAbsolutePath() + "/DS1-nucl.fa" + + " -dbtype nucl -title DS1-nucl -out " + blastDatabasesFolder.getAbsolutePath() + "/DS1-nucl\n" + + "/usr/bin/blast/makeblastdb -in " + tempFolder.getAbsolutePath() + "/DS2-nucl.fa" + + " -dbtype nucl -title DS2-nucl -out " + blastDatabasesFolder.getAbsolutePath() + "/DS2-nucl\n", + maintenanceTask.getCommands()); + assertEquals("TITLE all-nucl\nDBLIST DS1-nucl DS2-nucl", + FileUtilities.loadToString(new File(blastDatabasesFolder, "all-nucl.nal")).trim()); + assertEquals(false, new File(store, "blast-databases/all-prot.nal").exists()); + assertEquals("[]", Arrays.asList(tempFolder.listFiles()).toString()); + assertEquals(11L, lastSeenIdMatcher.recordedObject().getLastSeenDataSetId()); + assertEquals("12", FileUtilities.loadToString(lastSeenFile).trim()); + context.assertIsSatisfied(); + } + + private void prepareContentProvider(final AbstractExternalData dataSet, final File dataSetFolder) + { + context.checking(new Expectations() + { + { + one(contentProvider).asContent(dataSet); + will(returnValue(new DefaultFileBasedHierarchicalContentFactory().asHierarchicalContent(dataSetFolder, null))); + } + }); + } + + private RecordingMatcher<TrackingDataSetCriteria> prepareListNewerDataSet(final AbstractExternalData... dataSets) + { + final RecordingMatcher<TrackingDataSetCriteria> recordingMatcher = new RecordingMatcher<TrackingDataSetCriteria>(); + context.checking(new Expectations() + { + { + one(service).listNewerDataSets(with(recordingMatcher)); + will(returnValue(new ArrayList<AbstractExternalData>(Arrays.asList(dataSets)))); + } + }); + return recordingMatcher; + } + +}