diff --git a/bds/source/java/ch/systemsx/cisd/bds/Constants.java b/bds/source/java/ch/systemsx/cisd/bds/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..a8f2415d6778578b2ddd907842eb933ff277ece3 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/Constants.java @@ -0,0 +1,33 @@ +/* + * Copyright 2007 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.bds; + +/** + * Some constants used inside the <i>BDS</i> library + * + * @author Christian Ribeaud + */ +public final class Constants +{ + + /** The only accepted path separator (system independent). */ + public final static char PATH_SEPARATOR = '/'; + + private Constants() { + // Can not be instantiated. + } +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java b/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java index 0304ac73034a64017484f8892e1c5f688559a4cb..75fe887dd0ae20afebae8dc3978fb932be6d4e0b 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java +++ b/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java @@ -16,7 +16,7 @@ package ch.systemsx.cisd.bds; -import java.util.Map; +import java.util.Set; import ch.systemsx.cisd.bds.handler.ChecksumHandler; import ch.systemsx.cisd.bds.handler.MappingFileHandler; @@ -60,7 +60,8 @@ public class DataStructureV1_0 extends AbstractDataStructure private final void registerHandlers() { - mappingFileHandler = new MappingFileHandler(getMetaDataDirectory(), getStandardData(), getOriginalData()); + mappingFileHandler = + new MappingFileHandler(getMetaDataDirectory(), getStandardData(), getOriginalData(), false); registerHandler(mappingFileHandler); registerHandler(new ChecksumHandler(getMetaDataDirectory().makeDirectory(ChecksumHandler.CHECKSUM_DIRECTORY), getOriginalData())); @@ -253,9 +254,9 @@ public class DataStructureV1_0 extends AbstractDataStructure mappingFileHandler.addReference(reference); } - public final Map<String, Reference> getStandardOriginalMapping() + public final Set<Reference> getStandardOriginalMapping() { - return mappingFileHandler.getStandardOriginalMapping(); + return mappingFileHandler.getReferences(); } // diff --git a/bds/source/java/ch/systemsx/cisd/bds/Reference.java b/bds/source/java/ch/systemsx/cisd/bds/Reference.java index 10e29533fbc7f234b70827976be8b1f62f72543c..854859b23c4dcf1861146ca0bd8b6e6313a73a03 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/Reference.java +++ b/bds/source/java/ch/systemsx/cisd/bds/Reference.java @@ -23,9 +23,6 @@ package ch.systemsx.cisd.bds; */ public final class Reference { - /** The only accepted path separator (system independent). */ - public final static char PATH_SEPARATOR = '/'; - private final String path; private final String originalPath; @@ -71,4 +68,35 @@ public final class Reference { return referenceType; } + + // + // Object + // + + @Override + public final boolean equals(final Object obj) + { + if (obj == this) + { + return true; + } + if (obj instanceof Reference == false) + { + return false; + } + final Reference that = (Reference) obj; + return that.path.equals(path); + } + + @Override + public final int hashCode() + { + return path.hashCode(); + } + + @Override + public final String toString() + { + return getPath(); + } } diff --git a/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java index 1c61153d728706990b04bf55ab49ab535eb3b439..aa6016e62c5252717c29718ecb649439445af23d 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java +++ b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java @@ -27,7 +27,7 @@ import java.util.List; import org.apache.commons.io.IOUtils; -import ch.systemsx.cisd.bds.Reference; +import ch.systemsx.cisd.bds.Constants; import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; import ch.systemsx.cisd.bds.storage.INode; @@ -81,7 +81,7 @@ class ChecksumBuilder private void addChecksum(PrintWriter printWriter, String path, INode node) { - String nodePath = (path == null ? "" : path + Reference.PATH_SEPARATOR) + node.getName(); + String nodePath = (path == null ? "" : path + Constants.PATH_SEPARATOR) + node.getName(); if (node instanceof IFile) { IFile file = (IFile) node; diff --git a/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java b/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java index d0222927db54a8d79b06542972f50da9b8bac071..e5a539316d6b1655524e10aa037f340119ef1f2a 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java +++ b/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java @@ -16,13 +16,10 @@ package ch.systemsx.cisd.bds.handler; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Collection; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.List; -import java.util.Map; +import java.util.Set; import ch.systemsx.cisd.bds.DataStructureException; import ch.systemsx.cisd.bds.IDataStructureHandler; @@ -38,19 +35,20 @@ import ch.systemsx.cisd.bds.storage.IDirectory; */ public final class MappingFileHandler implements IDataStructureHandler { - private final Map<String, Reference> standardOriginalMapping = new LinkedHashMap<String, Reference>(); + private final Set<Reference> references = new HashSet<Reference>(); /** The directory the mapping is going to be written to. */ private final IDirectory mappingDirectory; /** The root of {@link Reference#getPath()}. Usually the path to <code>standard</code> directory. */ - @SuppressWarnings("unused") private final IDirectory pathRoot; /** The root of {@link Reference#getOriginalPath()}. Usually the path to <code>original</code> directory. */ - @SuppressWarnings("unused") private final IDirectory originalPathRoot; + /** Whether we should allow call to {@link #assertValid()}. */ + private final boolean doValidation; + /** * The mapping relating <i>standard</i> with <i>original</i> data. * <p> @@ -61,7 +59,7 @@ public final class MappingFileHandler implements IDataStructureHandler public static final String MAPPING_FILE = "standard_original_mapping"; public MappingFileHandler(final IDirectory mappingDirectory, final IDirectory pathRoot, - final IDirectory originalPathRoot) + final IDirectory originalPathRoot, final boolean doValidation) { assert mappingDirectory != null : "Given mapping directory can not be null."; assert pathRoot != null : "Given path root can not be null."; @@ -69,6 +67,7 @@ public final class MappingFileHandler implements IDataStructureHandler this.mappingDirectory = mappingDirectory; this.pathRoot = pathRoot; this.originalPathRoot = originalPathRoot; + this.doValidation = doValidation; } /** @@ -76,9 +75,9 @@ public final class MappingFileHandler implements IDataStructureHandler * * @return an unmodifiable version of this map. */ - public final Map<String, Reference> getStandardOriginalMapping() + public final Set<Reference> getReferences() { - return Collections.unmodifiableMap(standardOriginalMapping); + return Collections.unmodifiableSet(references); } /** @@ -89,18 +88,17 @@ public final class MappingFileHandler implements IDataStructureHandler public final void addReference(final Reference reference) throws DataStructureException { assert reference != null : "Unspecified reference."; - final String path = reference.getPath(); - if (standardOriginalMapping.containsKey(path)) + if (references.contains(reference)) { - throw new DataStructureException("There is already a reference for file '" + path + "'."); + throw new DataStructureException("There is already a reference for file '" + reference + "'."); } - standardOriginalMapping.put(path, reference); + references.add(reference); } private final void loadStandardOriginalMapping() { final List<String> mappingLines = Utilities.getStringList(mappingDirectory, MAPPING_FILE); - standardOriginalMapping.clear(); + references.clear(); for (int i = 0; i < mappingLines.size(); i++) { String referenceDefinition = mappingLines.get(i); @@ -118,25 +116,23 @@ public final class MappingFileHandler implements IDataStructureHandler + ": missing second tab character: " + referenceDefinition); } final ReferenceType type = ReferenceType.resolveByShortName(referenceDefinition.substring(i1 + 1, i2)); - standardOriginalMapping.put(path, new Reference(path, referenceDefinition.substring(i2 + 1), type)); + references.add(new Reference(path, referenceDefinition.substring(i2 + 1), type)); } } - - // TODO 2007-11-30, Christian Ribeaud: list all nodes present in the standard directory. + private final String createMappingFile() { - final StringWriter writer = new StringWriter(); - final PrintWriter printWriter = new PrintWriter(writer, true); - final Collection<Reference> values = standardOriginalMapping.values(); - for (final Reference reference : values) + final StringBuilder builder = new StringBuilder(); + for (final Reference reference : references) { final String path = reference.getPath(); final String shortName = reference.getReferenceType().getShortName(); final String originalPath = reference.getOriginalPath(); - printWriter.println(path + "\t" + shortName + "\t" + originalPath); + builder.append(path).append("\t"); + builder.append(shortName).append("\t"); + builder.append(originalPath).append("\n"); } - printWriter.close(); - return writer.toString(); + return builder.toString(); } // @@ -145,9 +141,24 @@ public final class MappingFileHandler implements IDataStructureHandler public final void assertValid() throws DataStructureException { - // TODO 2007-11-29, Christian Ribeaud: validation of loaded references. Note that this could interfere with - // checksum validation. To validate a checksum, the file must exist. So we would not need to check the original - // path existence here. + if (doValidation == false) + { + return; + } + final String errMsg = "Node '%s' not found in directory '%s'"; + for (final Reference reference : references) + { + final String path = reference.getPath(); + if (pathRoot.tryGetNode(path) == null) + { + throw new DataStructureException(String.format(errMsg, path, pathRoot)); + } + final String originalPath = reference.getOriginalPath(); + if (originalPathRoot.tryGetNode(originalPath) == null) + { + throw new DataStructureException(String.format(errMsg, originalPath, originalPathRoot)); + } + } } public final void performClosing() diff --git a/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java b/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java index 400bd2fee1880a14af753590df6fd6f461a61702..c2ed9e925f357620f7a28cec9b09f71fe06aba26 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java +++ b/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java @@ -146,6 +146,8 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement public final INode tryGetStandardNodeAt(final int channel, final Location plateLocation, final Location wellLocation) { checkChannel(channel); + assert plateLocation != null : "Plate location can not be null."; + assert wellLocation != null : "Well location can not be null."; checkLocation(getPlateGeometry(), plateLocation); checkLocation(getWellGeometry(), wellLocation); final IDirectory standardDir = getStandardDataDirectory(); diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java index f35e0adf9fa1a19a6d225301608fc9d052f847b4..8de90a92d2a130a9b413242a88fb67282e2bce8d 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java @@ -30,12 +30,20 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; */ abstract class AbstractNode implements INode { - protected final static void moveFileToDirectory(final File source, final File directory) + protected final static File moveFileToDirectory(final File source, final File directory, final String nameOrNull) throws EnvironmentFailureException { assert source != null; assert directory != null && directory.isDirectory(); - final File destination = new File(directory, source.getName()); + final String newName; + if (nameOrNull == null) + { + newName = source.getName(); + } else + { + newName = nameOrNull; + } + final File destination = new File(directory, newName); if (destination.exists() == false) { final boolean successful = source.renameTo(destination); @@ -45,6 +53,7 @@ abstract class AbstractNode implements INode .getAbsolutePath(), directory.getAbsolutePath()); } } + return destination; } protected final File nodeFile; @@ -84,7 +93,7 @@ abstract class AbstractNode implements INode public final void moveTo(final File directory) { - moveFileToDirectory(nodeFile, directory); + moveFileToDirectory(nodeFile, directory, null); } public boolean isValid() diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java index 6729aadf881250bbd3819eeff34b7d78a9ca4204..7738983457b06be8bc90443b8911bd804120d8e5 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java @@ -21,6 +21,7 @@ import java.util.Iterator; import org.apache.commons.io.FileUtils; +import ch.systemsx.cisd.bds.Constants; import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; import ch.systemsx.cisd.bds.storage.ILink; @@ -52,6 +53,29 @@ final class Directory extends AbstractNode implements IDirectory return ((AbstractNode) node).nodeFile; } + private final java.io.File findFile(final String name) + { + final java.io.File[] files = FileUtilities.listFiles(nodeFile); + for (final java.io.File file : files) + { + if (file.getName().equals(name)) + { + return file; + } + } + return null; + } + + private final static String cleanName(final String name) + { + final int index = name.indexOf(Constants.PATH_SEPARATOR); + if (index == 0) + { + return name.substring(1); + } + return name; + } + // // IDirectory // @@ -59,10 +83,19 @@ final class Directory extends AbstractNode implements IDirectory public final INode tryGetNode(final String name) { assert name != null : "Given name can not be null."; - final java.io.File[] files = FileUtilities.listFiles(nodeFile); - for (java.io.File file : files) + final String path = cleanName(name); + final int index = path.indexOf(Constants.PATH_SEPARATOR); + if (index > -1) { - if (file.getName().equals(name)) + final java.io.File dir = findFile(path.substring(0, index)); + if (dir != null) + { + return NodeFactory.createDirectoryNode(dir).tryGetNode(path.substring(index + 1)); + } + } else + { + final java.io.File file = findFile(path); + if (file != null) { return NodeFactory.createNode(file); } @@ -106,7 +139,7 @@ final class Directory extends AbstractNode implements IDirectory final java.io.File newFile = new java.io.File(nodeFile, file.getName()); if (move) { - moveFileToDirectory(file, nodeFile); + moveFileToDirectory(file, nodeFile, null); } else { try @@ -135,7 +168,7 @@ final class Directory extends AbstractNode implements IDirectory final java.io.File fileLink = LinkMakerProvider.getDefaultLinkMaker().tryCreateLink(file, nodeFile, name); if (fileLink != null) { - final Link link = NodeFactory.createLinkNode(fileLink); + final Link link = (Link) NodeFactory.createLinkNode(name, file); link.setParent(this); return link; } @@ -190,7 +223,7 @@ final class Directory extends AbstractNode implements IDirectory assert node != null : "Node can not be null"; assert name != null : "Name can not be null."; final java.io.File file = getNodeFile(node); - return addFile(file, true); + return NodeFactory.createNode(moveFileToDirectory(file, nodeFile, name)); } public final void removeNode(final INode node) diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java index b647b9e5ad18ab72b1716f535681e5a91c0e0aba..cac88fa1ff0bda1e3ce3a7acb64a20c63ba84040 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java @@ -20,6 +20,7 @@ import java.io.IOException; import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; +import ch.systemsx.cisd.bds.storage.ILink; import ch.systemsx.cisd.bds.storage.INode; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; @@ -37,6 +38,10 @@ public final class NodeFactory /** * A <code>INode</code> factory method for given <var>file</var>. + * <p> + * IMPORTANT NOTE: we compare the absolute path against the canonical one to found out whether it is a link or not. + * This only works for <i>symbolic</i> links and not for <i>hard</i> links. + * </p> */ public static INode createNode(final java.io.File file) throws EnvironmentFailureException { @@ -67,11 +72,29 @@ public final class NodeFactory } } - public final static Link createLinkNode(final java.io.File file) throws EnvironmentFailureException + /** + * Creates a new <code>ILink</code> with given <var>name</var> which points to given <var>file</var>. + */ + public final static ILink createLinkNode(final String name, final java.io.File file) + { + assert file != null : "Given file can not be null."; + assert name != null : "Given name can not be null."; + return new Link(name, createNode(file)); + } + + /** + * Creates a new <code>ILink</code>. + * <p> + * IMPORTANT NOTE: we compare the absolute path against the canonical one to found out whether it is a link or not. + * This only works for <i>symbolic</i> links and not for <i>hard</i> links. + * </p> + */ + public final static ILink createLinkNode(final java.io.File file) throws EnvironmentFailureException { - final String absolutePath = file.getAbsolutePath(); final String canonicalPath = getCanonicalPath(file); - assert absolutePath.equals(canonicalPath) == false : "Given file must be a link."; + final String absolutePath = file.getAbsolutePath(); + assert absolutePath.equals(canonicalPath) == false : String.format( + "Given file must be a link [absolute=%s,canonical=%s].", absolutePath, canonicalPath); return new Link(file.getName(), createNode(new java.io.File(canonicalPath))); } diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureV1_0Test.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureV1_0Test.java index 389a4f8481708adaf0aff33b7ef38f3d4199d8ee..599a006cdd6771b60787c2d217ca47035f401b93 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureV1_0Test.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureV1_0Test.java @@ -25,7 +25,7 @@ import static org.testng.AssertJUnit.fail; import java.io.IOException; import java.util.Date; import java.util.Iterator; -import java.util.Map; +import java.util.Set; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -203,9 +203,9 @@ public final class DataStructureV1_0Test extends AbstractFileSystemTestCase { dataStructure.create(); dataStructure.addReference(new Reference("a", "b", ReferenceType.IDENTICAL)); - Map<String, Reference> mapping = dataStructure.getStandardOriginalMapping(); + final Set<Reference> mapping = dataStructure.getStandardOriginalMapping(); assertEquals(1, mapping.size()); - Reference actualReference = mapping.get("a"); + final Reference actualReference = mapping.iterator().next(); assertEquals("a", actualReference.getPath()); assertEquals(ReferenceType.IDENTICAL, actualReference.getReferenceType()); assertEquals("b", actualReference.getOriginalPath()); @@ -232,7 +232,7 @@ public final class DataStructureV1_0Test extends AbstractFileSystemTestCase dataStructure.create(); try { - dataStructure.getStandardOriginalMapping().put("a", null); + dataStructure.getStandardOriginalMapping().add(null); fail("DataStructureException expected"); } catch (UnsupportedOperationException e) { @@ -401,16 +401,8 @@ public final class DataStructureV1_0Test extends AbstractFileSystemTestCase assertEquals(experimentRegistrator, reloadedDataStructure.getExperimentRegistrator()); assertEquals(measurementEntity, reloadedDataStructure.getMeasurementEntity()); assertEquals(ProcessingType.RAW_DATA, reloadedDataStructure.getProcessingType()); - Map<String, Reference> mapping = reloadedDataStructure.getStandardOriginalMapping(); + final Set<Reference> mapping = reloadedDataStructure.getStandardOriginalMapping(); assertEquals(2, mapping.size()); - Reference reference = mapping.get("a/b/c"); - assertEquals("a/b/c", reference.getPath()); - assertEquals(ReferenceType.IDENTICAL, reference.getReferenceType()); - assertEquals("a6b8/x.t", reference.getOriginalPath()); - reference = mapping.get("a78/jjh"); - assertEquals("a78/jjh", reference.getPath()); - assertEquals(ReferenceType.TRANSFORMED, reference.getReferenceType()); - assertEquals("a b/x\tt", reference.getOriginalPath()); checkFormattedData(reloadedDataStructure.getFormattedData()); IDirectory metaDataDir = Utilities.getSubDirectory(root, DIR_METADATA); diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/ChecksumHandlerTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/ChecksumHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..05512b28f8d868aa491fe925da6de615cbd3b7ec --- /dev/null +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/ChecksumHandlerTest.java @@ -0,0 +1,29 @@ +/* + * Copyright 2007 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.bds.handler; + +import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase; + +/** + * Test cases for corresponding {@link ChecksumHandler} class. + * + * @author Christian Ribeaud + */ +public final class ChecksumHandlerTest extends AbstractFileSystemTestCase +{ + +} diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/MappingFileHandlerTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/MappingFileHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3f23790a846c0557b04e6e1e9d8774ee81bdb8fc --- /dev/null +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/MappingFileHandlerTest.java @@ -0,0 +1,145 @@ +/* + * Copyright 2007 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.bds.handler; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.AssertJUnit.fail; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.bds.DataStructureException; +import ch.systemsx.cisd.bds.Reference; +import ch.systemsx.cisd.bds.ReferenceType; +import ch.systemsx.cisd.bds.storage.IDirectory; +import ch.systemsx.cisd.bds.storage.filesystem.NodeFactory; +import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase; + +/** + * Test cases for corresponding {@link MappingFileHandler} class. + * + * @author Christian Ribeaud + */ +public final class MappingFileHandlerTest extends AbstractFileSystemTestCase +{ + + private final static String MAPPING_FILE_CONTENT = + "row1/row2_column1.tiff\tI\toriginal1.tiff\n" + "row2/row3_column2.tiff\tI\toriginal2.tiff\n"; + + private MappingFileHandler handler; + + private final void prepareMappingFileHandler() + { + final IDirectory mappingDirectory = NodeFactory.createDirectoryNode(workingDirectory); + final IDirectory originalDirectory = mappingDirectory.makeDirectory("original"); + final IDirectory standardDirectory = mappingDirectory.makeDirectory("standard"); + handler = new MappingFileHandler(mappingDirectory, standardDirectory, originalDirectory, true); + } + + private final void writeMappingFile() throws IOException + { + final File mappingFile = new File(workingDirectory, MappingFileHandler.MAPPING_FILE); + FileUtils.writeStringToFile(mappingFile, MAPPING_FILE_CONTENT); + } + + private final void createMappedFiles() throws IOException + { + final File original = new File(workingDirectory, "original"); + final File standard = new File(workingDirectory, "standard"); + final File original1 = new File(original, "original1.tiff"); + FileUtils.touch(original1); + assertTrue(original1.exists()); + final File original2 = new File(original, "original2.tiff"); + FileUtils.touch(original2); + assertTrue(original2.exists()); + final File row1 = new File(standard, "row1"); + row1.mkdir(); + final File row2 = new File(standard, "row2"); + row2.mkdir(); + final File standard1 = new File(row1, "row2_column1.tiff"); + FileUtils.touch(standard1); + assertTrue(standard1.exists()); + final File standard2 = new File(row2, "row3_column2.tiff"); + FileUtils.touch(standard2); + assertTrue(standard2.exists()); + } + + @Override + @BeforeMethod + public void setup() throws IOException + { + super.setup(); + prepareMappingFileHandler(); + } + + @Test + public final void testAddReference() + { + try + { + handler.addReference(null); + fail("Null value not allowed."); + } catch (AssertionError ex) + { + // Nothing to do here. + } + handler.addReference(new Reference("1", "2", ReferenceType.IDENTICAL)); + try + { + handler.addReference(new Reference("1", "2", ReferenceType.IDENTICAL)); + fail("Can not added the same reference twice."); + } catch (DataStructureException ex) + { + // Nothing to do here. + } + } + + @Test + public final void testPerformOpening() throws IOException + { + writeMappingFile(); + handler.performOpening(); + assertEquals(2, handler.getReferences().size()); + } + + @Test + public final void testPerformClosing() throws IOException + { + handler.addReference(new Reference("row1/row2_column1.tiff", "original1.tiff", ReferenceType.IDENTICAL)); + handler.addReference(new Reference("row2/row3_column2.tiff", "original2.tiff", ReferenceType.IDENTICAL)); + handler.performClosing(); + final File mappingFile = new File(workingDirectory, MappingFileHandler.MAPPING_FILE); + assertTrue(mappingFile.exists()); + final String mapping = FileUtils.readFileToString(mappingFile); + mapping.equals(MAPPING_FILE_CONTENT); + } + + @Test + public final void testAssertValid() throws IOException + { + writeMappingFile(); + handler.performOpening(); + createMappedFiles(); + handler.assertValid(); + } + +} \ No newline at end of file diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSDataStructureV1_0Test.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSDataStructureV1_0Test.java index b3087dda8bc71e771be5cf7a0235f21b88a17157..f6a69e39e5061edeaf4a05cbde59d67b1144c72b 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSDataStructureV1_0Test.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSDataStructureV1_0Test.java @@ -21,12 +21,10 @@ import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; -import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.apache.commons.io.FileUtils; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -38,8 +36,6 @@ import ch.systemsx.cisd.bds.Format; import ch.systemsx.cisd.bds.FormatParameter; import ch.systemsx.cisd.bds.IDataStructure; import ch.systemsx.cisd.bds.IFormattedData; -import ch.systemsx.cisd.bds.storage.IDirectory; -import ch.systemsx.cisd.bds.storage.INode; import ch.systemsx.cisd.bds.storage.filesystem.FileStorage; import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase; @@ -109,51 +105,7 @@ public final class HCSDataStructureV1_0Test extends AbstractFileSystemTestCase assertEquals(format, formattedData.getFormat()); } - @Test - public final void testGetNodeAt() throws IOException - { - dataStructure.create(); - DataStructureV1_0Test.createExampleDataStructure(storage); - setFormatAndFormatParameters(); - final IDirectory standardData = dataStructure.getStandardData(); - final IDirectory channelDir = standardData.makeDirectory(Channel.CHANNEL + "1"); - final IDirectory plateRowDir = channelDir.makeDirectory(HCSImageFormattedData.ROW + "1"); - final IDirectory plateColumnDir = plateRowDir.makeDirectory(HCSImageFormattedData.COLUMN + "1"); - final String wellFileName = HCSImageFormattedData.createWellFileName(new Location(1, 1)); - final File wellFile = new File(workingDirectory, wellFileName); - FileUtils.writeStringToFile(wellFile, "This is an image..."); - plateColumnDir.addFile(wellFile, true); - final IHCSFormattedData formattedData = (IHCSFormattedData) dataStructure.getFormattedData(); - try - { - formattedData.tryGetStandardNodeAt(3, new Location(1, 1), new Location(1, 1)); - fail("3 > 2"); - } catch (IndexOutOfBoundsException ex) - { - // Nothing to do here. - } - try - { - formattedData.tryGetStandardNodeAt(2, new Location(1, 1), new Location(1, 1)); - fail("No directory named 'channel2' found."); - } catch (DataStructureException ex) - { - assertTrue(ex.getMessage().indexOf("'channel2'") > -1); - } - try - { - formattedData.tryGetStandardNodeAt(1, new Location(1, 3), new Location(1, 1)); - fail("Given geometry '2x3' does not contain location '[x=1,y=3]'."); - } catch (IllegalArgumentException ex) - { - assertTrue(ex.getMessage().indexOf("does not contain location") > -1); - } - final INode node = formattedData.tryGetStandardNodeAt(1, new Location(1, 1), new Location(1, 1)); - assertEquals("row1_column1.tiff", node.getName()); - dataStructure.close(); - } - - @Test + @Test(dependsOnMethods="testGetFormatedData") public final void testHCSImageDataStructure() { // Creating... diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java index 24849e23e56d6d29b90098e36bb79a064288d6a5..7a4ff83429f9be9524fd07b6607b57eab5ad732b 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java @@ -18,6 +18,8 @@ package ch.systemsx.cisd.bds.hcs; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; import java.io.File; @@ -36,6 +38,8 @@ import ch.systemsx.cisd.bds.DataStructureV1_0; import ch.systemsx.cisd.bds.FormatedDataFactory; import ch.systemsx.cisd.bds.IFormatParameters; import ch.systemsx.cisd.bds.storage.IDirectory; +import ch.systemsx.cisd.bds.storage.IFile; +import ch.systemsx.cisd.bds.storage.ILink; import ch.systemsx.cisd.bds.storage.INode; import ch.systemsx.cisd.bds.storage.filesystem.NodeFactory; import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase; @@ -86,9 +90,9 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase private final void prepareStandardNode() { standardNode = NodeFactory.createDirectoryNode(workingDirectory); - final IDirectory channel1 = standardNode.makeDirectory("channel1"); - final IDirectory row1 = channel1.makeDirectory("row1"); - leafDirectory = row1.makeDirectory("column2"); + final IDirectory channel1 = standardNode.makeDirectory(Channel.CHANNEL + "1"); + final IDirectory row1 = channel1.makeDirectory(HCSImageFormattedData.ROW + "1"); + leafDirectory = row1.makeDirectory(HCSImageFormattedData.COLUMN + "2"); } private final void addParameterCheckExpectations(final Expectations exp) @@ -163,9 +167,9 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase public final void testAddStandardNodeWithOriginalData() throws IOException { final String originalFileName = "original.txt"; - FileUtils.touch(new File(workingDirectory, originalFileName)); + FileUtils.writeStringToFile(new File(workingDirectory, originalFileName), "This is my original file..."); final int channelIndex = 1; - final IDirectory workingDirectoryNode = NodeFactory.createDirectoryNode(workingDirectory); + final IDirectory originalNode = NodeFactory.createDirectoryNode(workingDirectory); context.checking(new Expectations() { { @@ -175,25 +179,166 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase will(returnValue(standardNode)); one(directory).tryGetNode(DataStructureV1_0.DIR_ORIGINAL); - will(returnValue(workingDirectoryNode)); + will(returnValue(originalNode)); one(formatParameters).getValue(HCSImageFormat1_0.CONTAINS_ORIGINAL_DATA); will(returnValue(Boolean.FALSE)); } }); final INode node = formattedData.addStandardNode(originalFileName, channelIndex, PLATE_LOCATION, WELL_LOCATION); + final String standardFileName = "row2_column1.tiff"; assertNotNull(node); - assertEquals(originalFileName, node.getName()); - final INode standardFile = leafDirectory.tryGetNode(originalFileName); + assertEquals(standardFileName, node.getName()); + // Look at the standard leaf directory if the node is there as well. + final INode standardFile = leafDirectory.tryGetNode(standardFileName); assertNotNull(standardFile); - assertEquals(originalFileName, standardFile.getName()); + assertTrue(standardFile instanceof IFile); + assertEquals(standardFileName, standardFile.getName()); + // Node should no longer be in original directory + assertNull(originalNode.tryGetNode(originalFileName)); context.assertIsSatisfied(); } @Test - public final void testTryGetStandardNodeAt() + public final void testAddStandardNodeWithoutOriginalData() throws IOException { + final String originalFileName = "original.tiff"; + FileUtils.writeStringToFile(new File(workingDirectory, originalFileName), "This is my original file..."); + final int channelIndex = 1; + final IDirectory originalNode = NodeFactory.createDirectoryNode(workingDirectory); + context.checking(new Expectations() + { + { + addParameterCheckExpectations(this); + + exactly(2).of(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); + will(returnValue(standardNode)); + + one(directory).tryGetNode(DataStructureV1_0.DIR_ORIGINAL); + will(returnValue(originalNode)); + + one(formatParameters).getValue(HCSImageFormat1_0.CONTAINS_ORIGINAL_DATA); + will(returnValue(Boolean.TRUE)); + } + }); + final INode node = formattedData.addStandardNode(originalFileName, channelIndex, PLATE_LOCATION, WELL_LOCATION); + final String standardFileName = "row2_column1.tiff"; + assertNotNull(node); + assertTrue(node instanceof ILink); + assertEquals(standardFileName, node.getName()); + // Look at the standard leaf directory if the node is there as well. + final INode standardFile = leafDirectory.tryGetNode(standardFileName); + assertNotNull(standardFile); + assertTrue(standardFile instanceof IFile); + assertEquals(standardFileName, standardFile.getName()); + // Node should still be in original directory + assertNotNull(originalNode.tryGetNode(originalFileName)); + context.assertIsSatisfied(); + } + + @Test + public final void testTryGetStandardNodeAtWithNoFile() + { + final int channelIndex = 1; + context.checking(new Expectations() + { + { + addParameterCheckExpectations(this); + + one(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); + will(returnValue(standardNode)); + } + }); + final INode node = formattedData.tryGetStandardNodeAt(channelIndex, PLATE_LOCATION, WELL_LOCATION); + assertNull(node); + context.assertIsSatisfied(); + } + + @Test + public final void testTryGetStandardNodeAtWithFile() throws IOException + { + final File file = new File(workingDirectory, "row2_column1.tiff"); + FileUtils.writeStringToFile(file, "This is my original file..."); + leafDirectory.addFile(file, true); + final int channelIndex = 1; + context.checking(new Expectations() + { + { + addParameterCheckExpectations(this); + + one(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); + will(returnValue(standardNode)); + } + }); + final INode node = formattedData.tryGetStandardNodeAt(channelIndex, PLATE_LOCATION, WELL_LOCATION); + assertNotNull(node); + context.assertIsSatisfied(); + } + + @Test + public final void testTryGetStandardNodeAtWithWrongChannelIndex() + { + context.checking(new Expectations() + { + { + one(formatParameters).getValue(ChannelList.NUMBER_OF_CHANNELS); + will(returnValue(createChannelList())); + } + }); + try + { + formattedData.tryGetStandardNodeAt(2, null, null); + fail("2 > 1"); + } catch (IndexOutOfBoundsException ex) + { + // Nothing to do here. + } + context.assertIsSatisfied(); + } + + @Test + public final void testTryGetStandardNodeAtWithWrongPlateLocation() + { + context.checking(new Expectations() + { + { + one(formatParameters).getValue(ChannelList.NUMBER_OF_CHANNELS); + will(returnValue(createChannelList())); + + one(formatParameters).getValue(PlateGeometry.PLATE_GEOMETRY); + will(returnValue(new Geometry(2, 2))); + } + }); + try + { + final Location location = new Location(2, 3); + formattedData.tryGetStandardNodeAt(1, location, location); + fail("Given geometry '2x2' does not contain location '[x=2,y=3]'"); + } catch (IllegalArgumentException ex) + { + // Nothing to do here. + } + context.assertIsSatisfied(); + } + + @Test + public final void testTryGetStandardNodeAtWithWrongWellLocation() + { + context.checking(new Expectations() + { + { + addParameterCheckExpectations(this); + } + }); + try + { + formattedData.tryGetStandardNodeAt(1, new Location(2, 2), new Location(3, 2)); + fail("Given geometry '2x2' does not contain location '[x=3,y=2]'"); + } catch (IllegalArgumentException ex) + { + // Nothing to do here. + } context.assertIsSatisfied(); } } \ No newline at end of file