diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/DataStoreServerApi.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/DataStoreServerApi.java
index 586463eddca995e33485b923a447aa0c5327e54e..69b5805466b6c569b60fdea2031bbd4a695a81f3 100644
--- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/DataStoreServerApi.java
+++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/DataStoreServerApi.java
@@ -52,6 +52,7 @@ import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.id.DataSetFilePermI
 import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.id.IDataSetFileId;
 import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.search.DataSetFileSearchCriteria;
 import ch.ethz.sis.openbis.generic.server.dssapi.v3.download.DataSetFileDownloadInputStream;
+import ch.ethz.sis.openbis.generic.server.dssapi.v3.pathinfo.PathInfoFeeder;
 import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.filesystem.IFreeSpaceProvider;
@@ -75,7 +76,6 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PathInfoDataSourceProvi
 import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.RolesAllowed;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.IQueryApiServer;
-
 import net.lemnik.eodsql.QueryTool;
 
 /**
@@ -323,9 +323,12 @@ public class DataStoreServerApi extends AbstractDssServiceRpc<IDataStoreServerAp
 
             long dataSetId =
                     dao.createDataSet(permId, "");
+
+            PathInfoFeeder feeder = new PathInfoFeeder(dataSetId, files);
+
             try
             {
-                dao.createDataSetFiles(PathInfoDTOCreator.createPathEntries(dataSetId, permId, files));
+                feeder.storeFilesWith(dao);
             } catch (IllegalArgumentException e)
             {
                 dao.rollback();
diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/PathInfoDTOCreator.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/PathInfoDTOCreator.java
deleted file mode 100644
index 5816075dde1c534981b7a9832b1d2e0c58fbcd3e..0000000000000000000000000000000000000000
--- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/PathInfoDTOCreator.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2010 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.ethz.sis.openbis.generic.server.dssapi.v3;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.create.DataSetFileCreation;
-import ch.systemsx.cisd.etlserver.path.PathEntryDTO;
-
-/**
- * Converter between DataSetFileCreation (V3 API) and PathEntryDTO (PathinfoDB EODSQL DTO)
- * 
- * @author anttil
- */
-public class PathInfoDTOCreator
-{
-
-    public static Collection<PathEntryDTO> createPathEntries(long dataSetId, String dataSetCode, Collection<DataSetFileCreation> files)
-    {
-        checkInput(files);
-        Map<String, Long> fileIds = createIdsToPaths(files);
-
-        Date lastModified = new Date();
-        List<PathEntryDTO> result = new ArrayList<>();
-        Map<String, Long> directorySizes = new HashMap<>();
-        for (DataSetFileCreation file : files)
-        {
-            String path = file.getPath();
-
-            File f = new File(path);
-            PathEntryDTO dto = new PathEntryDTO();
-            dto.setDataSetId(dataSetId);
-            dto.setDataSetCode(dataSetCode);
-            dto.setDirectory(file.isDirectory());
-            dto.setFileName(f.getName());
-            dto.setRelativePath(f.getPath());
-            dto.setId(fileIds.get(f.getPath()));
-            if (f.getParent() != null)
-            {
-                dto.setParentId(fileIds.get(f.getParent()));
-            }
-            if (file.isDirectory() == false)
-            {
-                dto.setSizeInBytes(file.getFileLength());
-                dto.setChecksumCRC32(file.getChecksumCRC32());
-            } else
-            {
-                dto.setSizeInBytes(0);
-            }
-            dto.setLastModifiedDate(lastModified);
-            result.add(dto);
-
-            long leafSize = dto.getSizeInBytes();
-
-            f = new File(path).getParentFile();
-            while (f != null)
-            {
-                dto = new PathEntryDTO();
-                dto.setDataSetId(dataSetId);
-                dto.setDataSetCode(dataSetCode);
-                dto.setDirectory(true);
-                dto.setFileName(f.getName());
-                dto.setRelativePath(f.getPath());
-                dto.setId(fileIds.get(f.getPath()));
-                if (f.getParent() != null)
-                {
-                    dto.setParentId(fileIds.get(f.getParent()));
-                }
-                dto.setLastModifiedDate(lastModified);
-                result.add(dto);
-
-                Long current = directorySizes.get(f.getPath());
-                if (current == null)
-                {
-                    current = 0l;
-                }
-                current += leafSize;
-                directorySizes.put(f.getPath(), current);
-
-                f = f.getParentFile();
-            }
-        }
-
-        for (PathEntryDTO dto : result)
-        {
-            if (dto.isDirectory() && dto.getSizeInBytes() == null)
-            {
-                dto.setSizeInBytes(directorySizes.get(dto.getRelativePath()));
-            }
-        }
-
-        return new HashSet<PathEntryDTO>(result);
-    }
-
-    private static Map<String, Long> createIdsToPaths(Collection<DataSetFileCreation> files)
-    {
-        Map<String, Long> result = new HashMap<>();
-        long id = 1l;
-        for (DataSetFileCreation file : files)
-        {
-            String path = file.getPath();
-            File f = new File(path);
-            while (f != null)
-            {
-                if (result.containsKey(f.getPath()) == false)
-                {
-                    result.put(f.getPath(), id++);
-                }
-                f = f.getParentFile();
-            }
-        }
-        return result;
-    }
-
-    private static void checkInput(Collection<DataSetFileCreation> files)
-    {
-        Set<String> paths = new HashSet<>();
-        for (DataSetFileCreation file : files)
-        {
-            checkInput(file);
-            check(paths.contains(file.getPath()), "Path " + file.getPath() + " appears twice");
-            paths.add(file.getPath());
-        }
-    }
-
-    private static void checkInput(DataSetFileCreation file)
-    {
-        String path = file.getPath();
-        check(path == null || path.length() == 0, "Path of " + file + " was null");
-        check(path.startsWith("/"), "Path of " + file + " is absolute");
-        check(file.isDirectory() == false && file.getFileLength() == null, "Size of " + file + " is null");
-        check(file.isDirectory() && file.getFileLength() != null, "Directory " + file + " has a size");
-        check(file.isDirectory() && file.getChecksumCRC32() != null, "Directory " + file + " has a checksum");
-    }
-
-    private static void check(boolean condition, String message)
-    {
-        if (condition)
-        {
-            throw new IllegalArgumentException(message);
-        }
-    }
-}
diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/DataSetContentNode.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/DataSetContentNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..8dd24d75b2fe29c11dc83e058fc9ccca4ffb2bd9
--- /dev/null
+++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/DataSetContentNode.java
@@ -0,0 +1,12 @@
+package ch.ethz.sis.openbis.generic.server.dssapi.v3.pathinfo;
+
+interface DataSetContentNode
+{
+    long getLength();
+
+    Integer getChecksum();
+
+    String getFullPath();
+
+    boolean isDirectory();
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/DirectoryNode.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/DirectoryNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..852a2fb2a775a343662f36ef1184787df02c4bee
--- /dev/null
+++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/DirectoryNode.java
@@ -0,0 +1,124 @@
+package ch.ethz.sis.openbis.generic.server.dssapi.v3.pathinfo;
+
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+class DirectoryNode implements DataSetContentNode
+{
+    private final String parentPath;
+
+    private final String name;
+
+    private final String fullPath;
+
+    private final Map<String, DataSetContentNode> children;
+
+    public DirectoryNode(String parentPath, String name, Map<String, DataSetContentNode> children)
+    {
+        this.parentPath = parentPath;
+        this.name = name;
+        if (parentPath == null)
+        {
+            this.fullPath = name;
+        } else
+        {
+            this.fullPath = parentPath + "/" + name;
+        }
+        this.children = new HashMap<>();
+        this.children.putAll(children);
+    }
+
+    public DirectoryNode(String parentPath, String name)
+    {
+        this(parentPath, name, new HashMap<String, DataSetContentNode>());
+    }
+
+    public DirectoryNode addFile(Path path, long length, Integer checksum)
+    {
+        if (path.getParent() != null)
+        {
+            Path directoryName = path.getName(0);
+            Path tail = path.subpath(1, path.getNameCount());
+            DirectoryNode node = (DirectoryNode) children.get(directoryName.toString());
+            if (node == null)
+            {
+                node = new DirectoryNode(getFullPath(), directoryName.toString());
+            }
+
+            return newNode(directoryName.toString(), node.addFile(tail, length, checksum));
+        } else
+        {
+            if (children.containsKey(path.toString()))
+            {
+                throw new IllegalArgumentException("duplicate file: " + path.toString() + "/" + this.getFullPath());
+            }
+
+            return newNode(path.toString(), new FileNode(getFullPath(), path.toString(), length, checksum));
+        }
+    }
+
+    public DirectoryNode addDirectory(Path path)
+    {
+        if (path.getParent() != null)
+        {
+            Path directoryName = path.getName(0);
+            Path tail = path.subpath(1, path.getNameCount());
+            DirectoryNode node = (DirectoryNode) children.get(directoryName.toString());
+            if (node == null)
+            {
+                node = new DirectoryNode(getFullPath(), directoryName.toString());
+            }
+
+            return newNode(directoryName.toString(), node.addDirectory(tail));
+        } else if (children.containsKey(path.toString()))
+        {
+            return this;
+        } else
+        {
+            return newNode(path.toString(), new DirectoryNode(getFullPath(), path.toString()));
+        }
+    }
+
+    private DirectoryNode newNode(String nodeName, DataSetContentNode node)
+    {
+        Map<String, DataSetContentNode> newContent = new HashMap<String, DataSetContentNode>();
+        newContent.putAll(children);
+        newContent.put(nodeName, node);
+        return new DirectoryNode(parentPath, name, newContent);
+    }
+
+    @Override
+    public long getLength()
+    {
+        long result = 0;
+        for (DataSetContentNode node : children.values())
+        {
+            result += node.getLength();
+        }
+        return result;
+    }
+
+    @Override
+    public Integer getChecksum()
+    {
+        return null;
+    }
+
+    @Override
+    public String getFullPath()
+    {
+        return fullPath;
+    }
+
+    @Override
+    public boolean isDirectory()
+    {
+        return true;
+    }
+
+    Map<String, DataSetContentNode> getChildren()
+    {
+        return children;
+    }
+}
diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/FileNode.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/FileNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed5307b79e4f894f6c3a0382c110dfca5749c828
--- /dev/null
+++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/FileNode.java
@@ -0,0 +1,48 @@
+package ch.ethz.sis.openbis.generic.server.dssapi.v3.pathinfo;
+
+class FileNode implements DataSetContentNode
+{
+    private final String fullPath;
+
+    private final long length;
+
+    private final Integer checksum;
+
+    public FileNode(String parentPath, String name, long length, Integer checksum)
+    {
+        if (parentPath == null)
+        {
+            this.fullPath = name;
+        } else
+        {
+            this.fullPath = parentPath + "/" + name;
+        }
+        this.length = length;
+        this.checksum = checksum;
+    }
+
+    @Override
+    public long getLength()
+    {
+        return length;
+    }
+
+    @Override
+    public Integer getChecksum()
+    {
+        return checksum;
+    }
+
+    @Override
+    public String getFullPath()
+    {
+        return this.fullPath;
+    }
+
+    @Override
+    public boolean isDirectory()
+    {
+        return false;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/PathInfoFeeder.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/PathInfoFeeder.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe5568fd382b2d4381c847aca0acb1bd8281454c
--- /dev/null
+++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dssapi/v3/pathinfo/PathInfoFeeder.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 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.ethz.sis.openbis.generic.server.dssapi.v3.pathinfo;
+
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.create.DataSetFileCreation;
+import ch.systemsx.cisd.etlserver.path.IPathsInfoDAO;
+
+/**
+ * Stores entries to pathinfo db based on given DataSetFileCreation instances.
+ * 
+ * @author anttil
+ */
+public class PathInfoFeeder
+{
+
+    private DirectoryNode root = new DirectoryNode(null, null);
+
+    private final long dataSetId;
+
+    public PathInfoFeeder(long dataSetId, Collection<DataSetFileCreation> files)
+    {
+        checkInput(files);
+        for (DataSetFileCreation file : files)
+        {
+            if (file.isDirectory())
+            {
+                root = root.addDirectory(Paths.get(file.getPath()));
+            } else
+            {
+                root = root.addFile(Paths.get(file.getPath()), file.getFileLength(), file.getChecksumCRC32());
+            }
+        }
+        this.dataSetId = dataSetId;
+    }
+
+    public void storeFilesWith(IPathsInfoDAO dao)
+    {
+        storeFilesWith(dao, root, null, "", new Date());
+    }
+
+    private void storeFilesWith(IPathsInfoDAO dao, DataSetContentNode node, Long parentId, String name, Date timestamp)
+    {
+        long id;
+        String fullPath = node.getFullPath() == null ? "" : node.getFullPath();
+        if (node.getChecksum() == null)
+        {
+            id = dao.createDataSetFile(dataSetId, parentId, fullPath, name, node.getLength(),
+                    node.isDirectory(), timestamp);
+        } else
+        {
+            id = dao.createDataSetFileWithChecksum(dataSetId, parentId, fullPath, name, node.getLength(),
+                    node.isDirectory(), node.getChecksum(), timestamp);
+        }
+
+        if (node.isDirectory())
+        {
+            for (Entry<String, DataSetContentNode> entry : ((DirectoryNode) node).getChildren().entrySet())
+            {
+                storeFilesWith(dao, entry.getValue(), id, entry.getKey(), timestamp);
+            }
+        }
+    }
+
+    private static void checkInput(Collection<DataSetFileCreation> files)
+    {
+        Set<String> paths = new HashSet<>();
+        for (DataSetFileCreation file : files)
+        {
+            checkInput(file);
+            check(paths.contains(file.getPath()), "Path " + file.getPath() + " appears twice");
+            paths.add(file.getPath());
+        }
+    }
+
+    private static void checkInput(DataSetFileCreation file)
+    {
+        String path = file.getPath();
+        check(path == null || path.length() == 0, "Path of " + file + " was null");
+        check(path.startsWith("/"), "Path of " + file + " is absolute");
+        check(file.isDirectory() == false && file.getFileLength() == null, "Size of " + file + " is null");
+        check(file.isDirectory() && file.getFileLength() != null, "Directory " + file + " has a size");
+        check(file.isDirectory() && file.getChecksumCRC32() != null, "Directory " + file + " has a checksum");
+    }
+
+    private static void check(boolean condition, String message)
+    {
+        if (condition)
+        {
+            throw new IllegalArgumentException(message);
+        }
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/path/IPathsInfoDAO.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/path/IPathsInfoDAO.java
index 4ebdf3dce14b30c8d23414be41ba13717fd88c8b..52f642ea615ca27aa312d843a9f0ad75386c03ad 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/path/IPathsInfoDAO.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/path/IPathsInfoDAO.java
@@ -21,7 +21,6 @@ import java.util.Date;
 import java.util.List;
 
 import ch.systemsx.cisd.common.db.mapper.StringArrayMapper;
-
 import net.lemnik.eodsql.Select;
 import net.lemnik.eodsql.TransactionQuery;
 import net.lemnik.eodsql.Update;
@@ -38,7 +37,7 @@ public interface IPathsInfoDAO extends TransactionQuery
 
     @Select("insert into data_sets (code, location) values (?{1}, ?{2}) returning id")
     public long createDataSet(String code, String location);
-    
+
     @Update("delete from data_sets where code = ?{1}")
     public void deleteDataSet(String code);
 
@@ -47,6 +46,11 @@ public interface IPathsInfoDAO extends TransactionQuery
     public long createDataSetFile(long dataSetId, Long parentId, String relativePath,
             String fileName, long sizeInBytes, boolean directory, Date lastModifiedDate);
 
+    @Select("insert into data_set_files (dase_id, parent_id, relative_path, file_name, "
+            + "size_in_bytes, is_directory, checksum_crc32, last_modified) values (?{1}, ?{2}, ?{3}, ?{4}, ?{5}, ?{6}, ?{7}, ?{8}) returning id")
+    public long createDataSetFileWithChecksum(long dataSetId, Long parentId, String relativePath,
+            String fileName, long sizeInBytes, boolean directory, int checksum, Date lastModifiedDate);
+
     @Select("select registration_timestamp from last_feeding_event")
     public Date getRegistrationTimestampOfLastFeedingEvent();
 
diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/api/v3/PathInfoDTOCreatorTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/api/v3/PathInfoFeederTest.java
similarity index 69%
rename from datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/api/v3/PathInfoDTOCreatorTest.java
rename to datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/api/v3/PathInfoFeederTest.java
index 88a70f9bfbab8f57d8ae1180be6a7f3a1c12211c..df849163eaf7629331075335ddcec856d999b311 100644
--- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/api/v3/PathInfoDTOCreatorTest.java
+++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/api/v3/PathInfoFeederTest.java
@@ -2,11 +2,13 @@ package ch.ethz.sis.openbis.generic.dss.api.v3;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.nullValue;
 import static org.hamcrest.core.Every.everyItem;
 import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;
 import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
@@ -14,25 +16,29 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.hamcrest.beans.HasPropertyWithValue;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.api.Action;
+import org.jmock.api.Invocation;
+import org.jmock.lib.action.CustomAction;
 import org.testng.annotations.Test;
 
 import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.create.DataSetFileCreation;
-import ch.ethz.sis.openbis.generic.server.dssapi.v3.PathInfoDTOCreator;
+import ch.ethz.sis.openbis.generic.server.dssapi.v3.pathinfo.PathInfoFeeder;
+import ch.systemsx.cisd.etlserver.path.IPathsInfoDAO;
 import ch.systemsx.cisd.etlserver.path.PathEntryDTO;
 
-public class PathInfoDTOCreatorTest
+public class PathInfoFeederTest
 {
 
     public static final long DS_ID = 1l;
 
-    public static final String DS_CODE = "ds";
-
     @Test
     public void expansionCreatesRightAmountOfEntries()
     {
         Collection<PathEntryDTO> result = runWith(file().withPath("path/to/the/file/itself.txt"),
                 directory().withPath("path/to/a/directory"));
-        assertThat(result.size(), is(7));
+        assertThat(result.size(), is(8)); // one entry for root directory
     }
 
     @Test
@@ -84,13 +90,6 @@ public class PathInfoDTOCreatorTest
         assertThat(fileFrom(result).getDataSetId(), is(DS_ID));
     }
 
-    @Test
-    public void dataSetCodeTranslatedCorrectly()
-    {
-        Collection<PathEntryDTO> result = runWith(file());
-        assertThat(fileFrom(result).getDataSetCode(), is(DS_CODE));
-    }
-
     @Test
     public void modificationTimesSetCorrectly()
     {
@@ -127,7 +126,7 @@ public class PathInfoDTOCreatorTest
         long middleId = fileFrom(result, "path/to").getId();
         Long highParentId = fileFrom(result, "path/to/file.txt").getParentId();
 
-        assertThat(lowParentId, is(nullValue()));
+        assertThat(lowParentId, is(not(nullValue())));
         assertThat(middleParentId, is(lowId));
         assertThat(highParentId, is(middleId));
     }
@@ -224,16 +223,6 @@ public class PathInfoDTOCreatorTest
         return fileFrom(entries, "path/to/file.txt");
     }
 
-    private static Collection<PathEntryDTO> runWith(DataSetFileCreationBuilder... files)
-    {
-        Set<DataSetFileCreation> input = new HashSet<>();
-        for (DataSetFileCreationBuilder file : files)
-        {
-            input.add(file.build());
-        }
-        return PathInfoDTOCreator.createPathEntries(DS_ID, DS_CODE, input);
-    }
-
     private DataSetFileCreationBuilder file()
     {
         return new DataSetFileCreationBuilder(false).withPath("path/to/file.txt");
@@ -243,4 +232,68 @@ public class PathInfoDTOCreatorTest
     {
         return new DataSetFileCreationBuilder(true);
     }
+
+    private static Collection<PathEntryDTO> runWith(DataSetFileCreationBuilder... files)
+    {
+        Set<DataSetFileCreation> input = new HashSet<>();
+        for (DataSetFileCreationBuilder file : files)
+        {
+            input.add(file.build());
+        }
+        PathInfoFeeder creator = new PathInfoFeeder(1, input);
+
+        Mockery context = new Mockery();
+        final IPathsInfoDAO mockDao = context.mock(IPathsInfoDAO.class);
+        final Collection<PathEntryDTO> result = new ArrayList<PathEntryDTO>();
+        context.checking(new Expectations()
+            {
+                {
+
+                    Action action = new CustomAction("")
+                        {
+                            long counter = 1;
+
+                            @Override
+                            public Object invoke(Invocation invocation) throws Throwable
+                            {
+                                PathEntryDTO entry = new PathEntryDTO();
+                                entry.setId(counter);
+                                entry.setDataSetId((long) invocation.getParameter(0));
+                                if (invocation.getParameter(1) != null)
+                                {
+                                    entry.setParentId((long) invocation.getParameter(1));
+                                }
+                                entry.setRelativePath((String) invocation.getParameter(2));
+                                entry.setFileName((String) invocation.getParameter(3));
+                                entry.setSizeInBytes((long) invocation.getParameter(4));
+                                entry.setDirectory((boolean) invocation.getParameter(5));
+                                if (invocation.getParameter(6) instanceof Integer)
+                                {
+                                    entry.setChecksumCRC32((int) invocation.getParameter(6));
+                                    entry.setLastModifiedDate((Date) invocation.getParameter(7));
+                                } else
+                                {
+                                    entry.setLastModifiedDate((Date) invocation.getParameter(6));
+                                }
+
+                                result.add(entry);
+                                return counter++;
+                            }
+
+                        };
+
+                    allowing(mockDao).createDataSetFile(with(any(long.class)), with(any(Long.class)), with(any(String.class)),
+                            with(any(String.class)), with(any(long.class)), with(any(boolean.class)), with(any(Date.class)));
+                    will(action);
+
+                    allowing(mockDao).createDataSetFileWithChecksum(with(any(long.class)), with(any(Long.class)), with(any(String.class)),
+                            with(any(String.class)), with(any(long.class)), with(any(boolean.class)), with(any(int.class)), with(any(Date.class)));
+                    will(action);
+
+                }
+            });
+
+        creator.storeFilesWith(mockDao);
+        return result;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
index 846942c93547bf20e4f6d631ea91a868cebc9a11..5a46650a836d8aa732f7ad7c89156a6fe5c03546 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
@@ -1400,7 +1400,13 @@ public class DatasetLister extends AbstractLister implements IDatasetLister
         {
             DatasetLocation location = new DatasetLocation();
             location.setDatasetCode(record.code);
-            location.setDataSetLocation(record.location);
+            if (record.link_info == null)
+            {
+                location.setDataSetLocation(record.location);
+            } else
+            {
+                location.setDataSetLocation(datasetCode);
+            }
             location.setDataStoreCode(record.data_store_code);
             location.setDataStoreUrl(record.data_store_url);
             location.setOrderInContainer(record.ordinal);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLocationNodeRecord.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLocationNodeRecord.java
index b7b252266b4be547057d86affa23aa996a0007cc..2d0a31e067965664d6470a14eeb4a4ab0f87c454 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLocationNodeRecord.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLocationNodeRecord.java
@@ -34,6 +34,8 @@ public class DatasetLocationNodeRecord
 
     public String location;
 
+    public Integer link_info;
+
     public String data_store_code;
 
     public String data_store_url;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
index 5376a340116852693f0af0011e21ef6371920740..95831ed008dae4f9ea1b7bcf7e36758f17949c74 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
@@ -27,7 +27,6 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.common.CodeRecord;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.common.GenericEntityPropertyRecord;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.common.IPropertyListingQuery;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.fetchoptions.common.MetaProjectWithEntityId;
-
 import it.unimi.dsi.fastutil.longs.LongSet;
 import net.lemnik.eodsql.BaseQuery;
 import net.lemnik.eodsql.DataIterator;
@@ -333,18 +332,19 @@ public interface IDatasetListingQuery extends BaseQuery, IPropertyListingQuery
     public DataIterator<GenericEntityPropertyRecord> getEntityPropertyGenericValues(
             LongSet entityIds, String propertyTypeCode);
 
-    @Select(sql = "with recursive connected_data(id,code,container_id,ordinal,dast_id,location) as ("
-            + "  select distinct d.id,d.code,nullif(r.data_id_parent,d.id),nullif(r.ordinal,r.ordinal),d.dast_id,ed.location"
-            + "  from data as d left outer join external_data as ed on ed.data_id = d.id "
+    @Select(sql = "with recursive connected_data(id,code,container_id,ordinal,dast_id,location,link_info) as ("
+            + "  select distinct d.id,d.code,nullif(r.data_id_parent,d.id),nullif(r.ordinal,r.ordinal),d.dast_id,ed.location,ld.data_id"
+            + "  from data as d left outer join external_data as ed on ed.data_id = d.id"
+            + "  left outer join link_data as ld on ld.data_id = d.id"
             + "  left outer join data_set_relationships as r on r.data_id_parent=d.id"
             + "  where d.code = ?{1}"
             + "  union all"
-            + "    select distinct d.id,d.code,r.data_id_parent,r.ordinal,d.dast_id,ed.location"
+            + "    select distinct d.id,d.code,r.data_id_parent,r.ordinal,d.dast_id,ed.location,ld.data_id"
             + "    from connected_data as cd inner join data_set_relationships as r on r.data_id_parent=cd.id"
-            + "    inner join data as d on r.data_id_child=d.id left outer join external_data as ed on ed.data_id = d.id"
+            + "    inner join data as d on r.data_id_child=d.id left outer join external_data as ed on ed.data_id = d.id left outer join link_data as ld on ld.data_id = d.id"
             + "    where r.relationship_id = ?{2}"
             + ") " +
-            "select cd.id,cd.code,cd.container_id,cd.ordinal,cd.location,d.code as data_store_code, d.remote_url as data_store_url "
+            "select cd.id,cd.code,cd.container_id,cd.ordinal,cd.location,d.code as data_store_code, d.remote_url as data_store_url, cd.link_info "
             + "from connected_data as cd join data_stores as d on cd.dast_id = d.id", fetchSize = FETCH_SIZE)
     public DataIterator<DatasetLocationNodeRecord> listLocationsByDatasetCode(String datasetCode, long relationshipTypeId);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/FileSystemContentCopy.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/FileSystemContentCopy.java
new file mode 100644
index 0000000000000000000000000000000000000000..19792a80b056cb30a978214e364658f6006b8232
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/FileSystemContentCopy.java
@@ -0,0 +1,53 @@
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+public class FileSystemContentCopy implements IContentCopy
+{
+    private static final long serialVersionUID = 1L;
+
+    private String label;
+
+    private String host;
+
+    private String directory;
+
+    private String path;
+
+    private String hash;
+
+    public FileSystemContentCopy()
+    {
+    }
+
+    public FileSystemContentCopy(String label, String host, String directory, String path, String hash)
+    {
+        this.label = label;
+        this.host = host;
+        this.directory = directory;
+        this.path = path;
+        this.hash = hash;
+    }
+
+    @Override
+    public boolean isHyperLinkable()
+    {
+        return false;
+    }
+
+    @Override
+    public String getLocation()
+    {
+        if (hash == null)
+        {
+            return "Host: " + host + "<br/>Directory: " + directory + path;
+        } else
+        {
+            return "Host: " + host + "<br/>Directory: " + directory + path + "<br>Commit hash:" + hash;
+        }
+    }
+
+    @Override
+    public String getLabel()
+    {
+        return label;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IContentCopy.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IContentCopy.java
new file mode 100644
index 0000000000000000000000000000000000000000..d7655c973bfcb8727d19d8c451e023bebdc0482d
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IContentCopy.java
@@ -0,0 +1,12 @@
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+public interface IContentCopy extends Serializable
+{
+    boolean isHyperLinkable();
+
+    String getLabel();
+
+    String getLocation();
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LinkDataSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LinkDataSet.java
index 730b5bf489abdba9d0a8df2f732c0591f7995fe4..48d7204ca0b32b6087fd35631939cc97ac42fb9a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LinkDataSet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LinkDataSet.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
+import java.util.List;
+
 /**
  * A virtual data set storing the reference to the data set in external data management system. Link data sets have no physical representation in
  * local dss.
@@ -30,6 +32,8 @@ public class LinkDataSet extends AbstractExternalData
 
     private String externalCode;
 
+    private List<IContentCopy> copies;
+
     public LinkDataSet()
     {
         this(false);
@@ -61,6 +65,16 @@ public class LinkDataSet extends AbstractExternalData
         this.externalCode = externalCode;
     }
 
+    public List<IContentCopy> getCopies()
+    {
+        return copies;
+    }
+
+    public void setCopies(List<IContentCopy> copies)
+    {
+        this.copies = copies;
+    }
+
     @Override
     public boolean isLinkData()
     {
@@ -78,4 +92,11 @@ public class LinkDataSet extends AbstractExternalData
     {
         return DataSetKind.LINK;
     }
+
+    @Override
+    public boolean isAvailable()
+    {
+        return false;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UrlContentCopy.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UrlContentCopy.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d8b675fb9381a3ffc7208b65522137b2009d6e9
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UrlContentCopy.java
@@ -0,0 +1,38 @@
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+public class UrlContentCopy implements IContentCopy
+{
+    private static final long serialVersionUID = 1L;
+
+    private String label;
+
+    private String url;
+
+    public UrlContentCopy(String label, String url)
+    {
+        this.label = label;
+        this.url = url;
+    }
+
+    public UrlContentCopy()
+    {
+    }
+
+    @Override
+    public boolean isHyperLinkable()
+    {
+        return true;
+    }
+
+    @Override
+    public String getLabel()
+    {
+        return label;
+    }
+
+    @Override
+    public String getLocation()
+    {
+        return url;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
index 38b11ef15a7dbe3a01532f01f91bcb4b3d487d2a..93a8e3466daf7a508288c2baa7809c066ba505a4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
@@ -18,11 +18,14 @@ package ch.systemsx.cisd.openbis.generic.shared.translator;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Pattern;
 
 import ch.systemsx.cisd.openbis.common.types.BooleanOrUnknown;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
@@ -33,6 +36,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalDataManagementSystemType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileSystemContentCopy;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IContentCopy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
@@ -42,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UrlContentCopy;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ContentCopyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetRelationshipPE;
@@ -329,6 +336,35 @@ public class DataSetTranslator
             linkDataSet.setExternalCode(copy.getExternalCode());
         }
 
+        List<IContentCopy> translatedCopies = new ArrayList<>();
+        for (ContentCopyPE copy : linkDataPE.getContentCopies())
+        {
+            ExternalDataManagementSystemPE edms = copy.getExternalDataManagementSystem();
+            String address = edms.getAddress();
+            ExternalDataManagementSystemType type = edms.getAddressType();
+            String label = edms.getLabel() == null ? edms.getCode() : edms.getLabel();
+            IContentCopy translatedCopy;
+            if (ExternalDataManagementSystemType.FILE_SYSTEM.equals(type))
+            {
+                String[] split = address.split(":");
+                translatedCopy = new FileSystemContentCopy(label, split[0], split[1], copy.getPath(), copy.getGitCommitHash());
+            } else
+            {
+                translatedCopy = new UrlContentCopy(label,
+                        address.replaceAll(Pattern.quote("${") + ".*" + Pattern.quote("}"), copy.getExternalCode()));
+            }
+            translatedCopies.add(translatedCopy);
+        }
+        Collections.sort(translatedCopies, new Comparator<IContentCopy>()
+            {
+                @Override
+                public int compare(IContentCopy copy1, IContentCopy copy2)
+                {
+                    return copy1.getLabel().compareTo(copy2.getLabel());
+                }
+            });
+        linkDataSet.setCopies(translatedCopies);
+
         return linkDataSet;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertiesPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertiesPanel.java
index e3551dac5e49465ce6ad18eee1264895be59700e..151e5efc8f097a7bfb8f2ba8b23b60a08b9a1cfa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertiesPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertiesPanel.java
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Map;
 
 import com.extjs.gxt.ui.client.widget.ContentPanel;
+import com.google.gwt.user.client.ui.Anchor;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
@@ -35,6 +36,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStore;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IContentCopy;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PhysicalDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.PropertiesPanelUtils;
@@ -86,22 +89,26 @@ public class DataSetPropertiesPanel extends ContentPanel
         properties.put(messageProvider.getMessage(Dict.DATA_SET),
                 new ExternalHyperlink(dataset.getPermId(), dataset.getPermlink()));
 
+        properties.put(messageProvider.getMessage(Dict.DATA_SET_TYPE), datasetType);
+
         if (dataset.isLinkData())
         {
-            LinkDataSetAnchor anchor = LinkDataSetAnchor.tryCreate(dataset.tryGetAsLinkDataSet());
-
-            if (anchor != null)
+            LinkDataSet linkDataSet = dataset.tryGetAsLinkDataSet();
+            int counter = 1;
+            for (IContentCopy copy : linkDataSet.getCopies())
             {
-                anchor.setHTML(dataset.tryGetAsLinkDataSet().getExternalCode());
-                properties.put(messageProvider.getMessage(Dict.LINKED_DATA_SET), anchor);
-            } else
-            {
-                properties.put(messageProvider.getMessage(Dict.LINKED_DATA_SET), dataset
-                        .tryGetAsLinkDataSet().getExternalCode());
+                if (copy.isHyperLinkable())
+                {
+                    String url = copy.getLocation();
+                    Anchor anchor = new Anchor(copy.getLabel(), url);
+                    properties.put("Copy " + counter++, anchor);
+                } else
+                {
+                    properties.put("Copy " + counter++, copy.getLocation());
+                }
             }
         }
 
-        properties.put(messageProvider.getMessage(Dict.DATA_SET_TYPE), datasetType);
         properties.put(messageProvider.getMessage(Dict.SOURCE_TYPE), dataset.getSourceType());
 
         properties.put(messageProvider.getMessage(Dict.DATA_PRODUCER_CODE),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetViewer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetViewer.java
index ee33d684341bc293a98ff59909ef79c22c2a0440..49b00399bee31f280850541ea68179de1e75f439 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetViewer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetViewer.java
@@ -276,14 +276,8 @@ abstract public class GenericDataSetViewer extends AbstractViewerWithVerticalSpl
         {
             container.addSection(panel);
         }
-        // data
-        if (dataset.isLinkData())
-        {
-            container.addSection(new LinkDataViewSection(context, dataset.tryGetAsLinkDataSet()));
-        } else
-        {
-            container.addSection(new DataViewSection(context, dataset));
-        }
+
+        container.addSection(new DataViewSection(context, dataset));
 
         if (dataset.isContainer())
         {
@@ -386,8 +380,7 @@ abstract public class GenericDataSetViewer extends AbstractViewerWithVerticalSpl
     @Override
     public DatabaseModificationKind[] getRelevantModifications()
     {
-        return new DatabaseModificationKind[]
-        { DatabaseModificationKind.edit(ObjectKind.DATA_SET),
+        return new DatabaseModificationKind[] { DatabaseModificationKind.edit(ObjectKind.DATA_SET),
                 DatabaseModificationKind.createOrDelete(ObjectKind.DATA_SET),
                 DatabaseModificationKind.createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
                 DatabaseModificationKind.edit(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/LinkDataViewSection.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/LinkDataViewSection.java
deleted file mode 100644
index 90d3cf425d58c0419169c81c3b364005bca634a8..0000000000000000000000000000000000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/LinkDataViewSection.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2012 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.openbis.plugin.generic.client.web.client.application.dataset;
-
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.Widget;
-
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplayTypeIDGenerator;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkDataSet;
-
-/**
- * @author pkupczyk
- */
-public class LinkDataViewSection extends TabContent
-{
-    private final LinkDataSet dataset;
-
-    public LinkDataViewSection(final IViewContext<?> viewContext, final LinkDataSet dataset)
-    {
-        super(viewContext.getMessage(Dict.DATA_VIEW), viewContext, dataset);
-        this.dataset = dataset;
-        setIds(DisplayTypeIDGenerator.DATA_SET_DATA_SECTION);
-    }
-
-    @Override
-    protected void showContent()
-    {
-        Panel content = new FlowPanel();
-        content.setStyleName("linkDataViewContent");
-        content.add(createInfoWidget());
-        content.add(createLinkWidget());
-        add(content);
-
-    }
-
-    private Widget createInfoWidget()
-    {
-        Label label = new Label(viewContext.getMessage(Dict.LINKED_DATA_SET_INFO));
-        label.addStyleName("linkDataViewInfo");
-        return label;
-    }
-
-    private Widget createLinkWidget()
-    {
-        LinkDataSetAnchor anchor = LinkDataSetAnchor.tryCreate(dataset);
-
-        if (anchor != null)
-        {
-            Label label = new Label(viewContext.getMessage(Dict.LINKED_DATA_SET_LINK));
-            label.addStyleName("linkDataViewLabel");
-
-            anchor.setText(StringEscapeUtils.unescapeHtml(dataset.getExternalDataManagementSystem()
-                    .getLabel() + ":" + StringEscapeUtils.unescapeHtml(dataset.getExternalCode())));
-
-            Panel panel = new HorizontalPanel();
-            panel.add(label);
-            panel.add(anchor);
-            return panel;
-        } else
-        {
-            return new Label(viewContext.getMessage(Dict.LINKED_DATA_SET_LINK_NOT_AVAILABLE_MSG));
-        }
-    }
-}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslatorTest.java
index 099da63f192d483ac6d47995d59a4246a797ab22..631311addf21ca35f07c0dc681b24f4e86008db5 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslatorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslatorTest.java
@@ -18,6 +18,7 @@ import ch.systemsx.cisd.openbis.generic.server.TestJythonEvaluatorPool;
 import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalDataManagementSystemType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PhysicalDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ContentCopyPE;
@@ -209,6 +210,8 @@ public class DataSetTranslatorTest extends AssertJUnit
         ExternalDataManagementSystemPE edms = new ExternalDataManagementSystemPE();
         edms.setCode("EDMS");
         edms.setLabel("Label");
+        edms.setAddress("http://ethz.ch");
+        edms.setAddressType(ExternalDataManagementSystemType.URL);
 
         ContentCopyPE copy = new ContentCopyPE();
         copy.setExternalCode("TEST EXTERNAL CODE");