diff --git a/bds/source/java/ch/systemsx/cisd/bds/Channel.java b/bds/source/java/ch/systemsx/cisd/bds/Channel.java new file mode 100644 index 0000000000000000000000000000000000000000..72b6d170c5555e48eac990c13437e307c6da0108 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/Channel.java @@ -0,0 +1,110 @@ +/* + * 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; + +import ch.systemsx.cisd.bds.storage.IDirectory; + +/** + * A channel is composed of only one child: <code>wavelength</code>. + * <p> + * Each channel has its <code>counter</code> which uniquely identifies it. + * </p> + * + * @author Christian Ribeaud + */ +public final class Channel implements IStorable +{ + + static final String CHANNEL = "channel"; + + static final String WAVELENGTH = "wavelength"; + + private final int counter; + + private final int wavelength; + + public Channel(final int counter, final int wavelength) + { + assert counter > 0 : "Given counter must be > 0."; + this.counter = counter; + this.wavelength = wavelength; + } + + public final int getWavelength() + { + return wavelength; + } + + final static Channel loadFrom(final IDirectory directory) + { + final String name = directory.getName(); + assert name.startsWith(CHANNEL); + return new Channel(parseCounter(name), Utilities.getNumber(directory, WAVELENGTH)); + } + + private static int parseCounter(final String name) + { + try + { + return Integer.parseInt(name.substring(CHANNEL.length())); + } catch (NumberFormatException ex) + { + throw new DataStructureException(String.format("Could not parse the channel number in '%s'", name), ex); + } + } + + // + // IStorable + // + + public final void saveTo(final IDirectory directory) + { + final IDirectory channelDirectory = directory.makeDirectory(CHANNEL + counter); + channelDirectory.addKeyValuePair(WAVELENGTH, getWavelength() + ""); + } + + // + // Object + // + + @Override + public final boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + if (obj instanceof Channel == false) + { + return false; + } + final Channel channel = (Channel) obj; + return channel.counter == counter; + } + + @Override + public final int hashCode() + { + return 17 * 37 + counter; + } + + @Override + public final String toString() + { + return CHANNEL + counter + "[" + wavelength + "=" + getWavelength() + "]"; + } +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/ChannelList.java b/bds/source/java/ch/systemsx/cisd/bds/ChannelList.java new file mode 100644 index 0000000000000000000000000000000000000000..e13741a1d9fed616630d3d973e2ee2f833424422 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/ChannelList.java @@ -0,0 +1,80 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import ch.systemsx.cisd.bds.storage.IDirectory; +import ch.systemsx.cisd.bds.storage.INode; + +/** + * The list of encapsulated <code>Channels</code> available here. + * + * @author Christian Ribeaud + */ +public final class ChannelList implements IStorable +{ + static final String NUMBER_OF_CHANNELS = "number_of_channels"; + + private final List<Channel> channels; + + public ChannelList(final List<Channel> channels) + { + assert channels.size() > 0 : "At least one channel must be specified."; + this.channels = channels; + } + + /** + * Loads all <code>Channels</code> from the specified directory. + * + * @throws DataStructureException if the <code>Channels</code> could be loaded. + */ + final static ChannelList loadFrom(final IDirectory directory) + { + final List<Channel> channels = new ArrayList<Channel>(); + for (INode node : directory) + { + if (node.getName().startsWith(Channel.CHANNEL)) + { + assert node instanceof IDirectory : "Must be an IDirectory"; + channels.add(Channel.loadFrom((IDirectory) node)); + } + } + return new ChannelList(channels); + } + + /** Returns an unmodifiable list of <code>Channel</code>. */ + public final List<Channel> getChannels() + { + return Collections.unmodifiableList(channels); + } + + // + // IStorable + // + + public final void saveTo(final IDirectory directory) + { + directory.addKeyValuePair(NUMBER_OF_CHANNELS, channels.size() + ""); + for (Channel channel : channels) + { + channel.saveTo(directory); + } + } +} 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 8b55dc2b65020e23f722a869f995af609ef438ec..1447c1b2330cbf13ce52c0c5ffde3c56651afd04 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java +++ b/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java @@ -42,19 +42,21 @@ public class DataStructureV1_0 extends AbstractDataStructure static final String CHECKSUM_DIRECTORY = "md5sum"; static final String DIR_METADATA = "metadata"; - + static final String DIR_PARAMETERS = "parameters"; static final String DIR_DATA = "data"; static final String DIR_ORIGINAL = "original"; - + static final String MAPPING_FILE = "standard_original_mapping"; private static final Version VERSION = new Version(1, 0); - + private final ChecksumBuilder checksumBuilder = new ChecksumBuilder(new MD5ChecksumCalculator()); + private final Map<String, Reference> standardOriginalMapping = new LinkedHashMap<String, Reference>(); + private final FormatParameters formatParameters = new FormatParameters(); private Format format; @@ -121,7 +123,7 @@ public class DataStructureV1_0 extends AbstractDataStructure assert formatParameter != null : "Unspecified format parameter."; formatParameters.addParameter(formatParameter); } - + /** * Returns the experiment identifier. * @@ -143,7 +145,7 @@ public class DataStructureV1_0 extends AbstractDataStructure assertOpenOrCreated(); id.saveTo(getMetaDataDirectory()); } - + /** * Returns the date of registration of the experiment. * @@ -155,7 +157,7 @@ public class DataStructureV1_0 extends AbstractDataStructure assertOpenOrCreated(); return ExperimentRegistratorDate.loadFrom(getMetaDataDirectory()); } - + /** * Sets the date of registration of the experiment. */ @@ -176,14 +178,14 @@ public class DataStructureV1_0 extends AbstractDataStructure assertOpenOrCreated(); return ExperimentRegistrator.loadFrom(getMetaDataDirectory()); } - + public void setExperimentRegistrator(ExperimentRegistrator registrator) { assert registrator != null : "Unspecified experiment registrator."; assertOpenOrCreated(); registrator.saveTo(getMetaDataDirectory()); } - + /** * Returns the measurement entity. * @@ -217,7 +219,7 @@ public class DataStructureV1_0 extends AbstractDataStructure assertOpenOrCreated(); return ProcessingType.loadFrom(getMetaDataDirectory()); } - + /** * Sets the processing type. Overwrites an already set or loaded value. */ @@ -227,7 +229,7 @@ public class DataStructureV1_0 extends AbstractDataStructure assertOpenOrCreated(); type.saveTo(getMetaDataDirectory()); } - + /** * Returns the standard-original mapping. * @@ -237,7 +239,7 @@ public class DataStructureV1_0 extends AbstractDataStructure { return Collections.unmodifiableMap(standardOriginalMapping); } - + /** * Adds a reference to the standard-original mapping. * @@ -254,7 +256,7 @@ public class DataStructureV1_0 extends AbstractDataStructure } standardOriginalMapping.put(path, reference); } - + @Override protected void assertValid() { @@ -335,7 +337,7 @@ public class DataStructureV1_0 extends AbstractDataStructure standardOriginalMapping.put(path, new Reference(path, referenceDefinition.substring(i2 + 1), type)); } } - + @Override protected void performClosing() { @@ -343,9 +345,9 @@ public class DataStructureV1_0 extends AbstractDataStructure IDirectory checksumDirectory = metaDataDirectory.makeDirectory(CHECKSUM_DIRECTORY); String checksumsOfOriginal = checksumBuilder.buildChecksumsForAllFilesIn(getOriginalData()); checksumDirectory.addKeyValuePair(DIR_ORIGINAL, checksumsOfOriginal); - + formatParameters.saveTo(getParametersDirectory()); - + StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer, true); Collection<Reference> values = standardOriginalMapping.values(); @@ -358,7 +360,7 @@ public class DataStructureV1_0 extends AbstractDataStructure } printWriter.close(); metaDataDirectory.addKeyValuePair(MAPPING_FILE, writer.toString()); - + if (metaDataDirectory.tryToGetNode(Format.FORMAT_DIR) == null && format != null) { format.saveTo(metaDataDirectory); @@ -374,10 +376,10 @@ public class DataStructureV1_0 extends AbstractDataStructure { return Utilities.getOrCreateSubDirectory(root, DIR_METADATA); } - + private IDirectory getParametersDirectory() { return Utilities.getOrCreateSubDirectory(getMetaDataDirectory(), DIR_PARAMETERS); } - + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/ExperimentIdentifier.java b/bds/source/java/ch/systemsx/cisd/bds/ExperimentIdentifier.java index 5a66b75bca27e01502d594867dbe0ffff4a46d11..3540ac25f61b14017addaf82947e470fb631eead 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/ExperimentIdentifier.java +++ b/bds/source/java/ch/systemsx/cisd/bds/ExperimentIdentifier.java @@ -20,17 +20,20 @@ import ch.systemsx.cisd.bds.storage.IDirectory; /** * Identifier of the experiment which corresponds to the data. This is an immutable but extendable value object class. - * An instance of this class allows unique identification in the database. - * + * An instance of this class allows unique identification in the database. + * * @author Franz-Josef Elmer */ -public class ExperimentIdentifier +public class ExperimentIdentifier implements IStorable { static final String FOLDER = "experiment_identifier"; + static final String GROUP_CODE = "group_code"; + static final String PROJECT_CODE = "project_code"; + static final String EXPERIMENT_CODE = "experiment_code"; - + /** * Loads the experiment identifier from the specified directory. * @@ -44,14 +47,16 @@ public class ExperimentIdentifier String experimentCode = Utilities.getTrimmedString(idFolder, EXPERIMENT_CODE); return new ExperimentIdentifier(groupCode, projectCode, experimentCode); } - + private final String groupCode; + private final String projectCode; + private final String experimentCode; /** * Creates an instance for the specified codes of group, project, and experiment. - * + * * @param groupCode A non-empty string of the group code. * @param projectCode A non-empty string of the project code. * @param experimentCode A non-empty string of the experiment code. @@ -81,7 +86,7 @@ public class ExperimentIdentifier { return projectCode; } - + /** * Returns the experiment code; */ @@ -89,11 +94,15 @@ public class ExperimentIdentifier { return experimentCode; } - + + // + // IStorable + // + /** * Saves this instance to the specified directory. */ - void saveTo(IDirectory directory) + public final void saveTo(final IDirectory directory) { IDirectory folder = directory.makeDirectory(FOLDER); folder.addKeyValuePair(GROUP_CODE, groupCode); @@ -128,6 +137,5 @@ public class ExperimentIdentifier { return "[group:" + groupCode + ",project:" + projectCode + ",experiment:" + experimentCode + "]"; } - - + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistrator.java b/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistrator.java index 65d97e992be8fe9a15aacd627ac70f19a39af603..4d21cd66e391ca3db98b0d33fdaf50bafc84be47 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistrator.java +++ b/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistrator.java @@ -20,18 +20,21 @@ import ch.systemsx.cisd.bds.storage.IDirectory; /** * Registrator of the experiment which corresponds to the data. This is an immutable value object class. - * + * * @author Franz-Josef Elmer */ -public final class ExperimentRegistrator +public final class ExperimentRegistrator implements IStorable { static final String FOLDER = "experiment_registrator"; + static final String FIRST_NAME = "first_name"; + static final String SECOND_NAME = "last_name"; + static final String EMAIL = "email"; - + /** - * Loads the experiment registaror from the specified directory. + * Loads the experiment registrator from the specified directory. * * @throws DataStructureException if file missing. */ @@ -43,14 +46,16 @@ public final class ExperimentRegistrator String email = Utilities.getTrimmedString(folder, EMAIL); return new ExperimentRegistrator(firstName, secondName, email); } - + private final String firstName; + private final String secondName; + private final String email; /** * Creates an instance for the specified name and e-mail of the registrator. - * + * * @param firstName A non-empty string of the first name. * @param secondName A non-empty string of the second name. * @param email A non-empty string of the email. @@ -80,7 +85,7 @@ public final class ExperimentRegistrator { return secondName; } - + /** * Returns the email. */ @@ -88,11 +93,15 @@ public final class ExperimentRegistrator { return email; } - + + // + // IStorable + // + /** * Saves this instance to the specified directory. */ - void saveTo(IDirectory directory) + public final void saveTo(final IDirectory directory) { IDirectory folder = directory.makeDirectory(FOLDER); folder.addKeyValuePair(FIRST_NAME, firstName); @@ -127,6 +136,5 @@ public final class ExperimentRegistrator { return firstName + " " + secondName + ", e-mail:" + email; } - - + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistratorDate.java b/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistratorDate.java index e2a842040e287f9c6b935fc519533d4b7616b66b..b7563dec65d968a151edf7a02078ff4070454c2a 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistratorDate.java +++ b/bds/source/java/ch/systemsx/cisd/bds/ExperimentRegistratorDate.java @@ -23,15 +23,16 @@ import java.util.Date; import ch.systemsx.cisd.bds.storage.IDirectory; /** - * Immutable class which holds the date of registration of an experiment. - * + * Immutable class which holds the date of registration of an experiment. + * * @author Franz-Josef Elmer */ -public final class ExperimentRegistratorDate +public final class ExperimentRegistratorDate implements IStorable { static final String FILE_NAME = "experiment_registration_date"; + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); - + static ExperimentRegistratorDate loadFrom(IDirectory directory) { String dateAsString = Utilities.getTrimmedString(directory, FILE_NAME); @@ -43,9 +44,9 @@ public final class ExperimentRegistratorDate throw new DataStructureException("Couldn't be parsed as a date: " + dateAsString); } } - + private final Date date; - + /** * Creates an instance for the specified date. */ @@ -61,11 +62,15 @@ public final class ExperimentRegistratorDate { return date; } - + + // + // IStorable + // + /** * Saves this instance to the specified directory. */ - void saveTo(IDirectory directory) + public final void saveTo(IDirectory directory) { directory.addKeyValuePair(FILE_NAME, DATE_FORMAT.format(date)); } @@ -95,5 +100,5 @@ public final class ExperimentRegistratorDate { return DATE_FORMAT.format(date); } - + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/Format.java b/bds/source/java/ch/systemsx/cisd/bds/Format.java index 2c6b91ab4a9114902162cc549a1e95e439bd09ea..ed66c35b628860f156e32e9d2b0c60facfdf7cd3 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/Format.java +++ b/bds/source/java/ch/systemsx/cisd/bds/Format.java @@ -22,13 +22,15 @@ import ch.systemsx.cisd.bds.storage.INode; /** * Inmutable value object of a versioned format. - * + * * @author Franz-Josef Elmer */ -public class Format +public class Format implements IStorable { static final String FORMAT_CODE_FILE = "format_code"; + static final String FORMAT_DIR = "format"; + static final String FORMAT_VARIANT_FILE = "format_variant"; /** @@ -64,9 +66,11 @@ public class Format } return new Format(formatCode, formatVersion, variant); } - + private final String code; + private final Version version; + private final String variant; /** @@ -80,7 +84,7 @@ public class Format this.version = version; variant = variantOrNull; } - + /** * Returns the format code. */ @@ -107,7 +111,11 @@ public class Format return variant; } - void saveTo(IDirectory directory) + // + // IStorable + // + + public final void saveTo(final IDirectory directory) { IDirectory dir = directory.makeDirectory(FORMAT_DIR); dir.addKeyValuePair(FORMAT_CODE_FILE, code); @@ -130,7 +138,7 @@ public class Format return false; } Format format = (Format) obj; - return format.code.equals(code) && format.version.equals(version) + return format.code.equals(code) && format.version.equals(version) && (format.variant == null ? null == variant : format.variant.equals(variant)); } diff --git a/bds/source/java/ch/systemsx/cisd/bds/FormatParameter.java b/bds/source/java/ch/systemsx/cisd/bds/FormatParameter.java index 77a834c23a08faf20ef7c619537a4baf1b63a3be..1f6f40d729a10a346e369d81723163e4f4ec1926 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/FormatParameter.java +++ b/bds/source/java/ch/systemsx/cisd/bds/FormatParameter.java @@ -17,18 +17,19 @@ package ch.systemsx.cisd.bds; /** - * A format parameter with a name and a string value. - * + * A format parameter with a name and a string value. + * * @author Franz-Josef Elmer */ public final class FormatParameter { private final String name; + private final String value; /** * Creates an instance for the specified name and value. - * + * * @param name A non-empty string as the name of the parameter. * @param value A non-<code>null</code> string as the value. */ diff --git a/bds/source/java/ch/systemsx/cisd/bds/FormatParameters.java b/bds/source/java/ch/systemsx/cisd/bds/FormatParameters.java index 94f6e217afe81c131ecf0e1fba1fdc19b99e450c..317734aa8de707673cc41548a9b19609754f21c1 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/FormatParameters.java +++ b/bds/source/java/ch/systemsx/cisd/bds/FormatParameters.java @@ -26,10 +26,10 @@ import ch.systemsx.cisd.bds.storage.INode; /** * Implementation of {@link IFormatParameters} which allows to add {@link FormatParameter} instances. - * + * * @author Franz-Josef Elmer */ -class FormatParameters implements IFormatParameters +class FormatParameters implements IFormatParameters, IStorable { private final Map<String, FormatParameter> parameters = new LinkedHashMap<String, FormatParameter>(); @@ -45,15 +45,19 @@ class FormatParameters implements IFormatParameters } } } - - void saveTo(IDirectory directory) + + // + // IStorable + // + + public final void saveTo(final IDirectory directory) { for (FormatParameter parameter : parameters.values()) { directory.addKeyValuePair(parameter.getName(), parameter.getValue()); } } - + /** * Adds the specified parameter. * @@ -68,7 +72,7 @@ class FormatParameters implements IFormatParameters } parameters.put(name, parameter); } - + public String getValue(String parameterName) { FormatParameter formatParameter = parameters.get(parameterName); diff --git a/bds/source/java/ch/systemsx/cisd/bds/FormattedDataContext.java b/bds/source/java/ch/systemsx/cisd/bds/FormattedDataContext.java index 876bb3e091a51675f4601d17f96bc2da3aeb576d..c1c60e5360ac35a82c6fd7b1303fe08d7932ba0a 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/FormattedDataContext.java +++ b/bds/source/java/ch/systemsx/cisd/bds/FormattedDataContext.java @@ -19,15 +19,17 @@ package ch.systemsx.cisd.bds; import ch.systemsx.cisd.bds.storage.IDirectory; /** - * Context of {@link IFormattedData}. Argument of all constructores of concrete implementations of - * {@link IFormattedData}. - * + * Context of {@link IFormattedData}. Argument of all constructors of concrete implementations of + * {@link IFormattedData}. + * * @author Franz-Josef Elmer */ class FormattedDataContext { private final IDirectory dataDirectory; + private final Format format; + private final IFormatParameters formatParameters; FormattedDataContext(IDirectory dataDirectory, Format format, IFormatParameters formatParameters) diff --git a/bds/source/java/ch/systemsx/cisd/bds/Geometry.java b/bds/source/java/ch/systemsx/cisd/bds/Geometry.java new file mode 100644 index 0000000000000000000000000000000000000000..abafed7aa277a901640006320d85029be66645b8 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/Geometry.java @@ -0,0 +1,133 @@ +/* + * 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; + +import ch.systemsx.cisd.bds.storage.IDirectory; + +/** + * A <code>Geometry</code> is composed of 2 dimensions: + * <ul> + * <li>rows</li> + * <li>columns</li> + * </ul> + * <p> + * This class is not <code>abstract</code> but {@link #getGeometryDirectoryName()} must be overridden by subclasses in + * order to work properly. + * </p> + * + * @author Christian Ribeaud + */ +public class Geometry implements IStorable +{ + static final String NOT_POSITIVE = "Given number '%d' must be > 0."; + + final static String ROWS = "rows"; + + final static String COLUMNS = "columns"; + + private final int rows; + + private final int columns; + + protected Geometry(final int rows, final int columns) + { + assert columns > 0 : String.format(NOT_POSITIVE, columns); + this.columns = columns; + assert rows > 0 : String.format(NOT_POSITIVE, rows); + this.rows = rows; + } + + /** Return the number of columns this <code>Geometry</code> is composed of. */ + public final int getColumns() + { + return columns; + } + + /** Return the number of rows this <code>Geometry</code> is composed of. */ + public final int getRows() + { + return rows; + } + + private final String toString(int number) + { + return Integer.toString(number); + } + + /** + * Loads the geometry from the specified directory. + */ + final static Geometry loadFrom(final IDirectory directory, final String geometryDirectoryName) + { + final IDirectory geometryFolder = Utilities.getSubDirectory(directory, geometryDirectoryName); + return new Geometry(Utilities.getNumber(geometryFolder, ROWS), Utilities.getNumber(geometryFolder, COLUMNS)); + } + + // + // IStorable + // + + public final void saveTo(final IDirectory directory) + { + final IDirectory geometryDirectory = directory.makeDirectory(getGeometryDirectoryName()); + geometryDirectory.addKeyValuePair(ROWS, toString(getRows())); + geometryDirectory.addKeyValuePair(COLUMNS, toString(getColumns())); + } + + /** + * Returns the directory name where this <code>Geometry</code> is saved. + * <p> + * Currently this method is not supported and must be implemented. + * </p> + */ + protected String getGeometryDirectoryName() + { + throw new UnsupportedOperationException(); + } + + // + // Object + // + + @Override + public final boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + if (obj instanceof Geometry == false) + { + return false; + } + final Geometry geometry = (Geometry) obj; + return geometry.rows == rows && geometry.columns == columns; + } + + @Override + public final int hashCode() + { + + return 17 * 37 + getRows() + getColumns(); + } + + @Override + public final String toString() + { + return getRows() + "x" + getColumns(); + } +} \ No newline at end of file diff --git a/bds/source/java/ch/systemsx/cisd/bds/IStorable.java b/bds/source/java/ch/systemsx/cisd/bds/IStorable.java new file mode 100644 index 0000000000000000000000000000000000000000..954c5d2aa85ff4d354318b0bd8ab5a3b6e899b5f --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/IStorable.java @@ -0,0 +1,35 @@ +/* + * 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; + +import ch.systemsx.cisd.bds.storage.IDirectory; + +/** + * Each implementation knows how to save itself in given <code>IDirectory</code>. + * <p> + * Note that each implementation should have a <code>static</code> method <code>loadFrom(IDirectory)</code> that + * knows how to construct itself from given <code>IDirectory</code>. + * </p> + * + * @author Christian Ribeaud + */ +public interface IStorable +{ + + /** Saves this implementation to given <var>directory</var>. */ + public void saveTo(final IDirectory directory); +} \ No newline at end of file diff --git a/bds/source/java/ch/systemsx/cisd/bds/MeasurementEntity.java b/bds/source/java/ch/systemsx/cisd/bds/MeasurementEntity.java index 46ae7f3c066bbb75bcddb44df72b6a320c3400ae..a9861f378eba6d8e135624c768ff6208f15b3423 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/MeasurementEntity.java +++ b/bds/source/java/ch/systemsx/cisd/bds/MeasurementEntity.java @@ -20,15 +20,17 @@ import ch.systemsx.cisd.bds.storage.IDirectory; /** * Enity of measurement or calculation covered by the data. This is an immutable value object class. - * + * * @author Franz-Josef Elmer */ -public final class MeasurementEntity +public final class MeasurementEntity implements IStorable { static final String FOLDER = "measurement_entity"; + static final String ENTITY_TYPE_DESCRIPTION = "entity_type_description"; + static final String ENTITY_CODE = "entity_code"; - + /** * Loads the enity from the specified directory. * @@ -41,8 +43,9 @@ public final class MeasurementEntity String entityCode = Utilities.getTrimmedString(folder, ENTITY_CODE); return new MeasurementEntity(entityCode, entityTypeDescription); } - + private final String entityTypeDescription; + private final String entityCode; /** @@ -74,11 +77,15 @@ public final class MeasurementEntity { return entityCode; } - + + // + // IStorable + // + /** * Saves this instance to the specified directory. */ - void saveTo(IDirectory directory) + public final void saveTo(IDirectory directory) { IDirectory folder = directory.makeDirectory(FOLDER); folder.addKeyValuePair(ENTITY_TYPE_DESCRIPTION, entityTypeDescription); @@ -111,6 +118,5 @@ public final class MeasurementEntity { return "[" + entityCode + ": " + entityTypeDescription + "]"; } - - + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/PlateGeometry.java b/bds/source/java/ch/systemsx/cisd/bds/PlateGeometry.java new file mode 100644 index 0000000000000000000000000000000000000000..bbb35951e681c6b84c61638e49647a89b87f24ca --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/PlateGeometry.java @@ -0,0 +1,54 @@ +/* + * 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; + +import ch.systemsx.cisd.bds.storage.IDirectory; + +/** + * An <code>AbstractGeometry</code> implementation suitable for <i>Plate</i>. + * + * @author Christian Ribeaud + */ +public final class PlateGeometry extends Geometry +{ + + static final String PLATE_GEOMETRY = "plate_geometry"; + + public PlateGeometry(final int rows, final int columns) + { + super(rows, columns); + } + + /** + * Loads the geometry from the specified directory. + */ + static Geometry loadFrom(final IDirectory directory) + { + return loadFrom(directory, PLATE_GEOMETRY); + } + + // + // Geometry + // + + @Override + protected final String getGeometryDirectoryName() + { + return PLATE_GEOMETRY; + } + +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/ProcessingType.java b/bds/source/java/ch/systemsx/cisd/bds/ProcessingType.java index 86a0964bb387f8d558e3fbf336f3790166fd33f4..94d4c25419e817f350ebaa014eaef932d7633f38 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/ProcessingType.java +++ b/bds/source/java/ch/systemsx/cisd/bds/ProcessingType.java @@ -18,18 +18,17 @@ package ch.systemsx.cisd.bds; import ch.systemsx.cisd.bds.storage.IDirectory; - /** * Enumeration of processing types. - * + * * @author Franz-Josef Elmer */ -public enum ProcessingType +public enum ProcessingType implements IStorable { OTHER, RAW_DATA, COMPUTED_DATA; - + static final String PROCESSING_TYPE = "processing_type"; - + /** * Resolves the specified string representation of a processing type. * @@ -47,13 +46,17 @@ public enum ProcessingType } return OTHER; } - + static ProcessingType loadFrom(IDirectory directory) { return resolve(Utilities.getTrimmedString(directory, PROCESSING_TYPE)); } - - void saveTo(IDirectory directory) + + // + // IStorable + // + + public final void saveTo(IDirectory directory) { directory.addKeyValuePair(PROCESSING_TYPE, toString()); } diff --git a/bds/source/java/ch/systemsx/cisd/bds/Utilities.java b/bds/source/java/ch/systemsx/cisd/bds/Utilities.java index bab9c8ae8ed5c340b5e4190c2301102ea5066644..a4943f6174fed67928c4147c8e83d9a04f63317f 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/Utilities.java +++ b/bds/source/java/ch/systemsx/cisd/bds/Utilities.java @@ -16,7 +16,6 @@ package ch.systemsx.cisd.bds; - import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; import ch.systemsx.cisd.bds.storage.INode; @@ -83,12 +82,14 @@ public class Utilities * @param name Name of the file. * @throws DataStructureException if the requested file does not exist. */ - public static String getString(IDirectory directory, String name) + public static String getString(final IDirectory directory, final String name) { + assert directory != null : String.format("Given directory can not be null."); + assert name != null : String.format("Given name can not be null."); INode node = directory.tryToGetNode(name); if (node == null) { - throw new DataStructureException("File '" + name + "' missing in " + directory); + throw new DataStructureException("File '" + name + "' missing in '" + directory + "'."); } if (node instanceof IFile == false) { @@ -102,4 +103,17 @@ public class Utilities { } + /** For given <code>IDirectory</code> returns the number value corresponding to given <var>name</var>. */ + public final static int getNumber(final IDirectory directory, final String name) + { + // No assertion here as 'getString(IDirectory, String)' already does it. + String value = getTrimmedString(directory, name); + try + { + return Integer.parseInt(value); + } catch (NumberFormatException ex) + { + throw new DataStructureException("Value of " + name + " version file is not a number: " + value); + } + } } diff --git a/bds/source/java/ch/systemsx/cisd/bds/Version.java b/bds/source/java/ch/systemsx/cisd/bds/Version.java index 58918ab300e16d844fc0cf7e3efd61a94d1d48c6..11721a4366375401ed19ad398a4c3016baa16d32 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/Version.java +++ b/bds/source/java/ch/systemsx/cisd/bds/Version.java @@ -19,43 +19,34 @@ package ch.systemsx.cisd.bds; import ch.systemsx.cisd.bds.storage.IDirectory; /** - * Immutable value object for the version of something. - * + * Immutable value object for the version of something. + * * @author Franz-Josef Elmer */ public final class Version { static final String VERSION = "version"; + static final String MAJOR = "major"; + static final String MINOR = "minor"; - + /** * Loads the version from the specified directory. */ static Version loadFrom(IDirectory directory) { IDirectory versionFolder = Utilities.getSubDirectory(directory, VERSION); - return new Version(getNumber(versionFolder, MAJOR), getNumber(versionFolder, MINOR)); - } - - private static int getNumber(IDirectory versionFolder, String name) - { - String value = Utilities.getTrimmedString(versionFolder, name); - try - { - return Integer.parseInt(value); - } catch (NumberFormatException ex) - { - throw new DataStructureException("Value of " + name + " version file is not a number: " + value); - } + return new Version(Utilities.getNumber(versionFolder, MAJOR), Utilities.getNumber(versionFolder, MINOR)); } - + private final int major; + private final int minor; /** * Creates a new instance for the specified major and minor number. - * + * * @param major A positive number. * @param minor A non-negative number. */ @@ -82,16 +73,16 @@ public final class Version { return minor; } - + /** - * Returns <code>true</code> if this version is backwards compatible to the specified version. That is, - * if <code>version.getMajor() == this.getMajor()</code> and <code>version.getMinor() <= this.getMinor()</code>. + * Returns <code>true</code> if this version is backwards compatible to the specified version. That is, if + * <code>version.getMajor() == this.getMajor()</code> and <code>version.getMinor() <= this.getMinor()</code>. */ public boolean isBackwardsCompatibleWith(Version version) { return version.major == major && version.minor <= minor; } - + /** * Returns the previous minor version. * @@ -105,7 +96,7 @@ public final class Version } return new Version(major, minor - 1); } - + void saveTo(IDirectory directory) { IDirectory versionFolder = directory.makeDirectory(VERSION); @@ -139,7 +130,5 @@ public final class Version { return "V" + major + "." + minor; } - - - + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/WellGeometry.java b/bds/source/java/ch/systemsx/cisd/bds/WellGeometry.java new file mode 100644 index 0000000000000000000000000000000000000000..893e9b6ef06113c77b3761912d3dd8823388de39 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/WellGeometry.java @@ -0,0 +1,54 @@ +/* + * 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; + +import ch.systemsx.cisd.bds.storage.IDirectory; + +/** + * An <code>AbstractGeometry</code> implementation suitable for <i>Well</i>. + * + * @author Christian Ribeaud + */ +public final class WellGeometry extends Geometry +{ + + static final String WELL_GEOMETRY = "well_geometry"; + + public WellGeometry(final int rows, final int columns) + { + super(rows, columns); + } + + /** + * Loads the geometry from the specified directory. + */ + static Geometry loadFrom(final IDirectory directory) + { + return loadFrom(directory, WELL_GEOMETRY); + } + + // + // Geometry + // + + @Override + protected final String getGeometryDirectoryName() + { + return WELL_GEOMETRY; + } + +} 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 108c981c2bce993cc9565669f0207d3839ff6e9c..963379eea42293a396259a6f343754b45004c649 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 @@ -30,6 +30,8 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.utilities.FileUtilities; /** + * An <code>IDirectory</code> implementation. + * * @author Franz-Josef Elmer */ class Directory extends AbstractNode implements IDirectory 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 0ae75b1d5f9947a31d329faacfed2da6484cebff..f851a4c3d93f0367cce2f0ffc9d2397dcd3424f7 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 @@ -22,11 +22,21 @@ import ch.systemsx.cisd.bds.storage.INode; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; /** + * A <code>INode</code> factory class. + * <p> + * You should prefer to use this class instead of directly instantiate the corresponding <code>INode</code> + * implementations. + * </p> + * * @author Franz-Josef Elmer */ -class NodeFactory +public final class NodeFactory { - static INode createNode(java.io.File file) throws EnvironmentFailureException + + /** + * A <code>INode</code> factory method for given <var>file</var>. + */ + public static INode createNode(final java.io.File file) throws EnvironmentFailureException { assert file != null : "Unspecified node"; String absolutePath = file.getAbsolutePath(); @@ -50,5 +60,6 @@ class NodeFactory private NodeFactory() { + // Can not be instantiated. } } diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/UtilitiesTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/UtilitiesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d16f1db54a468e7383c2c2d940cb0fb522fc660f --- /dev/null +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/UtilitiesTest.java @@ -0,0 +1,83 @@ +/* + * 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; + +import java.io.File; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.bds.storage.IDirectory; +import ch.systemsx.cisd.bds.storage.IFile; +import ch.systemsx.cisd.bds.storage.filesystem.NodeFactory; +import ch.systemsx.cisd.common.logging.LogInitializer; +import ch.systemsx.cisd.common.utilities.FileUtilities; + +import static org.testng.AssertJUnit.*; + +/** + * Test cases for corresponding {@link Utilities} class. + * + * @author Christian Ribeaud + */ +public class UtilitiesTest +{ + private static final File UNIT_TEST_ROOT_DIRECTORY = new File("targets" + File.separator + "unit-test-wd"); + + private static final File WORKING_DIRECTORY = + new File(UNIT_TEST_ROOT_DIRECTORY, UtilitiesTest.class.getSimpleName()); + + @BeforeMethod + public final void setUp() + { + LogInitializer.init(); + FileUtilities.deleteRecursively(WORKING_DIRECTORY); + WORKING_DIRECTORY.mkdirs(); + assert WORKING_DIRECTORY.isDirectory() && WORKING_DIRECTORY.listFiles().length == 0; + WORKING_DIRECTORY.deleteOnExit(); + } + + @Test + public final void testGetNumber() + { + final IDirectory directory = (IDirectory) NodeFactory.createNode(WORKING_DIRECTORY); + final String key = "age"; + final String value = "35"; + final IFile file = directory.addKeyValuePair(key, value); + final File[] listFiles = WORKING_DIRECTORY.listFiles(); + assertEquals(1, listFiles.length); + assertEquals(key, listFiles[0].getName()); + assertEquals(value, file.getStringContent().trim()); + try + { + Utilities.getNumber(null, null); + fail("Directory and name can not be null."); + } catch (AssertionError ex) + { + // Nothing to do here + } + try + { + Utilities.getNumber(directory, "doesNotExist"); + fail("File 'doesNotExist' missing"); + } catch (DataStructureException ex) + { + // Nothing to do here + } + assertEquals(35, Utilities.getNumber(directory, key)); + } +} \ No newline at end of file