diff --git a/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java b/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java
index 939286081f8532d8956ecb31952bc45acc2acb71..55adf96bcffc1db1a6bceace1feed1a5d338b650 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java
@@ -16,24 +16,30 @@
 
 package ch.systemsx.cisd.bds;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IStorage;
 
 /**
  * Abstract superclass of classes implementing {@link IDataStructure}.
- *
+ * 
  * @author Franz-Josef Elmer
  */
-abstract class AbstractDataStructure implements IDataStructure
+abstract class AbstractDataStructure implements IDataStructure, IDataStructureHandler
 {
     protected final IStorage storage;
-    
+
     protected IDirectory root;
 
-    AbstractDataStructure(IStorage storage)
+    private final List<IDataStructureHandler> handlers;
+
+    AbstractDataStructure(final IStorage storage)
     {
-        assert storage != null: "Unspecified storage.";
+        assert storage != null : "Unspecified storage.";
         this.storage = storage;
+        handlers = new ArrayList<IDataStructureHandler>();
     }
 
     private void mountStorage()
@@ -41,42 +47,71 @@ abstract class AbstractDataStructure implements IDataStructure
         storage.mount();
         root = storage.getRoot();
     }
-    
+
+    protected final void registerHandler(final IDataStructureHandler handler)
+    {
+        assert handler != null : "Given handler can not be null.";
+        handlers.add(handler);
+    }
+
     /**
      * Asserts that this instance is already opened or created otherwise a {@link IllegalStateException} is thrown.
      */
-    protected void assertOpenOrCreated()
+    protected final void assertOpenOrCreated()
     {
         if (root == null)
         {
             throw new IllegalStateException("Data structure should first be opened or created.");
         }
     }
-    
-    /**
-     * Validates this data structure and throws {@link DataStructureException} if invalid. 
-     */
-    protected abstract void assertValid(); 
-    
-    /**
-     * Performs opening specific for the concrete data structure. Will be invoked after the common part of
-     * {@link #open()} but before validation with {@link #assertValid()}. 
-     */
-    protected abstract void performOpening();
-    
+
     /**
-     * Performs closing specific for the concrete data structure. Will be invoked before validation with
-     * {@link #assertValid()}.
+     * After-creation jobs that should be done. Kind of initialization for subclasses when they create a new data
+     * structure.
+     * <p>
+     * By default this method does nothing.
+     * </p>
      */
-    protected abstract void performClosing();
-    
+    protected void afterCreation()
+    {
+    }
+
+    //
+    // IDataStructureHandler
+    //
+
+    public void assertValid()
+    {
+        for (final IDataStructureHandler handler : handlers)
+        {
+            handler.assertValid();
+        }
+    }
+
+    public void performOpening()
+    {
+        for (final IDataStructureHandler handler : handlers)
+        {
+            handler.performOpening();
+        }
+    }
+
+    public void performClosing()
+    {
+        for (final IDataStructureHandler handler : handlers)
+        {
+            handler.performClosing();
+        }
+    }
+
     //
     // IDataStructure
     //
-    
+
     public final void create()
     {
         mountStorage();
+        afterCreation();
     }
 
     public final void open()
@@ -91,7 +126,7 @@ abstract class AbstractDataStructure implements IDataStructure
         }
         assertValid();
     }
-    
+
     public final void close()
     {
         assertOpenOrCreated();
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 691d18834b4164dc97b4b53d1417c606729ec47c..532c330053ad72f8f9ccaeae9f2e59c707048b85 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/DataStructureV1_0.java
@@ -16,21 +16,12 @@
 
 package ch.systemsx.cisd.bds;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
+import ch.systemsx.cisd.bds.handler.ChecksumHandler;
+import ch.systemsx.cisd.bds.handler.MappingFileHandler;
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IStorage;
-import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 
 /**
  * Data structure Version 1.0.
@@ -39,8 +30,6 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
  */
 public class DataStructureV1_0 extends AbstractDataStructure
 {
-    public static final String CHECKSUM_DIRECTORY = "md5sum";
-
     public static final String DIR_METADATA = "metadata";
 
     public static final String DIR_PARAMETERS = "parameters";
@@ -53,23 +42,12 @@ public class DataStructureV1_0 extends AbstractDataStructure
     /** The directory where <i>standardized</i> data could be found. */
     public static final String DIR_STANDARD = "standard";
 
-    /**
-     * The mapping relating <i>standard</i> with <i>original</i> data.
-     * <p>
-     * Note that under format specific conditions this mapping file could be empty, meaning that the <i>standard</i>
-     * directory contains the real data and not only links.
-     * </p>
-     */
-    public 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 MappingFileHandler mappingFileHandler;
+
     private Format format;
 
     /**
@@ -80,12 +58,12 @@ public class DataStructureV1_0 extends AbstractDataStructure
         super(storage);
     }
 
-    /**
-     * Returns version 1.0.
-     */
-    public Version getVersion()
+    private final void registerHandlers()
     {
-        return VERSION;
+        mappingFileHandler = new MappingFileHandler(getMetaDataDirectory(), getStandardData(), getOriginalData());
+        registerHandler(mappingFileHandler);
+        registerHandler(new ChecksumHandler(getMetaDataDirectory().makeDirectory(ChecksumHandler.CHECKSUM_DIRECTORY),
+                getOriginalData()));
     }
 
     /**
@@ -106,6 +84,24 @@ public class DataStructureV1_0 extends AbstractDataStructure
         return Utilities.getOrCreateSubDirectory(getDataDirectory(), DIR_STANDARD);
     }
 
+    public final IDirectory getDataDirectory()
+    {
+        assertOpenOrCreated();
+        return Utilities.getOrCreateSubDirectory(root, DIR_DATA);
+    }
+
+    public final IDirectory getMetaDataDirectory()
+    {
+        assertOpenOrCreated();
+        return Utilities.getOrCreateSubDirectory(root, DIR_METADATA);
+    }
+
+    public final IDirectory getParametersDirectory()
+    {
+        assertOpenOrCreated();
+        return Utilities.getOrCreateSubDirectory(getMetaDataDirectory(), DIR_PARAMETERS);
+    }
+
     /**
      * Returns the formated data. This method can be called only after method {@link #setFormat(Format)} has been
      * invoked. If the format is not known {@link UnknownFormat1_0} will be assumed.
@@ -251,36 +247,31 @@ public class DataStructureV1_0 extends AbstractDataStructure
         type.saveTo(getMetaDataDirectory());
     }
 
-    /**
-     * Returns the standard-original mapping.
-     * 
-     * @return an unmodifiable version of this map.
-     */
-    public Map<String, Reference> getStandardOriginalMapping()
+    public final void addReference(final Reference reference)
     {
-        return Collections.unmodifiableMap(standardOriginalMapping);
+        assertOpenOrCreated();
+        mappingFileHandler.addReference(reference);
     }
 
-    /**
-     * Adds a reference to the standard-original mapping.
-     * 
-     * @throws DataStructureException if a reference with the same path has already been registered.
-     */
-    public void addReference(Reference reference)
+    public final Map<String, Reference> getStandardOriginalMapping()
     {
-        assert reference != null : "Unspecified reference.";
-        assertOpenOrCreated();
-        String path = reference.getPath();
-        if (standardOriginalMapping.containsKey(path))
-        {
-            throw new DataStructureException("There is already a reference for file '" + path + "'.");
-        }
-        standardOriginalMapping.put(path, reference);
+        return mappingFileHandler.getStandardOriginalMapping();
+    }
+
+    //
+    // AbstractDataStructure
+    //
+
+    @Override
+    protected void afterCreation()
+    {
+        registerHandlers();
     }
 
     @Override
-    protected void assertValid()
+    public final void assertValid()
     {
+        super.assertValid();
         if (getOriginalData().iterator().hasNext() == false)
         {
             throw new DataStructureException("Empty original data directory.");
@@ -313,94 +304,29 @@ public class DataStructureV1_0 extends AbstractDataStructure
     }
 
     @Override
-    protected void performOpening()
+    public final void performOpening()
     {
-        IDirectory metaDataDirectory = getMetaDataDirectory();
-        setFormat(Format.loadFrom(metaDataDirectory));
+        registerHandlers();
+        super.performOpening();
+        setFormat(Format.loadFrom(getMetaDataDirectory()));
         formatParameters.loadFrom(getParametersDirectory());
-        loadStandardOriginalMapping(metaDataDirectory);
-    }
-
-    private void loadStandardOriginalMapping(IDirectory metaDataDirectory)
-    {
-        StringReader stringReader = new StringReader(Utilities.getString(metaDataDirectory, MAPPING_FILE));
-        BufferedReader reader = new BufferedReader(stringReader);
-        List<String> lines = new ArrayList<String>();
-        String line;
-        try
-        {
-            while ((line = reader.readLine()) != null)
-            {
-                lines.add(line);
-            }
-        } catch (IOException ex)
-        {
-            throw new EnvironmentFailureException("Unexpected IOException.", ex);
-        }
-        standardOriginalMapping.clear();
-        for (int i = 0; i < lines.size(); i++)
-        {
-            String referenceDefinition = lines.get(i);
-            int i1 = referenceDefinition.indexOf('\t');
-            if (i1 < 0)
-            {
-                throw new DataStructureException("Error in standard-original mapping line " + (i + 1)
-                        + ": missing first tab character: " + referenceDefinition);
-            }
-            String path = referenceDefinition.substring(0, i1);
-            int i2 = referenceDefinition.indexOf('\t', i1 + 1);
-            if (i2 < 0)
-            {
-                throw new DataStructureException("Error in standard-original mapping line " + (i + 1)
-                        + ": missing second tab character: " + referenceDefinition);
-            }
-            ReferenceType type = ReferenceType.tryToResolveByShortName(referenceDefinition.substring(i1 + 1, i2));
-            standardOriginalMapping.put(path, new Reference(path, referenceDefinition.substring(i2 + 1), type));
-        }
     }
 
     @Override
-    protected void performClosing()
+    public final void performClosing()
     {
-        IDirectory metaDataDirectory = getMetaDataDirectory();
-        IDirectory checksumDirectory = metaDataDirectory.makeDirectory(CHECKSUM_DIRECTORY);
-        String checksumsOfOriginal = checksumBuilder.buildChecksumsForAllFilesIn(getOriginalData());
-        checksumDirectory.addKeyValuePair(DIR_ORIGINAL, checksumsOfOriginal);
-
+        super.performClosing();
+        final IDirectory metaDataDirectory = getMetaDataDirectory();
         formatParameters.saveTo(getParametersDirectory());
-
-        StringWriter writer = new StringWriter();
-        PrintWriter printWriter = new PrintWriter(writer, true);
-        Collection<Reference> values = standardOriginalMapping.values();
-        for (Reference reference : values)
-        {
-            String path = reference.getPath();
-            String shortName = reference.getReferenceType().getShortName();
-            String originalPath = reference.getOriginalPath();
-            printWriter.println(path + "\t" + shortName + "\t" + originalPath);
-        }
-        printWriter.close();
-        metaDataDirectory.addKeyValuePair(MAPPING_FILE, writer.toString());
-
         if (metaDataDirectory.tryToGetNode(Format.FORMAT_DIR) == null && format != null)
         {
             format.saveTo(metaDataDirectory);
         }
     }
 
-    private IDirectory getDataDirectory()
-    {
-        return Utilities.getOrCreateSubDirectory(root, DIR_DATA);
-    }
-
-    private IDirectory getMetaDataDirectory()
-    {
-        return Utilities.getOrCreateSubDirectory(root, DIR_METADATA);
-    }
-
-    private IDirectory getParametersDirectory()
+    public final Version getVersion()
     {
-        return Utilities.getOrCreateSubDirectory(getMetaDataDirectory(), DIR_PARAMETERS);
+        return VERSION;
     }
 
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/IDataStructureHandler.java b/bds/source/java/ch/systemsx/cisd/bds/IDataStructureHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..690bcc2e68c33dcb6b76115975367995a22188ab
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/IDataStructureHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * The aim of this interface is to delegate the work that should be done in {@link AbstractDataStructure} to smaller
+ * parties.
+ * 
+ * @author Christian Ribeaud
+ */
+public interface IDataStructureHandler
+{
+
+    /**
+     * Validates this data structure and throws {@link DataStructureException} if invalid.
+     */
+    public void assertValid() throws DataStructureException;
+
+    /**
+     * Performs opening specific for the concrete data structure. Will be invoked after the common part of
+     * {@link IDataStructure#open()} but before validation with {@link #assertValid()}.
+     */
+    public void performOpening();
+
+    /**
+     * Performs closing specific for the concrete data structure. Will be invoked before validation with
+     * {@link #assertValid()}.
+     */
+    public void performClosing();
+
+}
\ No newline at end of file
diff --git a/bds/source/java/ch/systemsx/cisd/bds/Reference.java b/bds/source/java/ch/systemsx/cisd/bds/Reference.java
index 18dcbfa2fba569d9f989c4bb5deb27550bdf3ced..10e29533fbc7f234b70827976be8b1f62f72543c 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/Reference.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/Reference.java
@@ -21,7 +21,7 @@ package ch.systemsx.cisd.bds;
  * 
  * @author Franz-Josef Elmer
  */
-public class Reference
+public final class Reference
 {
     /** The only accepted path separator (system independent). */
     public final static char PATH_SEPARATOR = '/';
@@ -35,12 +35,14 @@ public class Reference
     /**
      * Creates an instance for the specified paths and reference type.
      * 
-     * @param path Path which referes to <code>originalPath</code>.
-     * @param originalPath Path to which <code>path</code> referes.
+     * @param path Path which refers to <code>originalPath</code>.
+     * @param originalPath Path to which <code>path</code> refers. This can be <code>null</code>.
      * @param referenceType Type of reference.
      */
-    public Reference(String path, String originalPath, ReferenceType referenceType)
+    public Reference(final String path, final String originalPath, final ReferenceType referenceType)
     {
+        assert path != null : "Path can not be null.";
+        assert originalPath != null : "Original path can not be null.";
         this.path = path;
         this.originalPath = originalPath;
         this.referenceType = referenceType;
diff --git a/bds/source/java/ch/systemsx/cisd/bds/ReferenceType.java b/bds/source/java/ch/systemsx/cisd/bds/ReferenceType.java
index 6a446339658fa611f4b87ed89138125ba9c4831c..4b159a53161a60abdee74db63f637a7e9aed9ada 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/ReferenceType.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/ReferenceType.java
@@ -18,19 +18,17 @@ package ch.systemsx.cisd.bds;
 
 /**
  * Type of reference between a file in <tt>data/standard</tt> and <tt>data/original</tt>.
- *
+ * 
  * @author Franz-Josef Elmer
  */
 public enum ReferenceType
 {
     IDENTICAL("I"), TRANSFORMED("T");
-    
+
     /**
-     * Tries to resolve the reference type from the specified short name.
-     * 
-     * @return <code>null</code> if there is no reference type with the specified short name.
+     * Resolves the reference type from the specified short name.
      */
-    public static ReferenceType tryToResolveByShortName(String shortName)
+    public final static ReferenceType resolveByShortName(final String shortName)
     {
         for (ReferenceType type : values())
         {
@@ -39,12 +37,12 @@ public enum ReferenceType
                 return type;
             }
         }
-        return null;
+        throw new IllegalArgumentException(String.format("No type for short name '%s'", shortName));
     }
 
     private final String shortName;
 
-    private ReferenceType(String shortName)
+    private ReferenceType(final String shortName)
     {
         this.shortName = shortName;
     }
@@ -56,6 +54,5 @@ public enum ReferenceType
     {
         return shortName;
     }
-    
-    
+
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/Utilities.java b/bds/source/java/ch/systemsx/cisd/bds/Utilities.java
index 1dd9765b4d744a2c58752f52cde3c5837cdb5839..ba177890da099a1ffaad490b9a6b814800368d98 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/Utilities.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/Utilities.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.bds;
 
+import java.util.List;
+
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IFile;
 import ch.systemsx.cisd.bds.storage.INode;
@@ -85,10 +87,31 @@ public class Utilities
      * @throws DataStructureException if the requested file does not exist.
      */
     public static String getString(final IDirectory directory, final String name)
+    {
+        final INode node = tryGetNode(directory, name);
+        final IFile file = (IFile) node;
+        return file.getStringContent();
+    }
+
+    /**
+     * Returns the string content of a file from the specified directory as list of <code>String</code> objects.
+     * 
+     * @param directory Directory of the requested file.
+     * @param name Name of the file.
+     * @throws DataStructureException if the requested file does not exist.
+     */
+    public static List<String> getStringList(final IDirectory directory, final String name)
+    {
+        final INode node = tryGetNode(directory, name);
+        final IFile file = (IFile) node;
+        return file.getStringContentList();
+    }
+
+    private final static INode tryGetNode(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);
+        final INode node = directory.tryToGetNode(name);
         if (node == null)
         {
             throw new DataStructureException("File '" + name + "' missing in '" + directory + "'.");
@@ -97,8 +120,7 @@ public class Utilities
         {
             throw new DataStructureException(node + " is not a file.");
         }
-        IFile file = (IFile) node;
-        return file.getStringContent();
+        return node;
     }
 
     private Utilities()
diff --git a/bds/source/java/ch/systemsx/cisd/bds/ChecksumBuilder.java b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java
similarity index 95%
rename from bds/source/java/ch/systemsx/cisd/bds/ChecksumBuilder.java
rename to bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java
index 4c800dca491d7e40ce3edda19ec2d59f77bce7bb..1c61153d728706990b04bf55ab49ab535eb3b439 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/ChecksumBuilder.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumBuilder.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.bds;
+package ch.systemsx.cisd.bds.handler;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,6 +27,7 @@ import java.util.List;
 
 import org.apache.commons.io.IOUtils;
 
+import ch.systemsx.cisd.bds.Reference;
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IFile;
 import ch.systemsx.cisd.bds.storage.INode;
@@ -41,7 +42,7 @@ class ChecksumBuilder
 {
     private final IChecksumCalculator checksumCalculator;
 
-    ChecksumBuilder(IChecksumCalculator checksumCalculator)
+    ChecksumBuilder(final IChecksumCalculator checksumCalculator)
     {
         this.checksumCalculator = checksumCalculator;
     }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..486330c615860cf20764250ddccd6fefe349d334
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java
@@ -0,0 +1,65 @@
+/*
+ * 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.bds.DataStructureException;
+import ch.systemsx.cisd.bds.DataStructureV1_0;
+import ch.systemsx.cisd.bds.IDataStructureHandler;
+import ch.systemsx.cisd.bds.storage.IDirectory;
+
+/**
+ * A <code>IDataStructureHandler</code> implementation for the <code>md5sum</code> directory.
+ * 
+ * @author Christian Ribeaud
+ */
+public final class ChecksumHandler implements IDataStructureHandler
+{
+
+    private final ChecksumBuilder checksumBuilder = new ChecksumBuilder(new MD5ChecksumCalculator());
+
+    private final IDirectory checksumDirectory;
+
+    private final IDirectory dataDirectory;
+
+    public static final String CHECKSUM_DIRECTORY = "md5sum";
+
+    public ChecksumHandler(final IDirectory checksumDirectory, final IDirectory dataDirectory)
+    {
+        this.checksumDirectory = checksumDirectory;
+        this.dataDirectory = dataDirectory;
+    }
+
+    //
+    // IDataStructureHandler
+    //
+
+    public final void assertValid() throws DataStructureException
+    {
+        // TODO 2007-11-29, Christian Ribeaud: validation of loaded checksums.
+    }
+
+    public final void performClosing()
+    {
+        final String checksumsOfOriginal = checksumBuilder.buildChecksumsForAllFilesIn(dataDirectory);
+        checksumDirectory.addKeyValuePair(DataStructureV1_0.DIR_ORIGINAL, checksumsOfOriginal);
+    }
+
+    public final void performOpening()
+    {
+    }
+
+}
diff --git a/bds/source/java/ch/systemsx/cisd/bds/IChecksumCalculator.java b/bds/source/java/ch/systemsx/cisd/bds/handler/IChecksumCalculator.java
similarity index 88%
rename from bds/source/java/ch/systemsx/cisd/bds/IChecksumCalculator.java
rename to bds/source/java/ch/systemsx/cisd/bds/handler/IChecksumCalculator.java
index 25c71540f6ed1ee5cf5d3ea5d67e3b2988fa3a5d..40734d983f0868fb9724c723146253a000326ab3 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/IChecksumCalculator.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/handler/IChecksumCalculator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.bds;
+package ch.systemsx.cisd.bds.handler;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,7 +24,7 @@ import java.io.InputStream;
  * 
  * @author Christian Ribeaud
  */
-public interface IChecksumCalculator
+interface IChecksumCalculator
 {
 
     /**
@@ -33,5 +33,5 @@ public interface IChecksumCalculator
      * @param inputStream Input stream from whom the bytes are read to calculate checksum.
      * @throws IOException if reading from <code>inputStream</code> causes an <code>IOException</code>.
      */
-    public String calculateChecksum(InputStream inputStream) throws IOException;
+    String calculateChecksum(InputStream inputStream) throws IOException;
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/MD5ChecksumCalculator.java b/bds/source/java/ch/systemsx/cisd/bds/handler/MD5ChecksumCalculator.java
similarity index 94%
rename from bds/source/java/ch/systemsx/cisd/bds/MD5ChecksumCalculator.java
rename to bds/source/java/ch/systemsx/cisd/bds/handler/MD5ChecksumCalculator.java
index 69882272c27d94aa27c1a7de8954d3ee41ba1921..532e6893199c4a455afb71ad1962c1fb6bd34b68 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/MD5ChecksumCalculator.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/handler/MD5ChecksumCalculator.java
@@ -1,4 +1,4 @@
-package ch.systemsx.cisd.bds;
+package ch.systemsx.cisd.bds.handler;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -6,6 +6,7 @@ import java.io.InputStream;
 import com.twmacinta.util.MD5;
 import com.twmacinta.util.MD5InputStream;
 
+
 /**
  * A {@link IChecksumCalculator} implementation based on <i>MD5</i>.
  * 
diff --git a/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java b/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..405643b64452b4105934da5301f9c9fd3be072a5
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/handler/MappingFileHandler.java
@@ -0,0 +1,160 @@
+/*
+ * 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 java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import ch.systemsx.cisd.bds.DataStructureException;
+import ch.systemsx.cisd.bds.IDataStructureHandler;
+import ch.systemsx.cisd.bds.Reference;
+import ch.systemsx.cisd.bds.ReferenceType;
+import ch.systemsx.cisd.bds.Utilities;
+import ch.systemsx.cisd.bds.storage.IDirectory;
+
+/**
+ * A <code>IDataStructureHandler</code> implementation for the <code>standard_original_mapping</code> file.
+ * 
+ * @author Christian Ribeaud
+ */
+public final class MappingFileHandler implements IDataStructureHandler
+{
+    private final Map<String, Reference> standardOriginalMapping = new LinkedHashMap<String, 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. */
+    private final IDirectory pathRoot;
+
+    /** The root of {@link Reference#getOriginalPath()}. Usually the path to <code>original</code> directory. */
+    private final IDirectory originalPathRoot;
+
+    /**
+     * The mapping relating <i>standard</i> with <i>original</i> data.
+     * <p>
+     * Note that under format specific conditions this mapping file could be empty, meaning that the <i>standard</i>
+     * directory contains the real data and not only links.
+     * </p>
+     */
+    public static final String MAPPING_FILE = "standard_original_mapping";
+
+    public MappingFileHandler(final IDirectory mappingDirectory, final IDirectory pathRoot,
+            final IDirectory originalPathRoot)
+    {
+        assert mappingDirectory != null : "Given mapping directory can not be null.";
+        assert pathRoot != null : "Given path root can not be null.";
+        assert originalPathRoot != null : "Given original path root can not be null.";
+        this.mappingDirectory = mappingDirectory;
+        this.pathRoot = pathRoot;
+        this.originalPathRoot = originalPathRoot;
+    }
+
+    /**
+     * Returns the standard-original mapping.
+     * 
+     * @return an unmodifiable version of this map.
+     */
+    public final Map<String, Reference> getStandardOriginalMapping()
+    {
+        return Collections.unmodifiableMap(standardOriginalMapping);
+    }
+
+    /**
+     * Adds a reference to the standard-original mapping.
+     * 
+     * @throws DataStructureException if a reference with the same path has already been registered.
+     */
+    public final void addReference(final Reference reference) throws DataStructureException
+    {
+        assert reference != null : "Unspecified reference.";
+        final String path = reference.getPath();
+        if (standardOriginalMapping.containsKey(path))
+        {
+            throw new DataStructureException("There is already a reference for file '" + path + "'.");
+        }
+        standardOriginalMapping.put(path, reference);
+    }
+
+    private final void loadStandardOriginalMapping()
+    {
+        final List<String> mappingLines = Utilities.getStringList(mappingDirectory, MAPPING_FILE);
+        standardOriginalMapping.clear();
+        for (int i = 0; i < mappingLines.size(); i++)
+        {
+            String referenceDefinition = mappingLines.get(i);
+            int i1 = referenceDefinition.indexOf('\t');
+            if (i1 < 0)
+            {
+                throw new DataStructureException("Error in standard-original mapping line " + (i + 1)
+                        + ": missing first tab character: " + referenceDefinition);
+            }
+            String path = referenceDefinition.substring(0, i1);
+            int i2 = referenceDefinition.indexOf('\t', i1 + 1);
+            if (i2 < 0)
+            {
+                throw new DataStructureException("Error in standard-original mapping line " + (i + 1)
+                        + ": 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));
+        }
+    }
+
+    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 String path = reference.getPath();
+            final String shortName = reference.getReferenceType().getShortName();
+            final String originalPath = reference.getOriginalPath();
+            printWriter.println(path + "\t" + shortName + "\t" + originalPath);
+        }
+        printWriter.close();
+        return writer.toString();
+    }
+
+    //
+    // 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.
+    }
+
+    public final void performClosing()
+    {
+        mappingDirectory.addKeyValuePair(MAPPING_FILE, createMappingFile());
+    }
+
+    public final void performOpening()
+    {
+        loadStandardOriginalMapping();
+    }
+
+}
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java
index a943effb8a143e33ca2d353059652ee67f7a2e63..7f0ef500185812fbd3c13ab24db044ac9310604d 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java
@@ -30,7 +30,7 @@ public interface IDirectory extends INode, Iterable<INode>
      * 
      * @return <code>null</code> if there is no child node named <code>name</code>.
      */
-    public INode tryToGetNode(String name);
+    public INode tryToGetNode(final String name);
 
     /**
      * Makes a new subdirectory in this directory. Does nothing if the subdirectory already exists.
@@ -58,10 +58,10 @@ public interface IDirectory extends INode, Iterable<INode>
     /**
      * Adds a plain file named <code>key</code> with content <code>value</code> to this directory.
      */
-    public IFile addKeyValuePair(String key, String value);
+    public IFile addKeyValuePair(final String key, final String value);
 
     /**
      * Adds the link named <code>name</code> to this directory which refers to the specified node.
      */
-    public ILink addLink(String name, INode node);
+    public ILink addLink(final String name, final INode node);
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IFile.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IFile.java
index 9b8702c860fe132e54a5aa616852cd9c37af049f..1fce846462f27cdeddc1d5cd9dd82f82587a8094 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/IFile.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IFile.java
@@ -17,11 +17,11 @@
 package ch.systemsx.cisd.bds.storage;
 
 import java.io.InputStream;
-import java.io.Reader;
+import java.util.List;
 
 /**
  * Node representing a file with some content.
- *
+ * 
  * @author Franz-Josef Elmer
  */
 public interface IFile extends INode
@@ -30,19 +30,20 @@ public interface IFile extends INode
      * Returns the content of this file node as a byte array.
      */
     public byte[] getBinaryContent();
-    
+
     /**
      * Returns the content of this file node as an input stream.
      */
     public InputStream getInputStream();
-    
+
     /**
      * Returns the content of this file node as a string.
      */
     public String getStringContent();
-    
+
     /**
-     * Returns the content of this file node as a reader.
+     * Returns the content of this file node as a list of <code>String</code> objects.
      */
-    public Reader getReader();
+    public List<String> getStringContentList();
+
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java
index 2d9621d6d8e975c435d832ed72792e456d3a2bb9..24de1be2923df2b3792689f883bf0c88490945fd 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java
@@ -35,6 +35,11 @@ public interface INode
      */
     public IDirectory tryToGetParent();
 
+    /**
+     * Whether this <code>INode</code> is valid.
+     */
+    public boolean isValid();
+
     /**
      * Extracts this node to the specified directory of the file system.
      * <p>
@@ -42,10 +47,10 @@ public interface INode
      * </p>
      */
     public void extractTo(final File directory);
-    
+
     /**
-     * Moves this node and all descendants to the specified directory of the file system.
-     * This node will be automatically removed from its parent.
+     * Moves this node and all descendants to the specified directory of the file system. This node will be
+     * automatically removed from its parent.
      */
     public void moveTo(final File directory);
 }
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 f80754a8a5aa839b5bce4057143ae96ddf849127..f35e0adf9fa1a19a6d225301608fc9d052f847b4 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
@@ -87,6 +87,11 @@ abstract class AbstractNode implements INode
         moveFileToDirectory(nodeFile, directory);
     }
 
+    public boolean isValid()
+    {
+        return nodeFile.exists();
+    }
+
     //
     // Object
     //
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 5023956f7be5d05f7b12b34f7a6ffca7a3734bd0..c51790b7ba93cfb8248fef9d1587c26faadb0950 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
@@ -190,4 +190,10 @@ final class Directory extends AbstractNode implements IDirectory
             }
         }
     }
+
+    @Override
+    public final boolean isValid()
+    {
+        return super.isValid() && FileUtilities.checkDirectoryFullyAccessible(nodeFile, "") == null;
+    }
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java
index 25fbe30589470e49b5714e6ffe66df61544a19db..559e0c5c98bcc9443e447cba402d80407d4d3609 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java
@@ -18,10 +18,9 @@ package ch.systemsx.cisd.bds.storage.filesystem;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.Reader;
+import java.util.List;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
@@ -31,6 +30,8 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.utilities.FileUtilities;
 
 /**
+ * An <code>IFile</code> implementation.
+ * 
  * @author Franz-Josef Elmer
  */
 class File extends AbstractNode implements IFile
@@ -56,7 +57,7 @@ class File extends AbstractNode implements IFile
         }
     }
 
-    public InputStream getInputStream()
+    public final InputStream getInputStream()
     {
         try
         {
@@ -67,22 +68,16 @@ class File extends AbstractNode implements IFile
         }
     }
 
-    public String getStringContent()
+    public final String getStringContent()
     {
         return FileUtilities.loadToString(nodeFile);
     }
 
-    public Reader getReader()
+    public final List<String> getStringContentList()
     {
-        try
-        {
-            return new FileReader(nodeFile);
-        } catch (FileNotFoundException ex)
-        {
-            throw new EnvironmentFailureException("Couldn't open reader for file " + nodeFile.getAbsolutePath());
-        }
+        return FileUtilities.loadToStringList(nodeFile);
     }
-    
+
     public final void extractTo(final java.io.File directory) throws EnvironmentFailureException
     {
         assert directory != null && directory.isDirectory();
@@ -95,4 +90,10 @@ class File extends AbstractNode implements IFile
                     nodeFile.getAbsolutePath(), directory.getAbsolutePath());
         }
     }
+
+    @Override
+    public final boolean isValid()
+    {
+        return super.isValid() && FileUtilities.checkPathFullyAccessible(nodeFile, "") == null;
+    }
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java
index 28565473b9a3c3c4e7fd853e44580a804ea957ac..604de64e9b8460f79f862bc7f9774c21ee38b7a3 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java
@@ -21,53 +21,76 @@ import java.io.File;
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.ILink;
 import ch.systemsx.cisd.bds.storage.INode;
-import ch.systemsx.cisd.common.exceptions.NotImplementedException;
 
 /**
+ * An <code>ILink</code> implementation.
+ * 
  * @author Franz-Josef Elmer
  */
-class Link implements ILink
+final class Link implements ILink
 {
 
     private final String name;
 
-    private IDirectory parent;
-
     private final INode reference;
 
-    Link(String name, INode reference)
+    private IDirectory parent;
+
+    Link(final String name, final INode reference)
     {
+        assert name != null : "A name must be specified.";
+        assert reference != null : "Reference can not be null.";
+        assert reference instanceof ILink : "Link of link not supported.";
         this.name = name;
         this.reference = reference;
     }
 
-    public String getName()
+    /** Sets the parent of this {@link INode}. */
+    final void setParent(final IDirectory parentOrNull)
     {
-        return name;
+        parent = parentOrNull;
     }
 
-    void setParent(IDirectory parentOrNull)
+    //
+    // ILink
+    //
+
+    public final String getName()
     {
-        parent = parentOrNull;
+        return name;
     }
 
-    public IDirectory tryToGetParent()
+    public final IDirectory tryToGetParent()
     {
         return parent;
     }
 
-    public INode getReference()
+    public final INode getReference()
     {
         return reference;
     }
 
-    public void extractTo(final File directory)
+    public final void extractTo(final File directory)
+    {
+        reference.extractTo(directory);
+    }
+
+    public final void moveTo(final File directory)
     {
-        throw new NotImplementedException();
+        reference.moveTo(directory);
     }
 
-    public void moveTo(File directory)
+    public final boolean isValid()
     {
-        throw new NotImplementedException();
+        if (reference.isValid() == false)
+        {
+            return false;
+        }
+        if (parent != null)
+        {
+            final INode node = parent.tryToGetNode(name);
+            return node != null && node.isValid();
+        }
+        return true;
     }
 }
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 d4237b1ee297e7a7d7ac7a82b2bdd9ebde734b5a..389a4f8481708adaf0aff33b7ef38f3d4199d8ee 100644
--- a/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureV1_0Test.java
+++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureV1_0Test.java
@@ -16,7 +16,6 @@
 
 package ch.systemsx.cisd.bds;
 
-import static ch.systemsx.cisd.bds.DataStructureV1_0.CHECKSUM_DIRECTORY;
 import static ch.systemsx.cisd.bds.DataStructureV1_0.DIR_METADATA;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
@@ -31,6 +30,8 @@ import java.util.Map;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.bds.handler.ChecksumHandler;
+import ch.systemsx.cisd.bds.handler.MappingFileHandler;
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IStorage;
 import ch.systemsx.cisd.bds.storage.StorageException;
@@ -413,7 +414,7 @@ public final class DataStructureV1_0Test extends AbstractFileSystemTestCase
         checkFormattedData(reloadedDataStructure.getFormattedData());
 
         IDirectory metaDataDir = Utilities.getSubDirectory(root, DIR_METADATA);
-        IDirectory checksumDir = Utilities.getSubDirectory(metaDataDir, CHECKSUM_DIRECTORY);
+        IDirectory checksumDir = Utilities.getSubDirectory(metaDataDir, ChecksumHandler.CHECKSUM_DIRECTORY);
         assertEquals("a1d0c6e83f027327d8461063f4ac58a6  answer\n", Utilities.getString(checksumDir,
                 DataStructureV1_0.DIR_ORIGINAL));
     }
@@ -550,7 +551,7 @@ public final class DataStructureV1_0Test extends AbstractFileSystemTestCase
         new ExperimentRegistratorDate(new Date(0)).saveTo(metaData);
         new ExperimentRegistrator("john", "doe", "j@doe").saveTo(metaData);
         new MeasurementEntity("a", "b").saveTo(metaData);
-        metaData.addKeyValuePair(DataStructureV1_0.MAPPING_FILE, "");
+        metaData.addKeyValuePair(MappingFileHandler.MAPPING_FILE, "");
         ProcessingType.COMPUTED_DATA.saveTo(metaData);
         storage.unmount();
     }
diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/ChecksumBuilderTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/ChecksumBuilderTest.java
similarity index 95%
rename from bds/sourceTest/java/ch/systemsx/cisd/bds/ChecksumBuilderTest.java
rename to bds/sourceTest/java/ch/systemsx/cisd/bds/handler/ChecksumBuilderTest.java
index a2806d8ffa11656f415c25c7d8a660607268f673..0846e03942ddcc9777a17e81e828df64363dc6cd 100644
--- a/bds/sourceTest/java/ch/systemsx/cisd/bds/ChecksumBuilderTest.java
+++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/handler/ChecksumBuilderTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.bds;
+package ch.systemsx.cisd.bds.handler;
 
 import static ch.systemsx.cisd.common.utilities.OSUtilities.LINE_SEPARATOR;
 import static org.testng.AssertJUnit.assertEquals;
@@ -27,6 +27,8 @@ import java.util.Random;
 import org.apache.commons.io.IOUtils;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.bds.handler.ChecksumBuilder;
+import ch.systemsx.cisd.bds.handler.MD5ChecksumCalculator;
 import ch.systemsx.cisd.bds.storage.filesystem.FileStorage;
 import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase;
 import ch.systemsx.cisd.common.utilities.FileUtilities;