From bd97e5ebe9aba4a6692bfbf858b478b52153e629 Mon Sep 17 00:00:00 2001
From: vkovtun <viktor.kovtun@id.ethz.ch>
Date: Mon, 4 Dec 2023 19:09:16 +0100
Subject: [PATCH] BIS-772: Working on combining export formats. Fixing issues
 with tests.

---
 .../v3/executor/exporter/EntitiesFinder.java  |   6 +-
 .../v3/executor/exporter/ExportExecutor.java  | 200 +++-
 .../systemtest/asapi/v3/ExportData.java       | 938 +++++++++---------
 .../export/export-data-set-html.zip           | Bin 789 -> 1029 bytes
 .../test_files/export/export-sample-all.zip   | Bin 0 -> 14769 bytes
 5 files changed, 630 insertions(+), 514 deletions(-)
 create mode 100644 server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/test_files/export/export-sample-all.zip

diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/EntitiesFinder.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/EntitiesFinder.java
index f56d676e1f8..b0ef245f381 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/EntitiesFinder.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/EntitiesFinder.java
@@ -157,7 +157,11 @@ class EntitiesFinder
         final List<ExperimentPermId> experimentPermIds = permIds.stream().map(ExperimentPermId::new)
                 .collect(Collectors.toList());
         final ExperimentFetchOptions fetchOptions = new ExperimentFetchOptions();
-        fetchOptions.withProject().withSpace();
+        final ProjectFetchOptions projectFetchOptions = fetchOptions.withProject();
+        projectFetchOptions.withSpace();
+        projectFetchOptions.withRegistrator();
+        projectFetchOptions.withModifier();
+
         fetchOptions.withType().withPropertyAssignments().withPropertyType();
         fetchOptions.withProperties();
         fetchOptions.withRegistrator();
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/ExportExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/ExportExecutor.java
index 3e558392a82..5bedb52808d 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/ExportExecutor.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/exporter/ExportExecutor.java
@@ -46,12 +46,16 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.text.SimpleDateFormat;
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Base64;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.EnumSet;
 import java.util.HashSet;
@@ -62,6 +66,8 @@ import java.util.Set;
 import java.util.stream.Collector;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
@@ -320,7 +326,7 @@ public class ExportExecutor implements IExportExecutor
             final TextFormatting textFormatting, final boolean compatibleWithImport,
             final Set<ExportFormat> exportFormats) throws IOException
     {
-        final String fullFileName = String.format("%s.%s%s", EXPORT_FILE_PREFIX, new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS").format(new Date()),
+        final String zipFileName = String.format("%s.%s%s", EXPORT_FILE_PREFIX, new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS").format(new Date()),
                 ZIP_EXTENSION);
         final Collection<String> warnings = new ArrayList<>();
 
@@ -343,7 +349,7 @@ public class ExportExecutor implements IExportExecutor
                 final ISessionWorkspaceProvider sessionWorkspaceProvider = CommonServiceProvider.getSessionWorkspaceProvider();
                 final File sessionWorkspaceDirectory = sessionWorkspaceProvider.getSessionWorkspace(sessionToken).getCanonicalFile();
                 final File docDirectory = new File(sessionWorkspaceDirectory, PDF_DIRECTORY);
-                mkdir(docDirectory);
+                mkdirs(docDirectory);
 
                 exportSpacesDoc(sessionToken, exportFields, entitiesVo, exportFormats, docDirectory);
                 exportProjectsDoc(sessionToken, docDirectory, entitiesVo, exportFields, exportFormats);
@@ -358,7 +364,15 @@ public class ExportExecutor implements IExportExecutor
             }
         }
 
-        return new ExportResult(fullFileName, warnings);
+        final ISessionWorkspaceProvider sessionWorkspaceProvider = CommonServiceProvider.getSessionWorkspaceProvider();
+        final String sessionWorkspaceDirectoryPath = sessionWorkspaceProvider.getSessionWorkspace(sessionToken).getCanonicalPath();
+        zipDirectory(sessionWorkspaceDirectoryPath, new File(sessionWorkspaceDirectoryPath, zipFileName));
+
+        deleteDirectory(sessionWorkspaceDirectoryPath + '/' + XLSX_DIRECTORY);
+        deleteDirectory(sessionWorkspaceDirectoryPath + '/' + PDF_DIRECTORY);
+        deleteDirectory(sessionWorkspaceDirectoryPath + '/' + DATA_DIRECTORY);
+
+        return new ExportResult(zipFileName, warnings);
     }
 
     private static void exportXlsx(final IApplicationServerApi api, final String sessionToken, final List<ExportablePermId> exportablePermIds,
@@ -371,14 +385,14 @@ public class ExportExecutor implements IExportExecutor
                 exportReferredMasterData, exportFields, textFormatting, compatibleWithImport);
 
         final File xlsxDirectory = new File(sessionWorkspaceDirectory, XLSX_DIRECTORY);
-        mkdir(xlsxDirectory);
+        mkdirs(xlsxDirectory);
 
         final File scriptsDirectory = new File(xlsxDirectory, SCRIPTS_DIRECTORY);
 
         final Map<String, String> xlsExportScripts = xlsExportResult.getScripts();
         if (!xlsExportScripts.isEmpty())
         {
-            mkdir(scriptsDirectory);
+            mkdirs(scriptsDirectory);
 
             for (final Map.Entry<String, String> script : xlsExportScripts.entrySet())
             {
@@ -478,13 +492,13 @@ public class ExportExecutor implements IExportExecutor
         final ISessionWorkspaceProvider sessionWorkspaceProvider = CommonServiceProvider.getSessionWorkspaceProvider();
         final File sessionWorkspaceDirectory = sessionWorkspaceProvider.getSessionWorkspace(sessionToken).getCanonicalFile();
         final File dataDirectory = new File(sessionWorkspaceDirectory, DATA_DIRECTORY);
-        mkdir(dataDirectory);
+        mkdirs(dataDirectory);
 
         final File metadataFile = new File(dataDirectory,
                 getDataDirectoryName(prefix, spaceCode, projectCode, containerCode, code, dataSetTypeCode, dataSetCode, dataSetName, META_FILE_NAME));
 
         final File dataSubdirectory = metadataFile.getParentFile();
-        mkdir(dataSubdirectory);
+        mkdirs(dataSubdirectory);
 
         try (final OutputStream os = new BufferedOutputStream(new FileOutputStream(metadataFile)))
         {
@@ -543,7 +557,7 @@ public class ExportExecutor implements IExportExecutor
                 final String spaceCode = getSpaceCode(entity);
                 final String folderName = spaceCode == null && entity instanceof Sample ? SHARED_SAMPLES_DIRECTORY : spaceCode;
                 final File space = createNextDocFile(docDirectory, folderName, null, null, null, null, null, null, null, null);
-                mkdir(space);
+                mkdirs(space);
             }
         }
     }
@@ -574,7 +588,7 @@ public class ExportExecutor implements IExportExecutor
                 if (projectCode != null)
                 {
                     final File space = createNextDocFile(docDirectory, getSpaceCode(entity), projectCode, null, null, null, null, null, null, null);
-                    mkdir(space);
+                    mkdirs(space);
                 }
             }
         }
@@ -602,7 +616,7 @@ public class ExportExecutor implements IExportExecutor
                     final Project project = experiment.getProject();
                     final File docFile = createNextDocFile(docDirectory, project.getSpace().getCode(), project.getCode(), experiment.getCode(),
                             getEntityName(experiment), null, null, null, null, null);
-                    mkdir(docFile);
+                    mkdirs(docFile);
                 }
             }
 
@@ -611,7 +625,7 @@ public class ExportExecutor implements IExportExecutor
                 final Experiment experiment = (Experiment) entity;
                 final Project project = experiment.getProject();
 
-                createDocFilesForEntity(sessionToken, docDirectory, exportFields, project,
+                createDocFilesForEntity(sessionToken, docDirectory, exportFields, experiment,
                         project.getSpace().getCode(), project.getCode(), experiment.getCode(), getEntityName(experiment), null, null, null, null,
                         exportFormats);
             }
@@ -666,7 +680,7 @@ public class ExportExecutor implements IExportExecutor
                     }
                 }
 
-                mkdir(docFile);
+                mkdirs(docFile);
             }
 
             if (entity instanceof Sample)
@@ -675,8 +689,11 @@ public class ExportExecutor implements IExportExecutor
                 final Experiment experiment = sample.getExperiment();
                 final Sample container = sample.getContainer();
 
+                final String spaceCode = getSpaceCode(sample);
+                final String spaceFolder = spaceCode != null ? spaceCode : SHARED_SAMPLES_DIRECTORY;
+
                 createDocFilesForEntity(sessionToken, docDirectory, exportFields, sample,
-                        getSpaceCode(sample), getProjectCode(sample), experiment != null ? experiment.getCode() : null,
+                        spaceFolder, getProjectCode(sample), experiment != null ? experiment.getCode() : null,
                         experiment != null ? getEntityName(experiment) : null, container != null ? container.getCode() : null, sample.getCode(),
                         getEntityName(sample), null, exportFormats);
             }
@@ -714,59 +731,111 @@ public class ExportExecutor implements IExportExecutor
     {
         if (entity instanceof Space)
         {
-            return ((Space) entity).getCode();
+            return getSpaceCode((Space) entity);
         } else if (entity instanceof Project)
         {
-            return ((Project) entity).getSpace().getCode();
+            return getSpaceCode((Project) entity);
         } else if (entity instanceof Experiment)
         {
-            return ((Experiment) entity).getProject().getSpace().getCode();
+            return getSpaceCode((Experiment) entity);
         } else if (entity instanceof Sample)
         {
-            final Sample sample = (Sample) entity;
-            final Space space = sample.getSpace();
-            if (space != null)
+            return getSpaceCode((Sample) entity);
+        } else if (entity instanceof DataSet)
+        {
+            return getSpaceCode((DataSet) entity);
+        } else
+        {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    private static String getSpaceCode(final Space entity)
+    {
+        return entity.getCode();
+    }
+
+    private static String getSpaceCode(final Project entity)
+    {
+        return entity.getSpace().getCode();
+    }
+
+    private static String getSpaceCode(final Experiment entity)
+    {
+        return entity.getProject().getSpace().getCode();
+    }
+
+    private static String getSpaceCode(final Sample sample)
+    {
+        final Space space = sample.getSpace();
+        if (space != null)
+        {
+            return sample.getSpace().getCode();
+        } else
+        {
+            final Experiment experiment = sample.getExperiment();
+            final Project project = sample.getProject();
+            if (experiment != null)
             {
-                return sample.getSpace().getCode();
+                return experiment.getProject().getSpace().getCode();
+            } else if (project != null)
+            {
+                return project.getSpace().getCode();
             } else
             {
-                final Experiment experiment = sample.getExperiment();
-                final Project project = sample.getProject();
-                if (experiment != null)
-                {
-                    return experiment.getProject().getSpace().getCode();
-                } else if (project != null)
-                {
-                    return project.getSpace().getCode();
-                } else
-                {
-                    return null;
-                }
+                return null;
             }
-        } else
-        {
-            throw new IllegalArgumentException();
         }
     }
 
+    private static String getSpaceCode(final DataSet dataSet)
+    {
+        final Sample sample = dataSet.getSample();
+        return sample != null ? getSpaceCode(sample) :  getSpaceCode(dataSet.getExperiment());
+    }
+
     private static String getProjectCode(final Object entity)
     {
         if (entity instanceof Project)
         {
-            return ((Project) entity).getCode();
+            return getProjectCode((Project) entity);
         } else if (entity instanceof Experiment)
         {
-            return ((Experiment) entity).getProject().getCode();
+            return getProjectCode((Experiment) entity);
         } else if (entity instanceof Sample)
         {
-            final Project project = getProjectForSample((Sample) entity);
-            return project != null ? project.getCode() : null;
+            return getProjectCode((Sample) entity);
+        } else if (entity instanceof DataSet)
+        {
+            return getProjectCode((DataSet) entity);
         } else
         {
             throw new IllegalArgumentException();
         }
     }
 
+    private static String getProjectCode(final Project project)
+    {
+        return project.getCode();
+    }
+
+    private static String getProjectCode(final Experiment experiment)
+    {
+        return experiment.getProject().getCode();
+    }
+
+    private static String getProjectCode(final Sample sample)
+    {
+        final Project project = getProjectForSample(sample);
+        return project != null ? project.getCode() : null;
+    }
+
+    private static String getProjectCode(final DataSet dataSet)
+    {
+        final Sample sample = dataSet.getSample();
+        return sample != null ? getProjectCode(sample) : getProjectCode(dataSet.getExperiment());
+    }
+
     private static Project getProjectForSample(final Sample sample)
     {
         final Experiment experiment = sample.getExperiment();
@@ -911,13 +980,13 @@ public class ExportExecutor implements IExportExecutor
         final boolean isDirectory = dataSetFile.isDirectory();
 
         final File dataDirectory = new File(sessionWorkspaceDirectory, DATA_DIRECTORY);
-        mkdir(dataDirectory);
+        mkdirs(dataDirectory);
 
         final File dataSetFsEntry = new File(dataDirectory, getDataDirectoryName(prefix, spaceCode, projectCode, containerCode, entityCode,
                 dataSetTypeCode, dataSetCode, dataSetName, filePath) + (isDirectory ? "/" : ""));
 
         final File dataSubdirectory = dataSetFsEntry.getParentFile();
-        mkdir(dataSubdirectory);
+        mkdirs(dataSubdirectory);
 
         if (!isDirectory)
         {
@@ -930,7 +999,7 @@ public class ExportExecutor implements IExportExecutor
             }
         } else
         {
-            mkdir(dataSetFsEntry);
+            mkdirs(dataSetFsEntry);
         }
     }
 
@@ -1402,11 +1471,11 @@ public class ExportExecutor implements IExportExecutor
      *
      * @param dir the directory to be created.
      */
-    private static void mkdir(final File dir)
+    private static void mkdirs(final File dir)
     {
         if (!dir.isDirectory())
         {
-            final boolean created = dir.mkdir();
+            final boolean created = dir.mkdirs();
             if (!created)
             {
                 throw new RuntimeException(String.format("Cannot create directory '%s'.", dir.getPath()));
@@ -1414,6 +1483,49 @@ public class ExportExecutor implements IExportExecutor
         }
     }
 
+    private static void zipDirectory(final String sourceDirectory, final File targetZipFile) throws IOException {
+        final Path sourceDir = Paths.get(sourceDirectory);
+        try (final ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetZipFile)))
+        {
+            try(final Stream<Path> stream = Files.walk(sourceDir))
+            {
+                stream.filter(path -> !path.equals(sourceDir) && !path.toFile().equals(targetZipFile))
+                        .forEach(path ->
+                        {
+                            final boolean isDirectory = Files.isDirectory(path);
+                            final String entryName = sourceDir.relativize(path).toString();
+                            final ZipEntry zipEntry = new ZipEntry(entryName + (isDirectory ? "/" : ""));
+                            try
+                            {
+                                zipOutputStream.putNextEntry(zipEntry);
+                                if (!isDirectory)
+                                {
+                                    Files.copy(path, zipOutputStream);
+                                }
+                                zipOutputStream.closeEntry();
+                            } catch (final IOException e)
+                            {
+                                throw new RuntimeException(e);
+                            }
+                        });
+            }
+        }
+    }
+
+    public static void deleteDirectory(final String directoryPath) throws IOException {
+        final Path path = Paths.get(directoryPath);
+        if (Files.exists(path))
+        {
+            try (final Stream<Path> walkStream = Files.walk(path))
+            {
+                walkStream
+                        .sorted(Comparator.reverseOrder())
+                        .map(Path::toFile)
+                        .forEach(File::delete);
+            }
+        }
+    }
+
     private static class EntitiesVo
     {
 
diff --git a/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/ExportData.java b/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/ExportData.java
index 9e4ee1301cb..1b79d3f0eb2 100644
--- a/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/ExportData.java
+++ b/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/ExportData.java
@@ -65,489 +65,489 @@ class ExportData
     static final String RICH_TEXT_WITH_SPREADSHEET_PROPERTY_NAME = "MULTILINE_WITH_SPREADSHEET";
 
     static final Object[][] EXPORT_DATA = {
-//            // XLS: All fields
-//            {
-//                    // Non-existing sample
-//                    "empty-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("WrongPermId"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Space: TEST-SPACE
-//                    "export-space-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Project: TEST-PROJECT
-//                    "export-project-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment: EXP-SPACE-TEST
-//                    "export-experiment-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-compatible-with-import-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    true // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /MP
-//                    "export-sample-shared-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-652"))),
-//                    new AllFields(),
-//                    XlsTextFormat.RICH,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-////            {
-////                    // Sample: /MP:A03
-////                    "export-sample-contained-xlsx.zip",
-////                    EnumSet.of(ExportFormat.XLSX),
-////                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-653"))),
-////                    new AllFields(),
-////                    XlsTextFormat.RICH,
-////                    true, // withReferredTypes
-////                    false // withImportCompatibility
-////            },
-//            {
-//                    // Data set: "ROOT_CONTAINER"
-//                    "export-data-set-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("ROOT_CONTAINER"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample Type: CELL_PLATE
-//                    "export-sample-type-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE_TYPE, new EntityTypePermId("CELL_PLATE", EntityKind.SAMPLE))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample Type: CELL_PLATE
-//                    "export-sample-type-with-referred-types-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE_TYPE, new EntityTypePermId("CELL_PLATE", EntityKind.SAMPLE))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment Type: SIRNA_HCS
-//                    "export-experiment-type-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT_TYPE, new EntityTypePermId("SIRNA_HCS", EntityKind.EXPERIMENT))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Dataset Type: HCS_IMAGE
-//                    "export-data-set-type-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.DATASET_TYPE, new EntityTypePermId("HCS_IMAGE", EntityKind.DATA_SET))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//
-//            // XLS: Selected fields
-//            {
-//                    // Space: TEST-SPACE
-//                    "export-space-filtered-attributes-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
-//                    new SelectedFields(List.of(CODE, REGISTRATOR, DESCRIPTION), List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Project: TEST-PROJECT
-//                    "export-project-filtered-fields-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
-//                    new SelectedFields(
-//                            List.of(REGISTRATOR, REGISTRATION_DATE, CODE, IDENTIFIER, SPACE, DESCRIPTION),
-//                            List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment: EXP-SPACE-TEST
-//                    "export-experiment-filtered-fields-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
-//                    new SelectedFields(
-//                            List.of(CODE, PERM_ID, IDENTIFIER, PROJECT, REGISTRATOR, MODIFIER),
-//                            List.of(new PropertyTypePermId("GENDER"), new PropertyTypePermId("DESCRIPTION"))),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-filtered-fields-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
-//                    new SelectedFields(
-//                            List.of(CODE, PERM_ID, IDENTIFIER, SPACE, PARENTS, CHILDREN, REGISTRATOR, REGISTRATION_DATE, MODIFIER, MODIFICATION_DATE),
-//                            List.of(new PropertyTypePermId("BACTERIUM"), new PropertyTypePermId("COMMENT"), new PropertyTypePermId("ORGANISM"))),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Data set: "20081105092159188-3", type: "HCS_IMAGE"
-//                    "export-data-set-filtered-fields-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("20081105092159188-3"))),
-//                    new SelectedFields(
-//                            List.of(REGISTRATOR, REGISTRATION_DATE, CODE, IDENTIFIER, PARENTS, CHILDREN, STORAGE_CONFIRMATION, PRESENT_IN_ARCHIVE,
-//                                    SAMPLE, EXPERIMENT),
-//                            List.of(new PropertyTypePermId("COMMENT"), new PropertyTypePermId("GENDER"))),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample Type: CELL_PLATE
-//                    "export-sample-type-filtered-attributes-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE_TYPE, new EntityTypePermId("CELL_PLATE", EntityKind.SAMPLE))),
-//                    new SelectedFields(List.of(CODE, AUTO_GENERATE_CODES, DESCRIPTION, GENERATED_CODE_PREFIX, UNIQUE_SUBCODES), List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment Type: SIRNA_HCS
-//                    "export-experiment-type-filtered-attributes-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT_TYPE, new EntityTypePermId("SIRNA_HCS", EntityKind.EXPERIMENT))),
-//                    new SelectedFields(List.of(DESCRIPTION, CODE, MODIFICATION_DATE), List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Dataset Type: HCS_IMAGE
-//                    "export-data-set-type-filtered-attributes-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.DATASET_TYPE, new EntityTypePermId("HCS_IMAGE", EntityKind.DATA_SET))),
-//                    new SelectedFields(List.of(CODE, DISALLOW_DELETION, DESCRIPTION), List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-plain-text-xlsx.zip",
-//                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
-//                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
+            // XLS: All fields
+            {
+                    // Non-existing sample
+                    "empty-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("WrongPermId"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Space: TEST-SPACE
+                    "export-space-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Project: TEST-PROJECT
+                    "export-project-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment: EXP-SPACE-TEST
+                    "export-experiment-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-compatible-with-import-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    true // withImportCompatibility
+            },
+            {
+                    // Sample: /MP
+                    "export-sample-shared-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-652"))),
+                    new AllFields(),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
 //            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-rich-text-xlsx.zip",
+//                    // Sample: /MP:A03
+//                    "export-sample-contained-xlsx.zip",
 //                    EnumSet.of(ExportFormat.XLSX),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
-//                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
-//                    XlsTextFormat.RICH,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//
-//            // HTML: All fields
-//            {
-//                    // Space: TEST-SPACE
-//                    "export-space-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
+//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-653"))),
 //                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Project: TEST-PROJECT
-//                    "export-project-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment: EXP-SPACE-TEST
-//                    "export-experiment-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /MP
-//                    "export-sample-shared-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-652"))),
-//                    new AllFields(),
-//                    XlsTextFormat.RICH,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-////            {
-////                    // Sample: /MP:A03
-////                    "export-sample-contained-html.zip",
-////                    EnumSet.of(ExportFormat.HTML),
-////                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-653"))),
-////                    new AllFields(),
-////                    XlsTextFormat.RICH,
-////                    true, // withReferredTypes
-////                    false // withImportCompatibility
-////            },
-//            {
-//                    // Data set: "ROOT_CONTAINER"
-//                    "export-data-set-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("ROOT_CONTAINER"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//
-//            // HTML: Selected fields
-//            {
-//                    // Space: TEST-SPACE
-//                    "export-space-filtered-fields-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
-//                    new SelectedFields(List.of(CODE, PERM_ID, MODIFICATION_DATE), List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Project: TEST-PROJECT
-//                    "export-project-filtered-fields-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
-//                    new SelectedFields(List.of(PERM_ID, IDENTIFIER, REGISTRATOR, REGISTRATION_DATE), List.of()),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment: EXP-SPACE-TEST
-//                    "export-experiment-filtered-fields-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
-//                    new SelectedFields(List.of(CODE, PARENTS, CHILDREN, REGISTRATOR, REGISTRATION_DATE),
-//                            List.of(new PropertyTypePermId("DESCRIPTION"))),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-filtered-fields-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
-//                    new SelectedFields(
-//                            List.of(CODE, PARENTS, CHILDREN, MODIFIER, MODIFICATION_DATE),
-//                            List.of(new PropertyTypePermId("BACTERIUM"), new PropertyTypePermId("COMMENT"), new PropertyTypePermId("ORGANISM"))),
-//                    XlsTextFormat.PLAIN,
-//                    false, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-plain-text-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
-//                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-rich-text-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
-//                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
-//                    XlsTextFormat.RICH,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-with-image-html.zip",
-//                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
-//                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_WITH_IMAGE_PROPERTY_NAME))),
 //                    XlsTextFormat.RICH,
 //                    true, // withReferredTypes
 //                    false // withImportCompatibility
 //            },
+            {
+                    // Data set: "ROOT_CONTAINER"
+                    "export-data-set-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("ROOT_CONTAINER"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample Type: CELL_PLATE
+                    "export-sample-type-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE_TYPE, new EntityTypePermId("CELL_PLATE", EntityKind.SAMPLE))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample Type: CELL_PLATE
+                    "export-sample-type-with-referred-types-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE_TYPE, new EntityTypePermId("CELL_PLATE", EntityKind.SAMPLE))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment Type: SIRNA_HCS
+                    "export-experiment-type-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT_TYPE, new EntityTypePermId("SIRNA_HCS", EntityKind.EXPERIMENT))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Dataset Type: HCS_IMAGE
+                    "export-data-set-type-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.DATASET_TYPE, new EntityTypePermId("HCS_IMAGE", EntityKind.DATA_SET))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+
+            // XLS: Selected fields
+            {
+                    // Space: TEST-SPACE
+                    "export-space-filtered-attributes-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
+                    new SelectedFields(List.of(CODE, REGISTRATOR, DESCRIPTION), List.of()),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Project: TEST-PROJECT
+                    "export-project-filtered-fields-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
+                    new SelectedFields(
+                            List.of(REGISTRATOR, REGISTRATION_DATE, CODE, IDENTIFIER, SPACE, DESCRIPTION),
+                            List.of()),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment: EXP-SPACE-TEST
+                    "export-experiment-filtered-fields-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
+                    new SelectedFields(
+                            List.of(CODE, PERM_ID, IDENTIFIER, PROJECT, REGISTRATOR, MODIFIER),
+                            List.of(new PropertyTypePermId("GENDER"), new PropertyTypePermId("DESCRIPTION"))),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-filtered-fields-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
+                    new SelectedFields(
+                            List.of(CODE, PERM_ID, IDENTIFIER, SPACE, PARENTS, CHILDREN, REGISTRATOR, REGISTRATION_DATE, MODIFIER, MODIFICATION_DATE),
+                            List.of(new PropertyTypePermId("BACTERIUM"), new PropertyTypePermId("COMMENT"), new PropertyTypePermId("ORGANISM"))),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Data set: "20081105092159188-3", type: "HCS_IMAGE"
+                    "export-data-set-filtered-fields-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("20081105092159188-3"))),
+                    new SelectedFields(
+                            List.of(REGISTRATOR, REGISTRATION_DATE, CODE, IDENTIFIER, PARENTS, CHILDREN, STORAGE_CONFIRMATION, PRESENT_IN_ARCHIVE,
+                                    SAMPLE, EXPERIMENT),
+                            List.of(new PropertyTypePermId("COMMENT"), new PropertyTypePermId("GENDER"))),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample Type: CELL_PLATE
+                    "export-sample-type-filtered-attributes-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE_TYPE, new EntityTypePermId("CELL_PLATE", EntityKind.SAMPLE))),
+                    new SelectedFields(List.of(CODE, AUTO_GENERATE_CODES, DESCRIPTION, GENERATED_CODE_PREFIX, UNIQUE_SUBCODES), List.of()),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment Type: SIRNA_HCS
+                    "export-experiment-type-filtered-attributes-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT_TYPE, new EntityTypePermId("SIRNA_HCS", EntityKind.EXPERIMENT))),
+                    new SelectedFields(List.of(DESCRIPTION, CODE, MODIFICATION_DATE), List.of()),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Dataset Type: HCS_IMAGE
+                    "export-data-set-type-filtered-attributes-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.DATASET_TYPE, new EntityTypePermId("HCS_IMAGE", EntityKind.DATA_SET))),
+                    new SelectedFields(List.of(CODE, DISALLOW_DELETION, DESCRIPTION), List.of()),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-plain-text-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
+                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-rich-text-xlsx.zip",
+                    EnumSet.of(ExportFormat.XLSX),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
+                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+
+            // HTML: All fields
+            {
+                    // Space: TEST-SPACE
+                    "export-space-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Project: TEST-PROJECT
+                    "export-project-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment: EXP-SPACE-TEST
+                    "export-experiment-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /MP
+                    "export-sample-shared-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-652"))),
+                    new AllFields(),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
 //            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-with-spreadsheet-html.zip",
+//                    // Sample: /MP:A03
+//                    "export-sample-contained-html.zip",
 //                    EnumSet.of(ExportFormat.HTML),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
-//                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_WITH_SPREADSHEET_PROPERTY_NAME))),
-//                    XlsTextFormat.RICH,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//
-//            // PDF: All fields
-//            {
-//                    // Space: TEST-SPACE
-//                    "export-space-pdf.zip",
-//                    EnumSet.of(ExportFormat.PDF),
-//                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Project: TEST-PROJECT
-//                    "export-project-pdf.zip",
-//                    EnumSet.of(ExportFormat.PDF),
-//                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Experiment: EXP-SPACE-TEST
-//                    "export-experiment-pdf.zip",
-//                    EnumSet.of(ExportFormat.PDF),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
-//                    "export-sample-pdf.zip",
-//                    EnumSet.of(ExportFormat.PDF),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /MP
-//                    "export-sample-shared-pdf.zip",
-//                    EnumSet.of(ExportFormat.PDF),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-652"))),
+//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-653"))),
 //                    new AllFields(),
 //                    XlsTextFormat.RICH,
 //                    true, // withReferredTypes
 //                    false // withImportCompatibility
 //            },
-//            {
-//                    // Data set: "ROOT_CONTAINER"
-//                    "export-data-set-pdf.zip",
-//                    EnumSet.of(ExportFormat.PDF),
-//                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("ROOT_CONTAINER"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//
-//            // Data
-//            {
-//                    // Sample: /CISD/NEMO/CP-TEST-3
-//                    "export-sample-data.zip",
-//                    EnumSet.of(ExportFormat.DATA),
-//                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200902091225616-1027"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
-//            {
-//                    // Sample: /CISD/NEMO/EXP1
-//                    "export-experiment-data.zip",
-//                    EnumSet.of(ExportFormat.DATA),
-//                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new SamplePermId("200811050951882-1028"))),
-//                    new AllFields(),
-//                    XlsTextFormat.PLAIN,
-//                    true, // withReferredTypes
-//                    false // withImportCompatibility
-//            },
+            {
+                    // Data set: "ROOT_CONTAINER"
+                    "export-data-set-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("ROOT_CONTAINER"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+
+            // HTML: Selected fields
+            {
+                    // Space: TEST-SPACE
+                    "export-space-filtered-fields-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
+                    new SelectedFields(List.of(CODE, PERM_ID, MODIFICATION_DATE), List.of()),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Project: TEST-PROJECT
+                    "export-project-filtered-fields-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
+                    new SelectedFields(List.of(PERM_ID, IDENTIFIER, REGISTRATOR, REGISTRATION_DATE), List.of()),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment: EXP-SPACE-TEST
+                    "export-experiment-filtered-fields-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
+                    new SelectedFields(List.of(CODE, PARENTS, CHILDREN, REGISTRATOR, REGISTRATION_DATE),
+                            List.of(new PropertyTypePermId("DESCRIPTION"))),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-filtered-fields-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
+                    new SelectedFields(
+                            List.of(CODE, PARENTS, CHILDREN, MODIFIER, MODIFICATION_DATE),
+                            List.of(new PropertyTypePermId("BACTERIUM"), new PropertyTypePermId("COMMENT"), new PropertyTypePermId("ORGANISM"))),
+                    XlsTextFormat.PLAIN,
+                    false, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-plain-text-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
+                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-rich-text-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
+                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_PROPERTY_NAME))),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-with-image-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
+                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_WITH_IMAGE_PROPERTY_NAME))),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-with-spreadsheet-html.zip",
+                    EnumSet.of(ExportFormat.HTML),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, null)), // null perm ID indicates that the newly created value in the setup of the test should be used.
+                    new SelectedFields(List.of(IDENTIFIER, CODE), List.of(new PropertyTypePermId(RICH_TEXT_WITH_SPREADSHEET_PROPERTY_NAME))),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+
+            // PDF: All fields
+            {
+                    // Space: TEST-SPACE
+                    "export-space-pdf.zip",
+                    EnumSet.of(ExportFormat.PDF),
+                    List.of(new ExportablePermId(ExportableKind.SPACE, new SpacePermId("TEST-SPACE"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Project: TEST-PROJECT
+                    "export-project-pdf.zip",
+                    EnumSet.of(ExportFormat.PDF),
+                    List.of(new ExportablePermId(ExportableKind.PROJECT, new ProjectPermId("20120814110011738-105"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Experiment: EXP-SPACE-TEST
+                    "export-experiment-pdf.zip",
+                    EnumSet.of(ExportFormat.PDF),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new ExperimentPermId("201206190940555-1032"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /TEST-SPACE/TEST-PROJECT/FV-TEST
+                    "export-sample-pdf.zip",
+                    EnumSet.of(ExportFormat.PDF),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("201206191219327-1054"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /MP
+                    "export-sample-shared-pdf.zip",
+                    EnumSet.of(ExportFormat.PDF),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200811050947161-652"))),
+                    new AllFields(),
+                    XlsTextFormat.RICH,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Data set: "ROOT_CONTAINER"
+                    "export-data-set-pdf.zip",
+                    EnumSet.of(ExportFormat.PDF),
+                    List.of(new ExportablePermId(ExportableKind.DATASET, new DataSetPermId("ROOT_CONTAINER"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+
+            // Data
+            {
+                    // Sample: /CISD/NEMO/CP-TEST-3
+                    "export-sample-data.zip",
+                    EnumSet.of(ExportFormat.DATA),
+                    List.of(new ExportablePermId(ExportableKind.SAMPLE, new SamplePermId("200902091225616-1027"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
+            {
+                    // Sample: /CISD/NEMO/EXP1
+                    "export-experiment-data.zip",
+                    EnumSet.of(ExportFormat.DATA),
+                    List.of(new ExportablePermId(ExportableKind.EXPERIMENT, new SamplePermId("200811050951882-1028"))),
+                    new AllFields(),
+                    XlsTextFormat.PLAIN,
+                    true, // withReferredTypes
+                    false // withImportCompatibility
+            },
 
             // All
             {
diff --git a/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/test_files/export/export-data-set-html.zip b/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/test_files/export/export-data-set-html.zip
index c55b23993c96d9d5beaca3fe426bb5adc095b89e..88bb91f7fb876ed6aecfa0d449c1a5dce2842706 100644
GIT binary patch
delta 319
zcmbQr*2=*f;LXe;!ob17!SHBC%S2v786XwTfCM;!?1GdueP_>Lmx+q9D(LcpNb>qF
zu5ON@J|RGL%pl_&JwVjPo)wHBda^l_emzV(6VwWj@d#i7WWp@d5AbGW5@CQl4(uwJ
zHju3dkPBqOwL#s0UHjyGCQ-(96aD41(M`{{P3re$WMEhdv_cPIG?4WZsC@DpCTTua
N237`;l0{%w000f2JL3QV

delta 124
zcmZqWn99Z*;LXe;!ob17!Ju1PK9Sdu8AR>&08yLS7*{ZY7?U?L>4WJ=X6ecQn0P0j
zViwX4@MdHZVSsB5&$mtL_hn>YSjxn}pvQm=>L>4Gw&Y`GU}m@u6xIOBGcW)EF&7zb

diff --git a/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/test_files/export/export-sample-all.zip b/server-application-server/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/test_files/export/export-sample-all.zip
new file mode 100644
index 0000000000000000000000000000000000000000..806e0ba0cf6c198c187d90ed24cc114b1a65a4ae
GIT binary patch
literal 14769
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

literal 0
HcmV?d00001

-- 
GitLab