diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/CrateReader.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/CrateReader.java
new file mode 100644
index 00000000..35fe0f66
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/CrateReader.java
@@ -0,0 +1,340 @@
+package edu.kit.datamanager.ro_crate.reader;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import edu.kit.datamanager.ro_crate.RoCrate;
+import edu.kit.datamanager.ro_crate.context.CrateMetadataContext;
+import edu.kit.datamanager.ro_crate.context.RoCrateMetadataContext;
+import edu.kit.datamanager.ro_crate.entities.contextual.ContextualEntity;
+import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
+import edu.kit.datamanager.ro_crate.entities.data.RootDataEntity;
+import edu.kit.datamanager.ro_crate.special.IdentifierUtils;
+import edu.kit.datamanager.ro_crate.special.JsonUtilFunctions;
+import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
+import edu.kit.datamanager.ro_crate.validation.Validator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+/**
+ * This class allows reading crates from the outside into the library in order
+ * to inspect or modify it.
+ *
+ * The constructor takes a strategy to support different ways of importing the
+ * crates. (from zip, folder, etc.).
+ *
+ * The reader consideres "hasPart" and "isPartOf" properties and considers all
+ * entities (in-)directly connected to the root entity ("./") as DataEntities.
+ *
+ * @param the type of the location parameter
+ */
+public class CrateReader {
+
+ private static final Logger logger = LoggerFactory.getLogger(CrateReader.class);
+
+ /**
+ * This is a private inner class that shall not be exposed. **Do not make it
+ * public or protected.** It serves only the purpose of unsafe operations
+ * while reading a crate and may be specific to this implementation.
+ */
+ private static class RoCrateUnsafe extends RoCrate {
+
+ public void addDataEntityWithoutRootHasPart(DataEntity entity) {
+ this.metadataContext.checkEntity(entity);
+ this.roCratePayload.addDataEntity(entity);
+ }
+ }
+
+ /**
+ * If the number of JSON entities in the crate is larger than this number,
+ * parallelization will be used.
+ */
+ private static final int PARALLELIZATION_THRESHOLD = 100;
+
+ private static final String FILE_PREVIEW_FILES = "ro-crate-preview_files";
+ private static final String FILE_PREVIEW_HTML = "ro-crate-preview.html";
+ private static final String FILE_METADATA_JSON = "ro-crate-metadata.json";
+
+ protected static final String SPECIFICATION_PREFIX = "https://w3id.org/ro/crate/";
+
+ protected static final String PROP_ABOUT = "about";
+ protected static final String PROP_CONTEXT = "@context";
+ protected static final String PROP_CONFORMS_TO = "conformsTo";
+ protected static final String PROP_GRAPH = "@graph";
+ protected static final String PROP_HAS_PART = "hasPart";
+ protected static final String PROP_ID = "@id";
+
+ private final GenericReaderStrategy strategy;
+
+ public CrateReader(GenericReaderStrategy strategy) {
+ this.strategy = strategy;
+ }
+
+ /**
+ * This function will read the location (using one of the specified
+ * strategies) and then build the relation between the entities.
+ *
+ * @param location the location of the ro-crate to be read
+ * @return the read RO-crate
+ */
+ public RoCrate readCrate(T location) {
+ // get the ro-crate-metadata.json
+ ObjectNode metadataJson = strategy.readMetadataJson(location);
+ // get the content of the crate
+ File files = strategy.readContent(location);
+
+ // this set will contain the files that are associated with entities
+ HashSet usedFiles = new HashSet<>();
+ usedFiles.add(files.toPath().resolve(FILE_METADATA_JSON).toFile().getPath());
+ usedFiles.add(files.toPath().resolve(FILE_PREVIEW_HTML).toFile().getPath());
+ usedFiles.add(files.toPath().resolve(FILE_PREVIEW_FILES).toFile().getPath());
+ return rebuildCrate(metadataJson, files, usedFiles);
+ }
+
+ private RoCrate rebuildCrate(ObjectNode metadataJson, File files, HashSet usedFiles) {
+ if (metadataJson == null) {
+ logger.error("Metadata JSON is null, cannot rebuild crate");
+ return null;
+ }
+ if (files == null) {
+ logger.error("Content files directory is null, cannot rebuild crate");
+ return null;
+ }
+ JsonNode context = metadataJson.get(PROP_CONTEXT);
+
+ CrateMetadataContext crateContext = new RoCrateMetadataContext(context);
+ RoCrateUnsafe crate = new RoCrateUnsafe();
+ crate.setMetadataContext(crateContext);
+ JsonNode graph = metadataJson.get(PROP_GRAPH);
+
+ if (graph.isArray()) {
+ moveRootEntitiesFromGraphToCrate(crate, (ArrayNode) graph);
+ RootDataEntity root = crate.getRootDataEntity();
+ if (root != null) {
+ Set dataEntityIds = getDataEntityIds(root, graph);
+ for (JsonNode entityJson : graph) {
+ String eId = unpackId(entityJson);
+ if (dataEntityIds.contains(eId)) {
+ // data entity
+ DataEntity.DataEntityBuilder dataEntity = new DataEntity.DataEntityBuilder()
+ .setAll(entityJson.deepCopy());
+
+ // Handle data entities with corresponding file
+ checkFolderHasFile(entityJson.get(PROP_ID).asText(), files).ifPresent(file -> {
+ usedFiles.add(file.getPath());
+ dataEntity.setLocationWithExceptions(file.toPath())
+ .setId(file.getName());
+ });
+
+ crate.addDataEntityWithoutRootHasPart(dataEntity.build());
+ } else {
+ // contextual entity
+ crate.addContextualEntity(
+ new ContextualEntity.ContextualEntityBuilder()
+ .setAll(entityJson.deepCopy())
+ .build());
+ }
+ }
+ }
+ }
+
+ Collection untrackedFiles = Arrays.stream(
+ Optional.ofNullable(files.listFiles()).orElse(new File[0]))
+ .filter(f -> !usedFiles.contains(f.getPath()))
+ .collect(Collectors.toSet());
+
+ crate.setUntrackedFiles(untrackedFiles);
+ Validator defaultValidation = new Validator(new JsonSchemaValidation());
+ defaultValidation.validate(crate);
+ return crate;
+ }
+
+ /**
+ * Extracts graph connections from top to bottom.
+ *
+ * Example: (connections.get(parent) -> children)
+ *
+ * @param graph the ArrayNode with all Entities.
+ * @return the graph connections.
+ */
+ protected Map> makeEntityGraph(JsonNode graph) {
+ Map> connections = new HashMap<>();
+
+ Map idToNodes = new HashMap<>();
+ StreamSupport.stream(graph.spliterator(), false)
+ .forEach(jsonNode -> idToNodes.put(unpackId(jsonNode), jsonNode));
+
+ for (JsonNode entityNode : graph) {
+ String currentId = unpackId(entityNode);
+ StreamSupport.stream(entityNode.path("hasPart").spliterator(), false)
+ .map(this::unpackId)
+ .map(s -> idToNodes.getOrDefault(s, null))
+ .filter(Objects::nonNull)
+ .forEach(child -> connections.computeIfAbsent(currentId, key -> new HashSet<>())
+ .add(unpackId(child)));
+ StreamSupport.stream(entityNode.path("isPartOf").spliterator(), false)
+ .map(this::unpackId)
+ .map(s -> idToNodes.getOrDefault(s, null))
+ .filter(Objects::nonNull)
+ .forEach(parent -> connections.computeIfAbsent(unpackId(parent), key -> new HashSet<>())
+ .add(currentId));
+ }
+ return connections;
+ }
+
+ protected Set getDataEntityIds(RootDataEntity root, JsonNode graph) {
+ if (root == null) {
+ return Set.of();
+ }
+ Map> network = makeEntityGraph(graph);
+ Set directDataEntities = new HashSet<>(root.hasPart);
+
+ Stack processingQueue = new Stack<>();
+ processingQueue.addAll(directDataEntities);
+ Set result = new HashSet<>();
+
+ while (!processingQueue.empty()) {
+ String currentId = processingQueue.pop();
+ result.add(currentId);
+ network.getOrDefault(currentId, new HashSet<>()).stream()
+ .filter(subId -> !result.contains(subId)) // avoid loops!
+ .forEach(subId -> {
+ result.add(subId);
+ processingQueue.add(subId);
+ });
+ }
+ return result;
+ }
+
+ protected String unpackId(JsonNode node) {
+ if (node.isTextual()) {
+ return node.asText();
+ } else /*if (node.isObject())*/ {
+ return node.path(PROP_ID).asText();
+ }
+ }
+
+ protected Optional checkFolderHasFile(String filepathOrId, File folder) {
+ if (IdentifierUtils.isUrl(filepathOrId)) {
+ return Optional.empty();
+ }
+ return IdentifierUtils.decode(filepathOrId)
+ .map(decoded -> folder.toPath().resolve(decoded).toFile())
+ .filter(File::exists);
+ }
+
+ /**
+ * Moves the descriptor and the root entity from the graph to the crate.
+ *
+ * Extracts the root data entity and the Metadata File Descriptor from the
+ * graph and inserts them into the crate object. It also deletes it from the
+ * graph. We will need the root dataset to distinguish between data entities
+ * and contextual entities.
+ *
+ * @param crate the crate, which will receive the entities, if available in
+ * the graph.
+ * @param graph the graph of the Metadata JSON file, where the entities are
+ * extracted and removed from.
+ */
+ protected void moveRootEntitiesFromGraphToCrate(RoCrate crate, ArrayNode graph) {
+ Optional maybeDescriptor = getMetadataDescriptor(graph);
+
+ maybeDescriptor.ifPresent(descriptor -> {
+ setCrateDescriptor(crate, descriptor);
+ JsonUtilFunctions.removeJsonNodeFromArrayNode(graph, descriptor);
+
+ Optional maybeRoot = extractRoot(graph, descriptor);
+
+ maybeRoot.ifPresent(root -> {
+ Set hasPartIds = extractHasPartIds(root);
+
+ crate.setRootDataEntity(
+ new RootDataEntity.RootDataEntityBuilder()
+ .setAll(root.deepCopy())
+ .setHasPart(hasPartIds)
+ .build());
+
+ JsonUtilFunctions.removeJsonNodeFromArrayNode(graph, root);
+ });
+ });
+ }
+
+ /**
+ * Find the metadata descriptor.
+ *
+ * Currently prefers algorithm of version 1.1 over the one of 1.2-DRAFT.
+ *
+ * @param graph the graph to search the descriptor in.
+ * @return the metadata descriptor of the crate.
+ */
+ protected Optional getMetadataDescriptor(ArrayNode graph) {
+ boolean isParallel = graph.size() > PARALLELIZATION_THRESHOLD;
+ // use the algorithm described here:
+ // https://www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity
+ Optional maybeDescriptor = StreamSupport.stream(graph.spliterator(), isParallel)
+ // "2. if the conformsTo property is a URI that starts with
+ // https://w3id.org/ro/crate/"
+ .filter(node -> node.path(PROP_CONFORMS_TO).path(PROP_ID).asText().startsWith(SPECIFICATION_PREFIX))
+ // "3. from this entity’s about object keep the @id URI as variable root"
+ .filter(node -> node.path(PROP_ABOUT).path(PROP_ID).isTextual())
+ // There should be only one descriptor. If multiple exist, we take the first
+ // one.
+ .findFirst();
+ return maybeDescriptor.or(()
+ -> // from https://www.researchobject.org/ro-crate/1.2-DRAFT/root-data-entity.html#finding-the-root-data-entity
+ StreamSupport.stream(graph.spliterator(), isParallel)
+ .filter(node -> node.path(PROP_ID).asText().equals(FILE_METADATA_JSON))
+ .findFirst()
+ );
+ }
+
+ /**
+ * Extracts the root entity from the graph, using the information from the
+ * descriptor.
+ *
+ * Basically implements step 5 of the algorithm described here:
+ *
+ * https://www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity
+ *
+ *
+ * @param graph the graph from the metadata JSON-LD file
+ * @param descriptor the RO-Crate descriptor
+ * @return the root entity, if found
+ */
+ private Optional extractRoot(ArrayNode graph, JsonNode descriptor) {
+ String rootId = descriptor.get(PROP_ABOUT).get(PROP_ID).asText();
+ boolean isParallel = graph.size() > PARALLELIZATION_THRESHOLD;
+ return StreamSupport.stream(graph.spliterator(), isParallel)
+ // root is an object (filter + conversion)
+ .filter(JsonNode::isObject)
+ .map(JsonNode::deepCopy)
+ // "5. if the entity has an @id URI that matches root return it"
+ .filter(node -> node.path(PROP_ID).asText().equals(rootId))
+ .findFirst();
+ }
+
+ private Set extractHasPartIds(ObjectNode root) {
+ JsonNode hasPartNode = root.path(PROP_HAS_PART);
+ boolean isParallel = hasPartNode.isArray() && hasPartNode.size() > PARALLELIZATION_THRESHOLD;
+ Set hasPartIds = StreamSupport.stream(hasPartNode.spliterator(), isParallel)
+ .map(hasPart -> hasPart.path(PROP_ID).asText())
+ .filter(text -> !text.isBlank())
+ .collect(Collectors.toSet());
+ if (hasPartIds.isEmpty() && hasPartNode.path(PROP_ID).isTextual()) {
+ hasPartIds.add(hasPartNode.path(PROP_ID).asText());
+ }
+ return hasPartIds;
+ }
+
+ private void setCrateDescriptor(RoCrate crate, JsonNode descriptor) {
+ ContextualEntity descriptorEntity = new ContextualEntity.ContextualEntityBuilder()
+ .setAll(descriptor.deepCopy())
+ .build();
+ crate.setJsonDescriptor(descriptorEntity);
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderReader.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderReader.java
index faaede49..f0436e27 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderReader.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderReader.java
@@ -1,37 +1,12 @@
package edu.kit.datamanager.ro_crate.reader;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-
/**
* A class for reading a crate from a folder.
*
* @author Nikola Tzotchev on 9.2.2022 г.
* @version 1
+ *
+ * @deprecated Use {@link FolderStrategy} instead.
*/
-public class FolderReader implements ReaderStrategy {
-
- @Override
- public ObjectNode readMetadataJson(String location) {
- Path metadata = new File(location).toPath().resolve("ro-crate-metadata.json");
- ObjectMapper objectMapper = MyObjectMapper.getMapper();
- ObjectNode objectNode = objectMapper.createObjectNode();
- try {
- objectNode = objectMapper.readTree(metadata.toFile()).deepCopy();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return objectNode;
- }
-
- @Override
- public File readContent(String location) {
- return new File(location);
- }
-}
+@Deprecated(since = "2.1.0", forRemoval = true)
+public class FolderReader extends FolderStrategy {}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderStrategy.java
new file mode 100644
index 00000000..f6e235ed
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/FolderStrategy.java
@@ -0,0 +1,36 @@
+package edu.kit.datamanager.ro_crate.reader;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+
+/**
+ * A class for reading a crate from a folder.
+ *
+ * @author Nikola Tzotchev on 9.2.2022 г.
+ * @version 1
+ */
+public class FolderStrategy implements GenericReaderStrategy {
+
+ @Override
+ public ObjectNode readMetadataJson(String location) {
+ Path metadata = new File(location).toPath().resolve("ro-crate-metadata.json");
+ ObjectMapper objectMapper = MyObjectMapper.getMapper();
+ ObjectNode objectNode = objectMapper.createObjectNode();
+ try {
+ objectNode = objectMapper.readTree(metadata.toFile()).deepCopy();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return objectNode;
+ }
+
+ @Override
+ public File readContent(String location) {
+ return new File(location);
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/GenericReaderStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/GenericReaderStrategy.java
new file mode 100644
index 00000000..c3539b17
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/GenericReaderStrategy.java
@@ -0,0 +1,28 @@
+package edu.kit.datamanager.ro_crate.reader;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.File;
+
+/**
+ * Generic interface for the strategy of the reader class.
+ * This allows for flexible input types when implementing different reading strategies.
+ *
+ * @param the type of the location parameter
+ */
+public interface GenericReaderStrategy {
+ /**
+ * Read the metadata.json file from the given location.
+ *
+ * @param location the location to read from
+ * @return the parsed metadata.json as ObjectNode
+ */
+ ObjectNode readMetadataJson(T location);
+
+ /**
+ * Read the content from the given location.
+ *
+ * @param location the location to read from
+ * @return the content as a File
+ */
+ File readContent(T location);
+}
\ No newline at end of file
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/ReaderStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/ReaderStrategy.java
index 506dfd4f..2029fe9c 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/reader/ReaderStrategy.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/ReaderStrategy.java
@@ -1,18 +1,14 @@
package edu.kit.datamanager.ro_crate.reader;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import java.io.File;
-
/**
- * Interface for the strategy fo the reader class.
+ * Interface for the strategy for the reader class.
* This should be implemented if additional strategies are to be build.
* (e.g., reading from a gzip)
*
* @author Nikola Tzotchev on 9.2.2022 г.
* @version 1
+ *
+ * @deprecated Use {@link GenericReaderStrategy} instead.
*/
-public interface ReaderStrategy {
- ObjectNode readMetadataJson(String location);
-
- File readContent(String location);
-}
+@Deprecated(since = "2.1.0", forRemoval = true)
+public interface ReaderStrategy extends GenericReaderStrategy {}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/Readers.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/Readers.java
new file mode 100644
index 00000000..49e09cb1
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/Readers.java
@@ -0,0 +1,77 @@
+package edu.kit.datamanager.ro_crate.reader;
+
+import java.io.InputStream;
+import java.nio.file.Path;
+
+/**
+ * Factory for creating common RO-Crate reader instances.
+ * Provides convenient static methods to instantiate readers with pre-configured strategies.
+ */
+public class Readers {
+
+ /**
+ * Private constructor to prevent instantiation of this utility class.
+ */
+ private Readers() {}
+
+ /**
+ * Creates a reader that reads from ZIP files using input streams.
+ *
+ * @return A reader configured for ZIP files
+ *
+ * @see ZipStreamStrategy#ZipStreamStrategy()
+ */
+ public static CrateReader newZipStreamReader() {
+ return new CrateReader<>(new ZipStreamStrategy());
+ }
+
+ /**
+ * Creates a reader that reads from ZIP files using input streams,
+ * extracting to a custom temporary location.
+ *
+ * @param extractPath Path where ZIP contents should be extracted
+ * @param useUuidSubfolder Whether to create a UUID subfolder under extractPath
+ * @return A reader configured for ZIP files with custom extraction
+ *
+ * @see ZipStreamStrategy#ZipStreamStrategy(Path, boolean)
+ */
+ public static CrateReader newZipStreamReader(Path extractPath, boolean useUuidSubfolder) {
+ return new CrateReader<>(new ZipStreamStrategy(extractPath, useUuidSubfolder));
+ }
+
+ /**
+ * Creates a reader that reads from a folder using a string path.
+ *
+ * @return A reader configured for folders
+ *
+ * @see FolderStrategy
+ */
+ public static CrateReader newFolderReader() {
+ return new CrateReader<>(new FolderStrategy());
+ }
+
+ /**
+ * Creates a reader that reads from a ZIP file using a string path.
+ *
+ * @return A reader configured for ZIP files
+ *
+ * @see ZipStrategy#ZipStrategy()
+ */
+ public static CrateReader newZipPathReader() {
+ return new CrateReader<>(new ZipStrategy());
+ }
+
+ /**
+ * Creates a reader that reads from a ZIP file using a string path,
+ * extracting to a custom temporary location.
+ *
+ * @param extractPath Path where ZIP contents should be extracted
+ * @param useUuidSubfolder Whether to create a UUID subfolder under extractPath
+ * @return A reader configured for ZIP files with custom extraction
+ *
+ * @see ZipStrategy#ZipStrategy(Path, boolean)
+ */
+ public static CrateReader newZipPathReader(Path extractPath, boolean useUuidSubfolder) {
+ return new CrateReader<>(new ZipStrategy(extractPath, useUuidSubfolder));
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/RoCrateReader.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/RoCrateReader.java
index 087888a5..d11177c1 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/reader/RoCrateReader.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/RoCrateReader.java
@@ -1,29 +1,5 @@
package edu.kit.datamanager.ro_crate.reader;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.context.CrateMetadataContext;
-import edu.kit.datamanager.ro_crate.context.RoCrateMetadataContext;
-import edu.kit.datamanager.ro_crate.entities.contextual.ContextualEntity;
-import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
-import edu.kit.datamanager.ro_crate.entities.data.RootDataEntity;
-import edu.kit.datamanager.ro_crate.special.IdentifierUtils;
-import edu.kit.datamanager.ro_crate.special.JsonUtilFunctions;
-
-import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
-import edu.kit.datamanager.ro_crate.validation.Validator;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* This class allows reading crates from the outside into the library in order
* to inspect or modify it.
@@ -33,333 +9,12 @@
*
* The reader consideres "hasPart" and "isPartOf" properties and considers all
* entities (in-)directly connected to the root entity ("./") as DataEntities.
+ *
+ * @deprecated Use {@link CrateReader} instead.
*/
-public class RoCrateReader {
-
- private static Logger logger = LoggerFactory.getLogger(RoCrateReader.class);
-
- /**
- * This is a private inner class that shall not be exposed. **Do not make it
- * public or protected.** It serves only the purpose of unsafe operations
- * while reading a crate and may be specific to this implementation.
- */
- private static class RoCrateUnsafe extends RoCrate {
-
- public void addDataEntityWithoutRootHasPart(DataEntity entity) {
- this.metadataContext.checkEntity(entity);
- this.roCratePayload.addDataEntity(entity);
- }
- }
-
- /**
- * If the number of JSON entities in the crate is larger than this number,
- * parallelization will be used.
- */
- private static final int PARALLELIZATION_THRESHOLD = 100;
-
- private static final String FILE_PREVIEW_FILES = "ro-crate-preview_files";
- private static final String FILE_PREVIEW_HTML = "ro-crate-preview.html";
- private static final String FILE_METADATA_JSON = "ro-crate-metadata.json";
-
- protected static final String SPECIFICATION_PREFIX = "https://w3id.org/ro/crate/";
-
- protected static final String PROP_ABOUT = "about";
- protected static final String PROP_CONTEXT = "@context";
- protected static final String PROP_CONFORMS_TO = "conformsTo";
- protected static final String PROP_GRAPH = "@graph";
- protected static final String PROP_HAS_PART = "hasPart";
- protected static final String PROP_ID = "@id";
-
- private final ReaderStrategy reader;
-
- public RoCrateReader(ReaderStrategy reader) {
- this.reader = reader;
- }
-
- /**
- * This function will read the location (using one of the specified
- * strategies) and then build the relation between the entities.
- *
- * @param source the input stream to read from
- *
- * @return the read RO-crate
- */
- public RoCrate readCrate(InputStream source) {
- RoCrate result = null;
- if (reader instanceof StreamReaderStrategy streamReaderStrategy) {
- ObjectNode metadata = streamReaderStrategy.readMetadataJson(source);
- File content = streamReaderStrategy.readContent(source);
- HashSet usedFiles = new HashSet<>();
- usedFiles.add(content.toPath().resolve(FILE_METADATA_JSON).toFile().getPath());
- usedFiles.add(content.toPath().resolve(FILE_PREVIEW_HTML).toFile().getPath());
- usedFiles.add(content.toPath().resolve(FILE_PREVIEW_FILES).toFile().getPath());
- result = rebuildCrate(metadata, content, usedFiles);
- } else {
- logger.error("Provided writer does not implement StreamReaderStrategy. Please use 'readCrate(String location)'.");
- }
- return result;
- }
-
- /**
- * This function will read the location (using one of the specified
- * strategies) and then build the relation between the entities.
- *
- * @param location the location of the ro-crate to be read
- * @return the read RO-crate
- */
- public RoCrate readCrate(String location) {
- // get the ro-crate-medata.json
- ObjectNode metadataJson = reader.readMetadataJson(location);
- // get the content of the crate
- File files = reader.readContent(location);
-
- // this set will contain the files that are associated with entities
- HashSet usedFiles = new HashSet<>();
- usedFiles.add(files.toPath().resolve(FILE_METADATA_JSON).toFile().getPath());
- usedFiles.add(files.toPath().resolve(FILE_PREVIEW_HTML).toFile().getPath());
- usedFiles.add(files.toPath().resolve(FILE_PREVIEW_FILES).toFile().getPath());
- return rebuildCrate(metadataJson, files, usedFiles);
- }
-
- private RoCrate rebuildCrate(ObjectNode metadataJson, File files, HashSet usedFiles) {
- if (metadataJson == null) {
- logger.error("Metadata JSON is null, cannot rebuild crate");
- return null;
- }
- if (files == null) {
- logger.error("Content files directory is null, cannot rebuild crate");
- return null;
- }
- JsonNode context = metadataJson.get(PROP_CONTEXT);
-
- CrateMetadataContext crateContext = new RoCrateMetadataContext(context);
- RoCrateUnsafe crate = new RoCrateUnsafe();
- crate.setMetadataContext(crateContext);
- JsonNode graph = metadataJson.get(PROP_GRAPH);
-
- if (graph.isArray()) {
- moveRootEntitiesFromGraphToCrate(crate, (ArrayNode) graph);
- RootDataEntity root = crate.getRootDataEntity();
- if (root != null) {
- Set dataEntityIds = getDataEntityIds(root, graph);
- for (JsonNode entityJson : graph) {
- String eId = unpackId(entityJson);
- if (dataEntityIds.contains(eId)) {
- // data entity
- DataEntity.DataEntityBuilder dataEntity = new DataEntity.DataEntityBuilder()
- .setAll(entityJson.deepCopy());
-
- // Handle data entities with corresponding file
- checkFolderHasFile(entityJson.get(PROP_ID).asText(), files).ifPresent(file -> {
- usedFiles.add(file.getPath());
- dataEntity.setLocationWithExceptions(file.toPath())
- .setId(file.getName());
- });
-
- crate.addDataEntityWithoutRootHasPart(dataEntity.build());
- } else {
- // contextual entity
- crate.addContextualEntity(
- new ContextualEntity.ContextualEntityBuilder()
- .setAll(entityJson.deepCopy())
- .build());
- }
- }
- }
- }
-
- Collection untrackedFiles = Arrays.stream(
- Optional.ofNullable(files.listFiles()).orElse(new File[0]))
- .filter(f -> !usedFiles.contains(f.getPath()))
- .collect(Collectors.toSet());
-
- crate.setUntrackedFiles(untrackedFiles);
- Validator defaultValidation = new Validator(new JsonSchemaValidation());
- defaultValidation.validate(crate);
- return crate;
- }
-
- /**
- * Extracts graph connections from top to bottom.
- *
- * Example: (connections.get(parent) -> children)
- *
- * @param graph the ArrayNode with all Entities.
- * @return the graph connections.
- */
- protected Map> makeEntityGraph(JsonNode graph) {
- Map> connections = new HashMap<>();
-
- Map idToNodes = new HashMap<>();
- StreamSupport.stream(graph.spliterator(), false)
- .forEach(jsonNode -> idToNodes.put(unpackId(jsonNode), jsonNode));
-
- for (JsonNode entityNode : graph) {
- String currentId = unpackId(entityNode);
- StreamSupport.stream(entityNode.path("hasPart").spliterator(), false)
- .map(this::unpackId)
- .map(s -> idToNodes.getOrDefault(s, null))
- .filter(Objects::nonNull)
- .forEach(child -> connections.computeIfAbsent(currentId, key -> new HashSet<>())
- .add(unpackId(child)));
- StreamSupport.stream(entityNode.path("isPartOf").spliterator(), false)
- .map(this::unpackId)
- .map(s -> idToNodes.getOrDefault(s, null))
- .filter(Objects::nonNull)
- .forEach(parent -> connections.computeIfAbsent(unpackId(parent), key -> new HashSet<>())
- .add(currentId));
- }
- return connections;
- }
-
- protected Set getDataEntityIds(RootDataEntity root, JsonNode graph) {
- if (root == null) {
- return Set.of();
- }
- Map> network = makeEntityGraph(graph);
- Set directDataEntities = new HashSet<>(root.hasPart);
-
- Stack processingQueue = new Stack<>();
- processingQueue.addAll(directDataEntities);
- Set result = new HashSet<>();
-
- while (!processingQueue.empty()) {
- String currentId = processingQueue.pop();
- result.add(currentId);
- network.getOrDefault(currentId, new HashSet<>()).stream()
- .filter(subId -> !result.contains(subId)) // avoid loops!
- .forEach(subId -> {
- result.add(subId);
- processingQueue.add(subId);
- });
- }
- return result;
- }
-
- protected String unpackId(JsonNode node) {
- if (node.isTextual()) {
- return node.asText();
- } else /*if (node.isObject())*/ {
- return node.path(PROP_ID).asText();
- }
- }
-
- protected Optional checkFolderHasFile(String filepathOrId, File folder) {
- if (IdentifierUtils.isUrl(filepathOrId)) {
- return Optional.empty();
- }
- return IdentifierUtils.decode(filepathOrId)
- .map(decoded -> folder.toPath().resolve(decoded).toFile())
- .filter(File::exists);
- }
-
- /**
- * Moves the descriptor and the root entity from the graph to the crate.
- *
- * Extracts the root data entity and the Metadata File Descriptor from the
- * graph and inserts them into the crate object. It also deletes it from the
- * graph. We will need the root dataset to distinguish between data entities
- * and contextual entities.
- *
- * @param crate the crate, which will receive the entities, if available in
- * the graph.
- * @param graph the graph of the Metadata JSON file, where the entities are
- * extracted and removed from.
- */
- protected void moveRootEntitiesFromGraphToCrate(RoCrate crate, ArrayNode graph) {
- Optional maybeDescriptor = getMetadataDescriptor(graph);
-
- maybeDescriptor.ifPresent(descriptor -> {
- setCrateDescriptor(crate, descriptor);
- JsonUtilFunctions.removeJsonNodeFromArrayNode(graph, descriptor);
-
- Optional maybeRoot = extractRoot(graph, descriptor);
-
- maybeRoot.ifPresent(root -> {
- Set hasPartIds = extractHasPartIds(root);
-
- crate.setRootDataEntity(
- new RootDataEntity.RootDataEntityBuilder()
- .setAll(root.deepCopy())
- .setHasPart(hasPartIds)
- .build());
-
- JsonUtilFunctions.removeJsonNodeFromArrayNode(graph, root);
- });
- });
- }
-
- /**
- * Find the metadata descriptor.
- *
- * Currently prefers algorithm of version 1.1 over the one of 1.2-DRAFT.
- *
- * @param graph the graph to search the descriptor in.
- * @return the metadata descriptor of the crate.
- */
- protected Optional getMetadataDescriptor(ArrayNode graph) {
- boolean isParallel = graph.size() > PARALLELIZATION_THRESHOLD;
- // use the algorithm described here:
- // https://www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity
- Optional maybeDescriptor = StreamSupport.stream(graph.spliterator(), isParallel)
- // "2. if the conformsTo property is a URI that starts with
- // https://w3id.org/ro/crate/"
- .filter(node -> node.path(PROP_CONFORMS_TO).path(PROP_ID).asText().startsWith(SPECIFICATION_PREFIX))
- // "3. from this entity’s about object keep the @id URI as variable root"
- .filter(node -> node.path(PROP_ABOUT).path(PROP_ID).isTextual())
- // There should be only one descriptor. If multiple exist, we take the first
- // one.
- .findFirst();
- return maybeDescriptor.or(()
- -> // from https://www.researchobject.org/ro-crate/1.2-DRAFT/root-data-entity.html#finding-the-root-data-entity
- StreamSupport.stream(graph.spliterator(), isParallel)
- .filter(node -> node.path(PROP_ID).asText().equals(FILE_METADATA_JSON))
- .findFirst()
- );
- }
-
- /**
- * Extracts the root entity from the graph, using the information from the
- * descriptor.
- *
- * Basically implements step 5 of the algorithm described here:
- *
- * https://www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity
- *
- *
- * @param graph the graph from the metadata JSON-LD file
- * @param descriptor the RO-Crate descriptor
- * @return the root entity, if found
- */
- private Optional extractRoot(ArrayNode graph, JsonNode descriptor) {
- String rootId = descriptor.get(PROP_ABOUT).get(PROP_ID).asText();
- boolean isParallel = graph.size() > PARALLELIZATION_THRESHOLD;
- return StreamSupport.stream(graph.spliterator(), isParallel)
- // root is an object (filter + conversion)
- .filter(JsonNode::isObject)
- .map(JsonNode::deepCopy)
- // "5. if the entity has an @id URI that matches root return it"
- .filter(node -> node.path(PROP_ID).asText().equals(rootId))
- .findFirst();
- }
-
- private Set extractHasPartIds(ObjectNode root) {
- JsonNode hasPartNode = root.path(PROP_HAS_PART);
- boolean isParallel = hasPartNode.isArray() && hasPartNode.size() > PARALLELIZATION_THRESHOLD;
- Set hasPartIds = StreamSupport.stream(hasPartNode.spliterator(), isParallel)
- .map(hasPart -> hasPart.path(PROP_ID).asText())
- .filter(text -> !text.isBlank())
- .collect(Collectors.toSet());
- if (hasPartIds.isEmpty() && hasPartNode.path(PROP_ID).isTextual()) {
- hasPartIds.add(hasPartNode.path(PROP_ID).asText());
- }
- return hasPartIds;
- }
-
- private void setCrateDescriptor(RoCrate crate, JsonNode descriptor) {
- ContextualEntity descriptorEntity = new ContextualEntity.ContextualEntityBuilder()
- .setAll(descriptor.deepCopy())
- .build();
- crate.setJsonDescriptor(descriptorEntity);
+@Deprecated(since = "2.1.0", forRemoval = true)
+public class RoCrateReader extends CrateReader {
+ public RoCrateReader(GenericReaderStrategy reader) {
+ super(reader);
}
}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/StreamReaderStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/StreamReaderStrategy.java
deleted file mode 100644
index 3dfcc243..00000000
--- a/src/main/java/edu/kit/datamanager/ro_crate/reader/StreamReaderStrategy.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package edu.kit.datamanager.ro_crate.reader;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import edu.kit.datamanager.ro_crate.writer.StreamWriterStrategy;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import org.slf4j.LoggerFactory;
-
-/**
- * Interface for reading RO-Crate metadata and content from input streams.
- *
- * @author jejkal
- */
-public interface StreamReaderStrategy extends ReaderStrategy {
-
- org.slf4j.Logger logger = LoggerFactory.getLogger(StreamReaderStrategy.class);
-
- /**
- * Default override of readMetadataJson interface from ReaderStrategy. The
- * override assumes, that location is a file, which is used as input stream.
- * If this assumption is not true, this call will fail.
- *
- * @param location The source, which is supposed to be a file.
- *
- * @return the RO-Crate metadata as ObjectNode
- */
- @Override
- default ObjectNode readMetadataJson(String location) {
- ObjectNode result = null;
- try {
- result = readMetadataJson(new FileInputStream(new File(location)));
- } catch (FileNotFoundException ex) {
- logger.error("Failed read crate from source " + location, ex);
- }
- return result;
- }
-
- /**
- * Default override of readContent interface from ReaderStrategy. The
- * override assumes, that location is a file, which is used as input stream.
- * If this assumption is not true, this call will fail.
- *
- * @param location The source, which is supposed to be a file.
- *
- * @return the RO-Crate content as file, i.e., a folder
- */
- @Override
- default File readContent(String location) {
- File result = null;
- try {
- result = readContent(new FileInputStream(new File(location)));
- } catch (FileNotFoundException ex) {
- logger.error("Failed read crate from source " + location, ex);
- }
- return result;
- }
-
- ObjectNode readMetadataJson(InputStream source);
-
- File readContent(InputStream source);
-
-}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipReader.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipReader.java
index da60798b..ad9bbb01 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipReader.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipReader.java
@@ -1,18 +1,7 @@
package edu.kit.datamanager.ro_crate.reader;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.UUID;
import java.nio.file.Path;
-import net.lingala.zip4j.ZipFile;
-import org.apache.commons.io.FileUtils;
-
/**
* A ReaderStrategy implementation which reads from ZipFiles.
*
@@ -28,17 +17,18 @@
* folder after extraction. Use RoCrateWriter to export it so some
* persistent location and possibly read it from there, if required. Or use
* the ZipWriter to write it back to its source.
+ *
+ * @deprecated Use {@link ZipStrategy} instead.
*/
-public class ZipReader implements ReaderStrategy {
-
- protected final String ID = UUID.randomUUID().toString();
- protected Path temporaryFolder = Path.of(String.format("./.tmp/ro-crate-java/zipReader/%s/", ID));
- protected boolean isExtracted = false;
+@Deprecated(since = "2.1.0", forRemoval = true)
+public class ZipReader extends ZipStrategy {
/**
* Crates a ZipReader with the default configuration as described in the class documentation.
*/
- public ZipReader() {}
+ public ZipReader() {
+ super();
+ }
/**
* Creates a ZipReader which will extract the contents temporary
@@ -52,77 +42,6 @@ public ZipReader() {}
* will have UUIDs as their names.
*/
public ZipReader(Path folderPath, boolean shallAddUuidSubfolder) {
- if (shallAddUuidSubfolder) {
- this.temporaryFolder = folderPath.resolve(ID);
- } else {
- this.temporaryFolder = folderPath;
- }
- }
-
- /**
- * @return the identifier which may be used as the name for a subfolder in the temporary directory.
- */
- public String getID() {
- return ID;
- }
-
- /**
- * @return the folder (considered temporary) where the zipped crate will be or has been extracted to.
- */
- public Path getTemporaryFolder() {
- return temporaryFolder;
- }
-
- /**
- * @return whether the crate has already been extracted into the temporary folder.
- */
- public boolean isExtracted() {
- return isExtracted;
- }
-
- private void readCrate(String location) {
- try {
- File folder = temporaryFolder.toFile();
- // ensure the directory is clean
- if (folder.isDirectory()) {
- FileUtils.cleanDirectory(folder);
- } else if (folder.isFile()) {
- FileUtils.delete(folder);
- }
- // extract
- try (ZipFile zf = new ZipFile(location)) {
- zf.extractAll(temporaryFolder.toAbsolutePath().toString());
- this.isExtracted = true;
- }
- // register deletion on exit
- FileUtils.forceDeleteOnExit(folder);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public ObjectNode readMetadataJson(String location) {
- if (!isExtracted) {
- this.readCrate(location);
- }
-
- ObjectMapper objectMapper = MyObjectMapper.getMapper();
- File jsonMetadata = temporaryFolder.resolve("ro-crate-metadata.json").toFile();
-
- try {
- return objectMapper.readTree(jsonMetadata).deepCopy();
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- @Override
- public File readContent(String location) {
- if (!isExtracted) {
- this.readCrate(location);
- }
- return temporaryFolder.toFile();
+ super(folderPath, shallAddUuidSubfolder);
}
}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStrategy.java
new file mode 100644
index 00000000..0d6381a6
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStrategy.java
@@ -0,0 +1,126 @@
+package edu.kit.datamanager.ro_crate.reader;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
+import net.lingala.zip4j.ZipFile;
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.UUID;
+
+/**
+ * A ReaderStrategy implementation which reads from ZipFiles.
+ *
+ * May be used as a dependency for CrateReader. It will unzip
+ * the ZipFile in a path relative to the directory this application runs in.
+ * By default, it will be `./.tmp/ro-crate-java/zipReader/$UUID/`.
+ *
+ * NOTE: The resulting crate may refer to these temporary files. Therefore,
+ * these files are only being deleted before the JVM exits. If you need to free
+ * space because your application is long-running or creates a lot of
+ * crates, you may use the getters to retrieve information which will help
+ * you to clean up manually. Keep in mind that crates may refer to this
+ * folder after extraction. Use RoCrateWriter to export it so some
+ * persistent location and possibly read it from there, if required. Or use
+ * the ZipWriter to write it back to its source.
+ */
+public class ZipStrategy implements GenericReaderStrategy {
+
+ protected final String ID = UUID.randomUUID().toString();
+ protected Path temporaryFolder = Path.of(String.format("./.tmp/ro-crate-java/zipReader/%s/", ID));
+ protected boolean isExtracted = false;
+
+ /**
+ * Crates a ZipReader with the default configuration as described in the class documentation.
+ */
+ public ZipStrategy() {}
+
+ /**
+ * Creates a ZipReader which will extract the contents temporary
+ * to the given location instead of the default location.
+ *
+ * @param folderPath the custom directory to extract
+ * content to for temporary access.
+ * @param shallAddUuidSubfolder if true, the reader will extract
+ * into subdirectories of the given
+ * directory. These subdirectories
+ * will have UUIDs as their names.
+ */
+ public ZipStrategy(Path folderPath, boolean shallAddUuidSubfolder) {
+ if (shallAddUuidSubfolder) {
+ this.temporaryFolder = folderPath.resolve(ID);
+ } else {
+ this.temporaryFolder = folderPath;
+ }
+ }
+
+ /**
+ * @return the identifier which may be used as the name for a subfolder in the temporary directory.
+ */
+ public String getID() {
+ return ID;
+ }
+
+ /**
+ * @return the folder (considered temporary) where the zipped crate will be or has been extracted to.
+ */
+ public Path getTemporaryFolder() {
+ return temporaryFolder;
+ }
+
+ /**
+ * @return whether the crate has already been extracted into the temporary folder.
+ */
+ public boolean isExtracted() {
+ return isExtracted;
+ }
+
+ private void readCrate(String location) {
+ try {
+ File folder = temporaryFolder.toFile();
+ // ensure the directory is clean
+ if (folder.isDirectory()) {
+ FileUtils.cleanDirectory(folder);
+ } else if (folder.isFile()) {
+ FileUtils.delete(folder);
+ }
+ // extract
+ try (ZipFile zf = new ZipFile(location)) {
+ zf.extractAll(temporaryFolder.toAbsolutePath().toString());
+ this.isExtracted = true;
+ }
+ // register deletion on exit
+ FileUtils.forceDeleteOnExit(folder);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public ObjectNode readMetadataJson(String location) {
+ if (!isExtracted) {
+ this.readCrate(location);
+ }
+
+ ObjectMapper objectMapper = MyObjectMapper.getMapper();
+ File jsonMetadata = temporaryFolder.resolve("ro-crate-metadata.json").toFile();
+
+ try {
+ return objectMapper.readTree(jsonMetadata).deepCopy();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public File readContent(String location) {
+ if (!isExtracted) {
+ this.readCrate(location);
+ }
+ return temporaryFolder.toFile();
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReader.java b/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamStrategy.java
similarity index 93%
rename from src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReader.java
rename to src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamStrategy.java
index b71212bb..cb4f53af 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReader.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamStrategy.java
@@ -13,6 +13,8 @@
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A ZIP file reader implementation of the StreamReaderStrategy interface.
@@ -21,8 +23,9 @@
*
* @author jejkal
*/
-public class ZipStreamReader implements StreamReaderStrategy {
+public class ZipStreamStrategy implements GenericReaderStrategy {
+ private static final Logger logger = LoggerFactory.getLogger(ZipStreamStrategy.class);
protected final String ID = UUID.randomUUID().toString();
protected Path temporaryFolder = Path.of(String.format("./.tmp/ro-crate-java/zipStreamReader/%s/", ID));
protected boolean isExtracted = false;
@@ -31,7 +34,7 @@ public class ZipStreamReader implements StreamReaderStrategy {
* Crates a ZipStreamReader with the default configuration as described in
* the class documentation.
*/
- public ZipStreamReader() {
+ public ZipStreamStrategy() {
}
/**
@@ -44,7 +47,7 @@ public ZipStreamReader() {
* subdirectories of the given directory. These subdirectories will have
* UUIDs as their names.
*/
- public ZipStreamReader(Path folderPath, boolean shallAddUuidSubfolder) {
+ public ZipStreamStrategy(Path folderPath, boolean shallAddUuidSubfolder) {
if (shallAddUuidSubfolder) {
this.temporaryFolder = folderPath.resolve(ID);
} else {
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/CrateWriter.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/CrateWriter.java
new file mode 100644
index 00000000..440be0c4
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/CrateWriter.java
@@ -0,0 +1,30 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import edu.kit.datamanager.ro_crate.Crate;
+import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
+import edu.kit.datamanager.ro_crate.validation.Validator;
+
+/**
+ * The class used for writing (exporting) crates. The class uses a strategy
+ * pattern for writing crates as different formats. (zip, folders, etc.)
+ */
+public class CrateWriter {
+
+ private final GenericWriterStrategy strategy;
+
+ public CrateWriter(GenericWriterStrategy strategy) {
+ this.strategy = strategy;
+ }
+
+ /**
+ * This method saves the crate to a destination provided.
+ *
+ * @param crate the crate to write.
+ * @param destination the location where the crate should be written.
+ */
+ public void save(Crate crate, DESTINATION destination) {
+ Validator defaultValidation = new Validator(new JsonSchemaValidation());
+ defaultValidation.validate(crate);
+ this.strategy.save(crate, destination);
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderStrategy.java
new file mode 100644
index 00000000..b2585637
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderStrategy.java
@@ -0,0 +1,63 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import edu.kit.datamanager.ro_crate.Crate;
+import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
+import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * A class for writing a crate to a folder.
+ *
+ * @author Nikola Tzotchev on 9.2.2022 г.
+ * @version 1
+ */
+public class FolderStrategy implements GenericWriterStrategy {
+
+ private static final Logger logger = LoggerFactory.getLogger(FolderStrategy.class);
+
+ @Override
+ public void save(Crate crate, String destination) {
+ File file = new File(destination);
+ try {
+ FileUtils.forceMkdir(file);
+ ObjectMapper objectMapper = MyObjectMapper.getMapper();
+ JsonNode node = objectMapper.readTree(crate.getJsonMetadata());
+ String str = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
+ InputStream inputStream = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+
+ File json = new File(destination, "ro-crate-metadata.json");
+ FileUtils.copyInputStreamToFile(inputStream, json);
+ inputStream.close();
+ // save also the preview files to the crate destination
+ if (crate.getPreview() != null) {
+ crate.getPreview().saveAllToFolder(file);
+ }
+ for (var e : crate.getUntrackedFiles()) {
+ if (e.isDirectory()) {
+ FileUtils.copyDirectoryToDirectory(e, file);
+ } else {
+ FileUtils.copyFileToDirectory(e, file);
+ }
+ }
+ } catch (IOException e) {
+ logger.error("Error creating destination directory!", e);
+ }
+ for (DataEntity dataEntity : crate.getAllDataEntities()) {
+ try {
+ dataEntity.savetoFile(file);
+ } catch (IOException e) {
+ logger.error("Cannot save " + dataEntity.getId() + " to destination folder!", e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderWriter.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderWriter.java
index ab704181..5730104e 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderWriter.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/FolderWriter.java
@@ -1,64 +1,11 @@
package edu.kit.datamanager.ro_crate.writer;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import edu.kit.datamanager.ro_crate.Crate;
-import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
-import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* A class for writing a crate to a folder.
*
* @author Nikola Tzotchev on 9.2.2022 г.
- * @version 1
+ *
+ * @deprecated Use {@link FolderStrategy} instead.
*/
-public class FolderWriter implements WriterStrategy {
-
- private static Logger logger = LoggerFactory.getLogger(FolderWriter.class);
-
- @Override
- public void save(Crate crate, String destination) {
- File file = new File(destination);
- try {
- FileUtils.forceMkdir(file);
- ObjectMapper objectMapper = MyObjectMapper.getMapper();
- JsonNode node = objectMapper.readTree(crate.getJsonMetadata());
- String str = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
- InputStream inputStream = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
-
- File json = new File(destination, "ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(inputStream, json);
- inputStream.close();
- // save also the preview files to the crate destination
- if (crate.getPreview() != null) {
- crate.getPreview().saveAllToFolder(file);
- }
- for (var e : crate.getUntrackedFiles()) {
- if (e.isDirectory()) {
- FileUtils.copyDirectoryToDirectory(e, file);
- } else {
- FileUtils.copyFileToDirectory(e, file);
- }
- }
- } catch (IOException e) {
- logger.error("Error creating destination directory!", e);
- }
- for (DataEntity dataEntity : crate.getAllDataEntities()) {
- try {
- dataEntity.savetoFile(file);
- } catch (IOException e) {
- logger.error("Cannot save " + dataEntity.getId() + " to destination folder!", e);
- }
- }
- }
-}
+@Deprecated(since = "2.1.0", forRemoval = true)
+public class FolderWriter extends FolderStrategy {}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/GenericWriterStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/GenericWriterStrategy.java
new file mode 100644
index 00000000..6306b576
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/GenericWriterStrategy.java
@@ -0,0 +1,19 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import edu.kit.datamanager.ro_crate.Crate;
+
+/**
+ * Generic interface for the strategy of the writer class.
+ * This allows for flexible output types when implementing different writing strategies.
+ *
+ * @param the type of the destination parameter
+ */
+public interface GenericWriterStrategy {
+ /**
+ * Saves the given crate to the specified destination.
+ *
+ * @param crate The crate to save
+ * @param destination The destination where the crate should be saved
+ */
+ void save(Crate crate, DESTINATION destination);
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriter.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriter.java
index 112b4d3a..9337d400 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriter.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriter.java
@@ -1,51 +1,15 @@
package edu.kit.datamanager.ro_crate.writer;
-import edu.kit.datamanager.ro_crate.Crate;
-import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
-import edu.kit.datamanager.ro_crate.validation.Validator;
-import java.io.OutputStream;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* The class used for writing (exporting) crates. The class uses a strategy
* pattern for writing crates as different formats. (zip, folders, etc.)
+ *
+ * @deprecated Use {@link CrateWriter} instead.
*/
-public class RoCrateWriter {
-
- private static Logger logger = LoggerFactory.getLogger(RoCrateWriter.class);
-
- private final WriterStrategy writer;
-
- public RoCrateWriter(WriterStrategy writer) {
- this.writer = writer;
- }
-
- /**
- * This method saves the crate to a destination provided.
- *
- * @param crate the crate to write.
- * @param destination the location where the crate should be written.
- */
- public void save(Crate crate, String destination) {
- Validator defaultValidation = new Validator(new JsonSchemaValidation());
- defaultValidation.validate(crate);
- this.writer.save(crate, destination);
- }
+@Deprecated(since = "2.1.0", forRemoval = true)
+public class RoCrateWriter extends CrateWriter {
- /**
- * This method saves the crate to a destination provided.
- *
- * @param crate the crate to write.
- * @param destination the location where the crate should be written.
- */
- public void save(Crate crate, OutputStream destination) {
- Validator defaultValidation = new Validator(new JsonSchemaValidation());
- defaultValidation.validate(crate);
- if (writer instanceof StreamWriterStrategy streamWriterStrategy) {
- streamWriterStrategy.save(crate, destination);
- } else {
- logger.error("Provided writer does not implement StreamWriterStrategy. Please use 'save(Crate crate, String destination)'.");
- }
+ public RoCrateWriter(GenericWriterStrategy writer) {
+ super(writer);
}
}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/StreamWriterStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/StreamWriterStrategy.java
deleted file mode 100644
index 04deb659..00000000
--- a/src/main/java/edu/kit/datamanager/ro_crate/writer/StreamWriterStrategy.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package edu.kit.datamanager.ro_crate.writer;
-
-import edu.kit.datamanager.ro_crate.Crate;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import org.slf4j.LoggerFactory;
-
-/**
- * Strategy for writing of crates to streams.
- *
- * @author jejkal
- */
-public interface StreamWriterStrategy extends WriterStrategy {
-
- static org.slf4j.Logger logger = LoggerFactory.getLogger(StreamWriterStrategy.class);
-
- /**
- * Default override of save interface from WriterStrategy. The override
- * assumes, that destination is a file, which is used as output stream. If
- * this assumption is not true, this call will fail.
- *
- * @param crate The crate to write.
- * @param destination The destination, which is supposed to be a file.
- */
- default void save(Crate crate, String destination) {
- try {
- save(crate, new FileOutputStream(new File(destination)));
- } catch (FileNotFoundException ex) {
- logger.error("Failed save crate to destination " + destination, ex);
- }
- }
-
- void save(Crate crate, OutputStream destination);
-}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/WriterStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/WriterStrategy.java
index 06be6585..12459673 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/writer/WriterStrategy.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/WriterStrategy.java
@@ -1,13 +1,12 @@
package edu.kit.datamanager.ro_crate.writer;
-import edu.kit.datamanager.ro_crate.Crate;
-
/**
* Strategy for writing of crates.
*
* @author Nikola Tzotchev on 9.2.2022 г.
* @version 1
+ *
+ * @deprecated Use {@link GenericWriterStrategy} instead.
*/
-public interface WriterStrategy {
- void save(Crate crate, String destination);
-}
+@Deprecated(since = "2.1.0", forRemoval = true)
+public interface WriterStrategy extends GenericWriterStrategy {}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/Writers.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/Writers.java
new file mode 100644
index 00000000..5b691ece
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/Writers.java
@@ -0,0 +1,42 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import java.io.OutputStream;
+
+/**
+ * Utility class for creating instances of different crate writers.
+ * This class is not meant to be instantiated.
+ */
+public class Writers {
+
+ /**
+ * Prevents instantiation of this utility class.
+ */
+ private Writers() {}
+
+ /**
+ * Creates a new instance of a crate writer that writes to a folder.
+ *
+ * @return a new instance of {@link CrateWriter} for writing to a folder
+ */
+ public static CrateWriter newFolderWriter() {
+ return new CrateWriter<>(new FolderStrategy());
+ }
+
+ /**
+ * Creates a new instance of a crate writer that writes to a zip stream.
+ *
+ * @return a new instance of {@link CrateWriter} for writing to a zip stream
+ */
+ public static CrateWriter newZipStreamWriter() {
+ return new CrateWriter<>(new ZipStreamStrategy());
+ }
+
+ /**
+ * Creates a new instance of a crate writer that writes to a zip file.
+ *
+ * @return a new instance of {@link CrateWriter} for writing to a zip file
+ */
+ public static CrateWriter newZipPathWriter() {
+ return new CrateWriter<>(new ZipStrategy());
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStrategy.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStrategy.java
new file mode 100644
index 00000000..c944aad3
--- /dev/null
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStrategy.java
@@ -0,0 +1,68 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import edu.kit.datamanager.ro_crate.Crate;
+import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
+import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
+import net.lingala.zip4j.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.ZipParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Implementation of the writing strategy to provide a way of writing crates to
+ * a zip archive.
+ */
+public class ZipStrategy implements GenericWriterStrategy {
+
+ private static final Logger logger = LoggerFactory.getLogger(ZipStrategy.class);
+
+ @Override
+ public void save(Crate crate, String destination) {
+ try (ZipFile zipFile = new ZipFile(destination)) {
+ saveMetadataJson(crate, zipFile);
+ saveDataEntities(crate, zipFile);
+ } catch (IOException e) {
+ // can not close ZipFile (threw Exception)
+ logger.error("Failed to write ro-crate to destination " + destination + ".", e);
+ }
+ }
+
+ private void saveDataEntities(Crate crate, ZipFile zipFile) {
+ for (DataEntity dataEntity : crate.getAllDataEntities()) {
+ try {
+ dataEntity.saveToZip(zipFile);
+ } catch (ZipException e) {
+ logger.error("Could not save " + dataEntity.getId() + " to zip file!", e);
+ }
+ }
+ }
+
+ private void saveMetadataJson(Crate crate, ZipFile zipFile) {
+ try {
+ // write the metadata.json file
+ ZipParameters zipParameters = new ZipParameters();
+ zipParameters.setFileNameInZip("ro-crate-metadata.json");
+ ObjectMapper objectMapper = MyObjectMapper.getMapper();
+ // we create an JsonNode only to have the file written pretty
+ JsonNode node = objectMapper.readTree(crate.getJsonMetadata());
+ String str = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
+ InputStream inputStream = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+ // write the ro-crate-metadata
+ zipFile.addStream(inputStream, zipParameters);
+ inputStream.close();
+ if (crate.getPreview() != null) {
+ crate.getPreview().saveAllToZip(zipFile);
+ }
+ } catch (IOException e) {
+ logger.error("Exception writing ro-crate-metadata.json file to zip.", e);
+ }
+ }
+}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStreamWriter.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStreamStrategy.java
similarity index 91%
rename from src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStreamWriter.java
rename to src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStreamStrategy.java
index 3145c3a1..818c064c 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStreamWriter.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipStreamStrategy.java
@@ -21,9 +21,9 @@
* Implementation of the writing strategy to provide a way of writing crates to
* a zip archive.
*/
-public class ZipStreamWriter implements StreamWriterStrategy {
+public class ZipStreamStrategy implements GenericWriterStrategy {
- private static Logger logger = LoggerFactory.getLogger(ZipStreamWriter.class);
+ private static final Logger logger = LoggerFactory.getLogger(ZipStreamStrategy.class);
@Override
public void save(Crate crate, OutputStream destination) {
@@ -41,7 +41,7 @@ private void saveDataEntities(Crate crate, ZipOutputStream zipStream) {
try {
dataEntity.saveToStream(zipStream);
} catch (IOException e) {
- logger.error("Could not save " + dataEntity.getId() + " to zip stream!", e);
+ logger.error("Could not save {} to zip stream!", dataEntity.getId(), e);
}
}
}
diff --git a/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipWriter.java b/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipWriter.java
index dff25fd0..f5261003 100644
--- a/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipWriter.java
+++ b/src/main/java/edu/kit/datamanager/ro_crate/writer/ZipWriter.java
@@ -1,69 +1,10 @@
package edu.kit.datamanager.ro_crate.writer;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import edu.kit.datamanager.ro_crate.Crate;
-import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
-import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import net.lingala.zip4j.ZipFile;
-import net.lingala.zip4j.exception.ZipException;
-import net.lingala.zip4j.model.ZipParameters;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* Implementation of the writing strategy to provide a way of writing crates to
* a zip archive.
+ *
+ * @deprecated Use {@link ZipStrategy} instead.
*/
-public class ZipWriter implements WriterStrategy {
-
- private static Logger logger = LoggerFactory.getLogger(ZipWriter.class);
-
- @Override
- public void save(Crate crate, String destination) {
- try (ZipFile zipFile = new ZipFile(destination)) {
- saveMetadataJson(crate, zipFile);
- saveDataEntities(crate, zipFile);
- } catch (IOException e) {
- // can not close ZipFile (threw Exception)
- logger.error("Failed to write ro-crate to destination " + destination + ".", e);
- }
- }
-
- private void saveDataEntities(Crate crate, ZipFile zipFile) {
- for (DataEntity dataEntity : crate.getAllDataEntities()) {
- try {
- dataEntity.saveToZip(zipFile);
- } catch (ZipException e) {
- logger.error("Could not save " + dataEntity.getId() + " to zip file!", e);
- }
- }
- }
-
- private void saveMetadataJson(Crate crate, ZipFile zipFile) {
- try {
- // write the metadata.json file
- ZipParameters zipParameters = new ZipParameters();
- zipParameters.setFileNameInZip("ro-crate-metadata.json");
- ObjectMapper objectMapper = MyObjectMapper.getMapper();
- // we create an JsonNode only to have the file written pretty
- JsonNode node = objectMapper.readTree(crate.getJsonMetadata());
- String str = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
- InputStream inputStream = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
- // write the ro-crate-metadata
- zipFile.addStream(inputStream, zipParameters);
- inputStream.close();
- if (crate.getPreview() != null) {
- crate.getPreview().saveAllToZip(zipFile);
- }
- } catch (IOException e) {
- logger.error("Exception writing ro-crate-metadata.json file to zip.", e);
- }
- }
-}
+@Deprecated(since = "2.1.0", forRemoval = true)
+public class ZipWriter extends ZipStrategy {}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/HelpFunctions.java b/src/test/java/edu/kit/datamanager/ro_crate/HelpFunctions.java
index 48c2d858..8f32213f 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/HelpFunctions.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/HelpFunctions.java
@@ -91,27 +91,27 @@ public static void compareCrateJsonToFileInResources(Crate crate1, String jsonFi
public static boolean compareTwoDir(File dir1, File dir2) throws IOException {
// compare the content of the two directories
- Map result_map = FileUtils.listFiles(dir1, null, true)
+ Map compareWithMe = FileUtils.listFiles(dir1, null, true)
.stream()
.collect(Collectors.toMap(java.io.File::getName, Function.identity()));
- Map input_map = FileUtils.listFiles(dir2, null, true)
+ Map testMe = FileUtils.listFiles(dir2, null, true)
.stream()
- .collect(Collectors.toMap(java.io.File::getName, Function.identity()));;
+ .collect(Collectors.toMap(java.io.File::getName, Function.identity()));
- if (result_map.size() != input_map.size()) {
+ if (compareWithMe.size() != testMe.size()) {
return false;
}
- for (String s : input_map.keySet()) {
+ for (String filename : testMe.keySet()) {
// we do that because the ro-crate-metadata.json can be differently formatted,
// or the order of the entities may be different
// the same holds for the html file
- if (s.equals("ro-crate-preview.html") || s.equals("ro-crate-metadata.json")) {
- if (!result_map.containsKey(s)) {
+ if (filename.equals("ro-crate-preview.html") || filename.equals("ro-crate-metadata.json")) {
+ if (!compareWithMe.containsKey(filename)) {
return false;
}
- } else if (!FileUtils.contentEqualsIgnoreEOL(input_map.get(s), result_map.get(s), null)) {
+ } else if (!FileUtils.contentEqualsIgnoreEOL(testMe.get(filename), compareWithMe.get(filename), null)) {
return false;
}
}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/crate/BuilderSpec12Test.java b/src/test/java/edu/kit/datamanager/ro_crate/crate/BuilderSpec12Test.java
index ee0d72e0..eddd93ee 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/crate/BuilderSpec12Test.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/crate/BuilderSpec12Test.java
@@ -8,6 +8,7 @@
import java.net.URISyntaxException;
import java.util.Collection;
+import edu.kit.datamanager.ro_crate.reader.Readers;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.JsonNode;
@@ -15,8 +16,6 @@
import edu.kit.datamanager.ro_crate.Crate;
import edu.kit.datamanager.ro_crate.RoCrate;
import edu.kit.datamanager.ro_crate.entities.contextual.ContextualEntity;
-import edu.kit.datamanager.ro_crate.reader.FolderReader;
-import edu.kit.datamanager.ro_crate.reader.RoCrateReader;
import edu.kit.datamanager.ro_crate.special.CrateVersion;
import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
import edu.kit.datamanager.ro_crate.validation.Validator;
@@ -40,7 +39,7 @@ void testAppendConformsTo() throws URISyntaxException {
@Test
void testModificationOfDraftCrate() throws URISyntaxException {
String path = this.getClass().getResource("/crates/spec-1.2-DRAFT/minimal-with-conformsTo-Array").getPath();
- RoCrate crate = new RoCrateReader(new FolderReader()).readCrate(path);
+ RoCrate crate = Readers.newFolderReader().readCrate(path);
Collection existingProfiles = crate.getProfiles();
profile1 = new URI("https://example.com/myprofile/1.0");
profile2 = new URI("https://example.com/myprofile/2.0");
@@ -69,8 +68,8 @@ void testModificationOfDraftCrate() throws URISyntaxException {
Collection newProfileState = modifiedCrate.getProfiles();
assertEquals(existingProfiles.size() + 2, newProfileState.size());
// new profiles are present
- newProfileState.contains(profile1.toString());
- newProfileState.contains(profile2.toString());
+ assertTrue(newProfileState.contains(profile1.toString()));
+ assertTrue(newProfileState.contains(profile2.toString()));
// old profiles are present
assertEquals(
0,
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/crate/ReadAndWriteTest.java b/src/test/java/edu/kit/datamanager/ro_crate/crate/ReadAndWriteTest.java
index 2f2e308c..4a39cca3 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/crate/ReadAndWriteTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/crate/ReadAndWriteTest.java
@@ -3,10 +3,9 @@
import edu.kit.datamanager.ro_crate.Crate;
import edu.kit.datamanager.ro_crate.HelpFunctions;
import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.preview.CustomPreview;
import edu.kit.datamanager.ro_crate.preview.StaticPreview;
-import edu.kit.datamanager.ro_crate.reader.FolderReader;
-import edu.kit.datamanager.ro_crate.reader.RoCrateReader;
+import edu.kit.datamanager.ro_crate.reader.CrateReader;
+import edu.kit.datamanager.ro_crate.reader.Readers;
import edu.kit.datamanager.ro_crate.writer.FolderWriter;
import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
@@ -40,7 +39,7 @@ void testReadingAndWriting(@TempDir Path path) throws IOException {
RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
writer.save(crate, writeDir.toAbsolutePath().toString());
- RoCrateReader reader = new RoCrateReader(new FolderReader());
+ CrateReader reader = Readers.newFolderReader();
Crate newCrate = reader.readCrate(writeDir.toAbsolutePath().toString());
// the preview files as well as the metadata file should not be included here
@@ -51,7 +50,7 @@ void testReadingAndWriting(@TempDir Path path) throws IOException {
@Test
void testReadCrateWithHasPartHierarchy() {
- RoCrateReader reader = new RoCrateReader(new FolderReader());
+ CrateReader reader = Readers.newFolderReader();
RoCrate crate = reader.readCrate(ReadAndWriteTest.class.getResource("/crates/hasPartHierarchy").getPath());
assertEquals(1, crate.getAllContextualEntities().size());
assertEquals(6, crate.getAllDataEntities().size());
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java b/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java
index 8f008510..b1f6e21b 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java
@@ -1,7 +1,6 @@
package edu.kit.datamanager.ro_crate.crate;
-import edu.kit.datamanager.ro_crate.reader.FolderReader;
-import edu.kit.datamanager.ro_crate.reader.RoCrateReader;
+import edu.kit.datamanager.ro_crate.reader.Readers;
import edu.kit.datamanager.ro_crate.HelpFunctions;
import edu.kit.datamanager.ro_crate.RoCrate;
@@ -21,7 +20,7 @@ public class TestRemoveAddContext {
void setup() {
String crateManifestPath = "/crates/extendedContextExample/";
crateManifestPath = Objects.requireNonNull(TestRemoveAddContext.class.getResource(crateManifestPath)).getPath();
- this.crateWithComplexContext = new RoCrateReader(new FolderReader()).readCrate(crateManifestPath);
+ this.crateWithComplexContext = Readers.newFolderReader().readCrate(crateManifestPath);
}
@Test
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/RealTest.java b/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/RealTest.java
index bdc132b8..ae206b7c 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/RealTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/RealTest.java
@@ -12,8 +12,8 @@
import edu.kit.datamanager.ro_crate.entities.data.DataSetEntity;
import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
import edu.kit.datamanager.ro_crate.externalproviders.personprovider.OrcidProvider;
-import edu.kit.datamanager.ro_crate.reader.FolderReader;
-import edu.kit.datamanager.ro_crate.reader.RoCrateReader;
+import edu.kit.datamanager.ro_crate.reader.CrateReader;
+import edu.kit.datamanager.ro_crate.reader.Readers;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
@@ -30,7 +30,7 @@ class RealTest {
@Test
void testWithIDRCProject(@TempDir Path temp) throws IOException {
- RoCrateReader reader = new RoCrateReader(new FolderReader());
+ CrateReader reader = Readers.newFolderReader();
final String locationMetadataFile = "/crates/other/idrc_project/ro-crate-metadata.json";
Crate crate = reader.readCrate(RealTest.class.getResource("/crates/other/idrc_project").getPath());
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/WorkflowHubTest.java b/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/WorkflowHubTest.java
index 245a0118..1d45bd09 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/WorkflowHubTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/crate/realexamples/WorkflowHubTest.java
@@ -2,8 +2,8 @@
import edu.kit.datamanager.ro_crate.Crate;
import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.reader.RoCrateReader;
-import edu.kit.datamanager.ro_crate.reader.ZipReader;
+import edu.kit.datamanager.ro_crate.reader.CrateReader;
+import edu.kit.datamanager.ro_crate.reader.Readers;
import edu.kit.datamanager.ro_crate.writer.FolderWriter;
import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
@@ -18,7 +18,7 @@ public class WorkflowHubTest {
@Test
void testImportZip(@TempDir Path temp) throws IOException {
- RoCrateReader reader = new RoCrateReader(new ZipReader());
+ CrateReader reader = Readers.newZipPathReader();
Crate crate = reader.readCrate(WorkflowHubTest.class.getResource("/crates/workflowhub/workflow-109-5.crate.zip").getPath());
HelpFunctions.compareCrateJsonToFileInResources(crate, "/crates/workflowhub/workflow1/ro-crate-metadata.json");
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/reader/CrateReaderTest.java b/src/test/java/edu/kit/datamanager/ro_crate/reader/CrateReaderTest.java
new file mode 100644
index 00000000..bcf8948d
--- /dev/null
+++ b/src/test/java/edu/kit/datamanager/ro_crate/reader/CrateReaderTest.java
@@ -0,0 +1,230 @@
+package edu.kit.datamanager.ro_crate.reader;
+
+import edu.kit.datamanager.ro_crate.Crate;
+import edu.kit.datamanager.ro_crate.HelpFunctions;
+import edu.kit.datamanager.ro_crate.RoCrate;
+import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
+import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
+import edu.kit.datamanager.ro_crate.writer.CrateWriter;
+import edu.kit.datamanager.ro_crate.writer.Writers;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Abstract class for testing crate readers.
+ *
+ * @param the source type of the reader strategy. Even though each implementation knows this T,
+ * we can't use it everywhere we'd like to as the code here needs to be generic.
+ * We therefore rely on methods to take a path (as we always assume local testing).
+ * Streams, for example, will therefore need to stream from/to a file.
+ * This parameter is only required to satisfy the generic reader strategy.
+ * @param the type of the reader strategy
+ */
+abstract class CrateReaderTest> {
+
+ protected static RoCrate.RoCrateBuilder newBaseCrate() {
+ return new RoCrate.RoCrateBuilder(
+ "minimal",
+ "minimal RO_crate",
+ "2024",
+ "https://creativecommons.org/licenses/by-nc-sa/3.0/au/"
+ );
+ }
+
+ protected static FileEntity newDataEntity(Path filePath) throws IllegalArgumentException {
+ return new FileEntity.FileEntityBuilder()
+ .setLocationWithExceptions(filePath)
+ .setId(filePath.toFile().getName())
+ .addProperty("name", "Survey responses")
+ .addProperty("contentSize", "26452")
+ .addProperty("encodingFormat", "text/csv")
+ .build();
+ }
+
+ /**
+ * Saves the crate with the writer fitting to the reader of {@link #readCrate(Path)}.
+ *
+ * @param crate the crate to save
+ * @param target the target path to the save location
+ * @throws IOException if an error occurs while saving the crate
+ */
+ abstract protected void saveCrate(Crate crate, Path target) throws IOException;
+
+ /**
+ * Reads the crate with the reader fitting to the writer of {@link #saveCrate(Crate, Path)}.
+ * @param source the source path to the crate
+ * @return the read crate
+ * @throws IOException if an error occurs while reading the crate
+ */
+ abstract protected Crate readCrate(Path source) throws IOException;
+
+ /**
+ * Creates a new reader strategy with a non-default temporary directory (if supported, default otherwise).
+ *
+ * @param tmpDirectory the temporary directory to use
+ * @param useUuidSubfolder whether to create a UUID subfolder under the temporary directory
+ * @return a new reader strategy
+ */
+ abstract protected READER_STRATEGY newReaderStrategyWithTmp(Path tmpDirectory, boolean useUuidSubfolder);
+
+ /**
+ * Reads the crate using the provided reader strategy.
+ *
+ * @param strategy the reader strategy to use
+ * @param source the source path to the crate
+ * @return the read crate
+ * @throws IOException if an error occurs while reading the crate
+ */
+ abstract protected Crate readCrate(READER_STRATEGY strategy, Path source) throws IOException;
+
+ @Test
+ void testReadingBasicCrate(@TempDir Path temp) throws IOException {
+
+ RoCrate roCrate = newBaseCrate().build();
+ Path zipPath = temp.resolve("result.zip");
+ this.saveCrate(roCrate, zipPath);
+ Crate importedCrate = this.readCrate(zipPath);
+ HelpFunctions.compareTwoCrateJson(roCrate, importedCrate);
+ }
+
+ @Test
+ void testWithFile(@TempDir Path temp) throws IOException {
+ Path csvPath = temp.resolve("survey-responses-2019.csv");
+ FileUtils.touch(csvPath.toFile());
+ FileUtils.writeStringToFile(csvPath.toFile(), "Dummy content", Charset.defaultCharset());
+ RoCrate rawCrate = newBaseCrate()
+ .addDataEntity(newDataEntity(csvPath))
+ .build();
+
+ assertEquals(1, rawCrate.getAllDataEntities().size());
+
+ Path zipPath = temp.resolve("result.zip");
+ this.saveCrate(rawCrate, zipPath);
+ Crate importedCrate = this.readCrate(zipPath);
+
+ HelpFunctions.compareTwoCrateJson(rawCrate, importedCrate);
+ }
+
+ @Test
+ void testWithFileUrlEncoded(@TempDir Path temp) throws IOException {
+ // This URL will be encoded because of whitespaces
+ Path csvPath = temp.resolve("survey responses 2019.csv");
+ FileUtils.touch(csvPath.toFile());
+ FileUtils.writeStringToFile(csvPath.toFile(), "Dummy content", Charset.defaultCharset());
+ RoCrate rawCrate = newBaseCrate()
+ .addDataEntity(newDataEntity(csvPath))
+ .build();
+
+ DataEntity rawEntity = rawCrate.getAllDataEntities().iterator().next();
+ assertTrue(rawEntity.getId().contains("survey"));
+ assertFalse(rawEntity.getId().contains(" "));
+ assertEquals(1, rawCrate.getAllDataEntities().size());
+
+ Path zipPath = temp.resolve("result.zip");
+ this.saveCrate(rawCrate, zipPath);
+ Crate importedCrate = this.readCrate(zipPath);
+
+ DataEntity importedEntity = importedCrate.getAllDataEntities().iterator().next();
+ assertTrue(importedEntity.getId().contains("survey"));
+ assertFalse(importedEntity.getId().contains(" "));
+ assertEquals(1, importedCrate.getAllDataEntities().size());
+
+ HelpFunctions.compareTwoCrateJson(rawCrate, importedCrate);
+ }
+
+ @Test
+ void TestWithFileWithLocation(@TempDir Path temp) throws IOException {
+ Path csvPath = temp.resolve("survey-responses-2019.csv");
+ FileUtils.writeStringToFile(csvPath.toFile(), "Dummy content", Charset.defaultCharset());
+ RoCrate rawCrate = newBaseCrate()
+ .addDataEntity(newDataEntity(csvPath))
+ .setPreview(null)//disable preview to allow to compare folders before and after
+ .build();
+
+ // write to zip file and read via zip stream
+ Path zipPath = temp.resolve("result.zip");
+ this.saveCrate(rawCrate, zipPath);
+ Crate importedCrate = this.readCrate(zipPath);
+
+ // write raw crate and imported crate to folders and compare the results
+ Path rawCrateTarget = temp.resolve("rawCrateSaved");
+ Path importedCrateTarget = temp.resolve("importedCrateSaved");
+ {
+ // write raw crate and imported crate to two different directories
+ CrateWriter writer = Writers.newFolderWriter();
+ writer.save(rawCrate, rawCrateTarget.toString());
+ writer.save(importedCrate, importedCrateTarget.toString());
+ }
+
+ assertTrue(HelpFunctions.compareTwoDir(rawCrateTarget.toFile(), importedCrateTarget.toFile()));
+ HelpFunctions.compareTwoCrateJson(rawCrate, importedCrate);
+ }
+
+ @Test
+ void TestWithFileWithLocationAddEntity(@TempDir Path temp) throws IOException {
+ Path csvPath = temp.resolve("file.csv");
+ FileUtils.writeStringToFile(csvPath.toFile(), "fakecsv.1", Charset.defaultCharset());
+ RoCrate rawCrate = newBaseCrate()
+ .addDataEntity(newDataEntity(csvPath))
+ .build();
+
+ // write to zip file and import via zip stream
+ Path zipPath = temp.resolve("result.zip");
+ this.saveCrate(rawCrate, zipPath);
+ Crate importedCrate = this.readCrate(zipPath);
+ {
+ // modify the imported crate
+ Path newFile = temp.resolve("new_file");
+ FileUtils.writeStringToFile(newFile.toFile(), "Some file content", Charset.defaultCharset());
+ importedCrate.addDataEntity(new FileEntity.FileEntityBuilder()
+ .setEncodingFormat("setnew")
+ .setLocationWithExceptions(newFile)
+ .setId("new_file")
+ .build());
+ }
+ // write raw crate to a folder
+ Path rawCrateTarget = temp.resolve("rawCrateSaved");
+ Path importedCrateTarget = temp.resolve("importedCrateSaved");
+ {
+ // write raw crate and imported crate to two different directories
+ CrateWriter writer = Writers.newFolderWriter();
+ writer.save(rawCrate, rawCrateTarget.toString());
+ writer.save(importedCrate, importedCrateTarget.toFile().toString());
+ }
+ // assert the folders are different
+ assertFalse(HelpFunctions.compareTwoDir(rawCrateTarget.toFile(), importedCrateTarget.toFile()));
+ HelpFunctions.compareTwoMetadataJsonNotEqual(rawCrate, importedCrate);
+ // assert the importedCrateTarget folder contains newFile
+ assertTrue(importedCrateTarget.resolve("new_file").toFile().isFile());
+ }
+
+ @Test
+ void testReadingBasicCrateWithCustomPath(@TempDir Path temp) throws IOException {
+ RoCrate rawCrate = newBaseCrate().build();
+
+ // Write to zip file
+ Path zipPath = temp.resolve("result.zip");
+ this.saveCrate(rawCrate, zipPath);
+
+ // read again and compare using custom path for temporary extraction folder
+ // (if available, otherwise uses default)
+ Path differentFolder = temp.resolve("differentFolder");
+ READER_STRATEGY strategy = this.newReaderStrategyWithTmp(differentFolder, true);
+ Crate importedCrate = this.readCrate(strategy, zipPath);
+ HelpFunctions.compareTwoCrateJson(rawCrate, importedCrate);
+
+ {
+ // try it again without the UUID subfolder and test if the directory is being cleaned up (for coverage).
+ READER_STRATEGY strategyWithoutSubfolder = this.newReaderStrategyWithTmp(differentFolder, false);
+ Crate crate = this.readCrate(strategyWithoutSubfolder, zipPath);
+ HelpFunctions.compareTwoCrateJson(rawCrate, crate);
+ }
+ }
+}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/reader/FolderReaderTest.java b/src/test/java/edu/kit/datamanager/ro_crate/reader/FolderReaderTest.java
index d4eb91fb..21850edd 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/reader/FolderReaderTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/reader/FolderReaderTest.java
@@ -4,19 +4,12 @@
import edu.kit.datamanager.ro_crate.HelpFunctions;
import edu.kit.datamanager.ro_crate.RoCrate;
import edu.kit.datamanager.ro_crate.entities.contextual.PersonEntity;
-import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
-
-import edu.kit.datamanager.ro_crate.writer.FolderWriter;
-import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
+import edu.kit.datamanager.ro_crate.writer.Writers;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.charset.Charset;
import java.nio.file.Path;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
import static org.junit.jupiter.api.Assertions.*;
@@ -24,56 +17,61 @@
* @author Nikola Tzotchev on 9.2.2022 г.
* @version 1
*/
-class FolderReaderTest {
+class FolderReaderTest extends CrateReaderTest {
- private Path writeMetadataToFile(Path temp, RoCrate c1) throws IOException {
- // Write metadata to file
- Path f = temp.resolve("ro-crate-metadata.json");
- FileUtils.touch(f.toFile());
- FileUtils.writeStringToFile(f.toFile(), c1.getJsonMetadata(), Charset.defaultCharset());
- return f;
+ @Override
+ protected void saveCrate(Crate crate, Path target) {
+ Writers.newFolderWriter().save(crate, target.toAbsolutePath().toString());
+ assertTrue(target.toFile().isDirectory());
}
- @Test
- void testReadingBasicCrate(@TempDir Path temp) throws IOException {
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .build();
- Path f = writeMetadataToFile(temp, roCrate);
- // Read from written file
- RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
- RoCrate res = roCrateFolderReader.readCrate(temp.toFile().toString());
- // Write metadata again
- Path r = temp.resolve("output.txt");
- FileUtils.touch(r.toFile());
- FileUtils.writeStringToFile(r.toFile(), res.getJsonMetadata(), Charset.defaultCharset());
- // See if it is the same
- assertTrue(FileUtils.contentEquals(f.toFile(), r.toFile()));
+ @Override
+ protected Crate readCrate(Path source) throws IOException {
+ return Readers.newFolderReader().readCrate(source.toAbsolutePath().toString());
}
+ @Override
+ protected FolderStrategy newReaderStrategyWithTmp(Path tmpDirectory, boolean useUuidSubfolder) {
+ // This strategy does not support a non-default temporary directory
+ // and will always use the default one.
+ // It also has no state we could make assertions on.
+ return new FolderStrategy();
+ }
+
+ @Override
+ protected Crate readCrate(FolderStrategy strategy, Path source) throws IOException {
+ return new CrateReader<>(strategy)
+ .readCrate(source.toAbsolutePath().toString());
+ }
+
+ /**
+ * The folder reader is state-less, so we should be able to read multiple crates
+ * with the same instance.
+ */
@Test
void testMultipleReads(@TempDir Path temp1, @TempDir Path temp2) throws IOException {
String id = "https://orcid.org/0000-0001-6121-5409";
PersonEntity person = new PersonEntity.PersonEntityBuilder()
- .setId(id)
- .setContactPoint("mailto:tim.luckett@uts.edu.au")
- .setAffiliation("https://ror.org/03f0f6041")
- .setFamilyName("Luckett")
- .setGivenName("Tim")
- .addProperty("name", "Tim Luckett")
- .build();
+ .setId(id)
+ .setContactPoint("mailto:tim.luckett@uts.edu.au")
+ .setAffiliation("https://ror.org/03f0f6041")
+ .setFamilyName("Luckett")
+ .setGivenName("Tim")
+ .addProperty("name", "Tim Luckett")
+ .build();
RoCrate c1 = new RoCrate.RoCrateBuilder("mini", "test", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/").build();
RoCrate c2 = new RoCrate.RoCrateBuilder("other", "with file", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addContextualEntity(person)
- .build();
- writeMetadataToFile(temp1, c1);
- writeMetadataToFile(temp2, c2);
+ .addContextualEntity(person)
+ .build();
+ this.saveCrate(c1, temp1);
+ this.saveCrate(c2, temp2);
// some first checks...
assertEquals(0, c1.getAllContextualEntities().size());
assertEquals(1, c2.getAllContextualEntities().size());
// read both with the same reader
- RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
- RoCrate c1_read = roCrateFolderReader.readCrate(temp1.toFile().toString());
- RoCrate c2_read = roCrateFolderReader.readCrate(temp2.toFile().toString());
+ CrateReader reader = Readers.newFolderReader();
+ RoCrate c1_read = reader.readCrate(temp1.toFile().toString());
+ RoCrate c2_read = reader.readCrate(temp2.toFile().toString());
// check that the reference is not the same
assertNotEquals(c1, c1_read);
assertNotEquals(c2, c2_read);
@@ -82,149 +80,4 @@ void testMultipleReads(@TempDir Path temp1, @TempDir Path temp2) throws IOExcept
assertEquals(1, c2_read.getAllContextualEntities().size());
HelpFunctions.compareTwoMetadataJsonNotEqual(c1_read, c2_read);
}
-
- @Test
- void testWithFile(@TempDir Path temp) throws IOException {
- Path cvs = temp.resolve("survey-responses-2019.csv");
- FileUtils.touch(cvs.toFile());
- FileUtils.writeStringToFile(cvs.toFile(), "fkdjaflkjfla", Charset.defaultCharset());
-
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .setLocationWithExceptions(cvs)
- .setId(cvs.toFile().getName())
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .build()
- )
- .build();
-
- assertEquals(1, roCrate.getAllDataEntities().size());
-
- writeMetadataToFile(temp, roCrate);
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
- RoCrate res = roCrateFolderReader.readCrate(temp.toFile().toString());
- HelpFunctions.compareTwoCrateJson(roCrate, res);
- }
-
- @Test
- void testWithFileUrlEncoded(@TempDir Path temp) throws IOException {
-
- // get the std output redirected, so we can see if there is something written
- PrintStream standardOut = System.out;
- ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
- System.setOut(new PrintStream(outputStreamCaptor));
-
- Path csv = temp.resolve("survey responses 2019.csv"); // This URL will be encoded because of whitespaces
- FileUtils.touch(csv.toFile());
- FileUtils.writeStringToFile(csv.toFile(), "fkdjaflkjfla", Charset.defaultCharset());
-
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .setLocationWithExceptions(csv)
- .setId(csv.toFile().getName())
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .build()
- )
- .build();
-
- writeMetadataToFile(temp, roCrate);
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
- Crate res = roCrateFolderReader.readCrate(temp.toFile().toString());
- HelpFunctions.compareTwoCrateJson(roCrate, res);
-
- // Make sure we did not print any errors
- assertEquals("", outputStreamCaptor.toString().trim());
- System.setOut(standardOut);
- }
-
- @Test
- void TestWithFileWithLocation(@TempDir Path temp) throws IOException {
- Path file = temp.resolve("survey-responses-2019.csv");
- FileUtils.writeStringToFile(file.toFile(), "fakecsv.1", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .setLocationWithExceptions(file)
- .setId("survey-responses-2019.csv")
- .build()
- )
- .setPreview(null)//disable preview to allow to compare folders before and after
- .build();
- Path locationSource = temp.resolve("src");
- FileUtils.forceMkdir(locationSource.toFile());
- RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
-
- writer.save(roCrate, locationSource.toFile().toString());
-
- writeMetadataToFile(temp, roCrate);
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
-
- Crate res = roCrateFolderReader.readCrate(locationSource.toFile().toString());
-
- Path destinationDir = temp.resolve("result");
- FileUtils.forceMkdir(destinationDir.toFile());
-
- writer.save(res, destinationDir.toFile().toString());
-
- // that copies the directory locally to see its content
- //FileUtils.copyDirectory(locationSource.toFile(), new File("test"));
- assertTrue(HelpFunctions.compareTwoDir(locationSource.toFile(), destinationDir.toFile()));
- HelpFunctions.compareTwoCrateJson(roCrate, res);
- }
-
- @Test
- void TestWithFileWithLocationAddEntity(@TempDir Path temp) throws IOException {
- Path file = temp.resolve("file.csv");
- FileUtils.writeStringToFile(file.toFile(), "fakecsv.1", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .setLocationWithExceptions(file)
- .setId("survey-responses-2019.csv")
- .build()
- )
- .build();
- Path locationSource = temp.resolve("src");
- FileUtils.forceMkdir(locationSource.toFile());
- RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
-
- writer.save(roCrate, locationSource.toFile().toString());
-
- writeMetadataToFile(temp, roCrate);
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
-
- Path newFile = temp.resolve("new_file");
- FileUtils.writeStringToFile(newFile.toFile(), "fkladjsl;fjasd;lfjda;lkf", Charset.defaultCharset());
-
- Crate res = roCrateFolderReader.readCrate(locationSource.toFile().toString());
- res.addDataEntity(new FileEntity.FileEntityBuilder()
- .setEncodingFormat("setnew")
- .setLocationWithExceptions(newFile)
- .setId("new_file")
- .build());
-
- Path destinationDir = temp.resolve("result");
- FileUtils.forceMkdir(destinationDir.toFile());
-
- writer.save(res, destinationDir.toFile().toString());
-
- assertFalse(HelpFunctions.compareTwoDir(locationSource.toFile(), destinationDir.toFile()));
- HelpFunctions.compareTwoMetadataJsonNotEqual(roCrate, res);
- }
}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/reader/RoCrateReaderSpec12Test.java b/src/test/java/edu/kit/datamanager/ro_crate/reader/RoCrateReaderSpec12Test.java
index 24bdcb54..7b1df7df 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/reader/RoCrateReaderSpec12Test.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/reader/RoCrateReaderSpec12Test.java
@@ -29,7 +29,7 @@ public class RoCrateReaderSpec12Test {
@Test
void testReadingCrateWithConformsToArray() {
String path = this.getClass().getResource("/crates/spec-1.2-DRAFT/minimal-with-conformsTo-Array").getPath();
- Crate crate = new RoCrateReader(new FolderReader()).readCrate(path);
+ Crate crate = Readers.newFolderReader().readCrate(path);
JsonNode conformsTo = crate.getJsonDescriptor().getProperty("conformsTo");
assertTrue(conformsTo.isArray());
assertEquals(2, conformsTo.size());
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipReaderTest.java b/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipReaderTest.java
index 33006ff2..3611c834 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipReaderTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipReaderTest.java
@@ -1,200 +1,44 @@
package edu.kit.datamanager.ro_crate.reader;
import edu.kit.datamanager.ro_crate.Crate;
-import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
-import edu.kit.datamanager.ro_crate.writer.FolderWriter;
-import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
-import edu.kit.datamanager.ro_crate.writer.ZipWriter;
+import edu.kit.datamanager.ro_crate.writer.Writers;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.io.File;
import java.io.IOException;
-import java.nio.charset.Charset;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.*;
-class ZipReaderTest {
-
- @Test
- void testReadingBasicCrate(@TempDir Path temp) throws IOException {
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- File zipFile = zipPath.toFile();
- assertTrue(zipFile.isFile());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipReader());
- Crate res = roCrateFolderReader.readCrate(zipFile.getAbsolutePath());
- HelpFunctions.compareTwoCrateJson(roCrate, res);
- }
-
- @Test
- void testWithFile(@TempDir Path temp) throws IOException {
- Path cvs = temp.resolve("survey-responses-2019.csv");
- FileUtils.touch(cvs.toFile());
- FileUtils.writeStringToFile(cvs.toFile(), "fkdjaflkjfla", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .setLocationWithExceptions(cvs)
- .setId(cvs.toFile().getName())
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .build()
- )
- .build();
-
- assertEquals(1, roCrate.getAllDataEntities().size());
+class ZipReaderTest extends CrateReaderTest {
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toFile().getAbsolutePath());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipReader());
- Crate res = roCrateFolderReader.readCrate(zipPath.toFile().getAbsolutePath());
-
- HelpFunctions.compareTwoCrateJson(roCrate, res);
+ @Override
+ protected void saveCrate(Crate crate, Path target) {
+ Writers.newZipPathWriter().save(crate, target.toAbsolutePath().toString());
+ assertTrue(target.toFile().isFile());
}
- @Test
- void TestWithFileWithLocation(@TempDir Path temp) throws IOException {
- Path file = temp.resolve("survey-responses-2019.csv");
- FileUtils.writeStringToFile(file.toFile(), "fakecsv.1", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .setLocationWithExceptions(file)
- .setId("survey-responses-2019.csv")
- .build()
- )
- .setPreview(null)//disable preview to allow to compare folders before and after
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipReader());
- Crate res = roCrateFolderReader.readCrate(zipPath.toString());
-
- Path locationSource = temp.resolve("expected");
- RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
- writer.save(roCrate, locationSource.toString());
-
- Path destinationDir = temp.resolve("result");
- FileUtils.forceMkdir(destinationDir.toFile());
- writer.save(res, destinationDir.toString());
-
- // that copies the directory locally to see its content
- assertTrue(HelpFunctions.compareTwoDir(locationSource.toFile(), destinationDir.toFile()));
- HelpFunctions.compareTwoCrateJson(roCrate, res);
+ @Override
+ protected Crate readCrate(Path source) throws IOException {
+ return Readers.newZipPathReader().readCrate(source.toAbsolutePath().toString());
}
- @Test
- void TestWithFileWithLocationAddEntity(@TempDir Path temp) throws IOException {
- Path file = temp.resolve("file.csv");
- FileUtils.writeStringToFile(file.toFile(), "fakecsv.1", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .setLocationWithExceptions(file)
- .setId("survey-responses-2019.csv")
- .build()
- )
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipReader());
- Crate res = roCrateFolderReader.readCrate(zipPath.toFile().getAbsolutePath());
-
- Path locationSource = temp.resolve("expected");
- RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
- writer.save(roCrate, locationSource.toString());
-
- Path newFile = temp.resolve("new_file");
- FileUtils.writeStringToFile(newFile.toFile(), "fkladjsl;fjasd;lfjda;lkf", Charset.defaultCharset());
-
- res.addDataEntity(new FileEntity.FileEntityBuilder()
- .setEncodingFormat("setnew")
- .setLocationWithExceptions(newFile)
- .setId("new_file")
- .build());
-
- Path destinationDir = temp.resolve("result");
- FileUtils.forceMkdir(destinationDir.toFile());
- writer.save(res, destinationDir.toFile().toString());
-
- assertFalse(HelpFunctions.compareTwoDir(locationSource.toFile(), destinationDir.toFile()));
- HelpFunctions.compareTwoMetadataJsonNotEqual(roCrate, res);
+ @Override
+ protected ZipStrategy newReaderStrategyWithTmp(Path tmpDirectory, boolean useUuidSubfolder) {
+ ZipStrategy strategy = new ZipStrategy(tmpDirectory, useUuidSubfolder);
+ assertFalse(strategy.isExtracted());
+ if (useUuidSubfolder) {
+ assertEquals(strategy.getTemporaryFolder().getFileName().toString(), strategy.getID());
+ } else {
+ assertEquals(strategy.getTemporaryFolder().getFileName().toString(), tmpDirectory.getFileName().toString());
+ }
+ assertTrue(strategy.getTemporaryFolder().startsWith(tmpDirectory));
+ return strategy;
}
- @Test
- void testReadingBasicCrateWithCustomPath(@TempDir Path temp) throws IOException {
- RoCrate roCrate = new RoCrate.RoCrateBuilder(
- "minimal",
- "minimal RO_crate",
- "2024",
- "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- File zipFile = zipPath.toFile();
- assertTrue(zipFile.isFile());
-
- Path differentFolder = temp.resolve("differentFolder");
- ZipReader readerType = new ZipReader(differentFolder, true);
- assertFalse(readerType.isExtracted());
- assertEquals(readerType.getTemporaryFolder().getFileName().toString(), readerType.getID());
- assertTrue(readerType.getTemporaryFolder().startsWith(differentFolder));
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(readerType);
- Crate crate = roCrateFolderReader.readCrate(zipFile.getAbsolutePath());
- assertTrue(readerType.isExtracted());
- HelpFunctions.compareTwoCrateJson(roCrate, crate);
-
- {
- // try it again without the UUID subfolder and test if the directory is being cleaned up (using coverage).
- ZipReader newReaderType = new ZipReader(differentFolder, false);
- assertFalse(newReaderType.isExtracted());
- assertNotEquals(newReaderType.getTemporaryFolder().getFileName().toString(), newReaderType.getID());
- assertTrue(newReaderType.getTemporaryFolder().startsWith(differentFolder));
-
- RoCrateReader newRoCrateFolderReader = new RoCrateReader(newReaderType);
- Crate crate2 = newRoCrateFolderReader.readCrate(zipFile.getAbsolutePath());
- assertTrue(newReaderType.isExtracted());
- HelpFunctions.compareTwoCrateJson(roCrate, crate2);
- }
+ @Override
+ protected Crate readCrate(ZipStrategy strategy, Path source) throws IOException {
+ Crate importedCrate = new CrateReader<>(strategy)
+ .readCrate(source.toAbsolutePath().toString());
+ assertTrue(strategy.isExtracted());
+ return importedCrate;
}
}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReaderTest.java b/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReaderTest.java
index 05ca63d5..33436c6c 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReaderTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReaderTest.java
@@ -1,201 +1,44 @@
package edu.kit.datamanager.ro_crate.reader;
import edu.kit.datamanager.ro_crate.Crate;
-import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
-import edu.kit.datamanager.ro_crate.writer.FolderWriter;
-import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
-import edu.kit.datamanager.ro_crate.writer.ZipWriter;
+import edu.kit.datamanager.ro_crate.writer.Writers;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.charset.Charset;
+import java.io.*;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.*;
-class ZipStreamReaderTest {
-
- @Test
- void testReadingBasicCrate(@TempDir Path temp) throws IOException {
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- File zipFile = zipPath.toFile();
- assertTrue(zipFile.isFile());
-
- RoCrateReader roCrateReader = new RoCrateReader(new ZipStreamReader());
- Crate res = roCrateReader.readCrate(new FileInputStream(zipFile));
- HelpFunctions.compareTwoCrateJson(roCrate, res);
- }
-
- @Test
- void testWithFile(@TempDir Path temp) throws IOException {
- Path cvs = temp.resolve("survey-responses-2019.csv");
- FileUtils.touch(cvs.toFile());
- FileUtils.writeStringToFile(cvs.toFile(), "fkdjaflkjfla", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .setLocationWithExceptions(cvs)
- .setId(cvs.toFile().getName())
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .build()
- )
- .build();
-
- assertEquals(1, roCrate.getAllDataEntities().size());
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toFile().getAbsolutePath());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipStreamReader());
- Crate res = roCrateFolderReader.readCrate(new FileInputStream(zipPath.toFile()));
-
- HelpFunctions.compareTwoCrateJson(roCrate, res);
+class ZipStreamReaderTest extends CrateReaderTest {
+ @Override
+ protected void saveCrate(Crate crate, Path target) throws IOException {
+ Writers.newZipStreamWriter().save(crate, new FileOutputStream(target.toFile()));
+ assertTrue(target.toFile().isFile());
}
- @Test
- void TestWithFileWithLocation(@TempDir Path temp) throws IOException {
- Path file = temp.resolve("survey-responses-2019.csv");
- FileUtils.writeStringToFile(file.toFile(), "fakecsv.1", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .setLocationWithExceptions(file)
- .setId("survey-responses-2019.csv")
- .build()
- )
- .setPreview(null)//disable preview to allow to compare folders before and after
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipStreamReader());
- Crate res = roCrateFolderReader.readCrate(new FileInputStream(zipPath.toFile()));
-
- Path locationSource = temp.resolve("expected");
- RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
- writer.save(roCrate, locationSource.toString());
-
- Path destinationDir = temp.resolve("result");
- FileUtils.forceMkdir(destinationDir.toFile());
- writer.save(res, destinationDir.toString());
-
- // that copies the directory locally to see its content
- assertTrue(HelpFunctions.compareTwoDir(locationSource.toFile(), destinationDir.toFile()));
- HelpFunctions.compareTwoCrateJson(roCrate, res);
+ @Override
+ protected Crate readCrate(Path source) throws IOException {
+ return Readers.newZipStreamReader().readCrate(new FileInputStream(source.toFile()));
}
- @Test
- void TestWithFileWithLocationAddEntity(@TempDir Path temp) throws IOException {
- Path file = temp.resolve("file.csv");
- FileUtils.writeStringToFile(file.toFile(), "fakecsv.1", Charset.defaultCharset());
- RoCrate roCrate = new RoCrate.RoCrateBuilder("minimal", "minimal RO_crate", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Survey responses")
- .addProperty("contentSize", "26452")
- .addProperty("encodingFormat", "text/csv")
- .setLocationWithExceptions(file)
- .setId("survey-responses-2019.csv")
- .build()
- )
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipStreamReader());
- Crate res = roCrateFolderReader.readCrate(new FileInputStream(zipPath.toFile()));
-
- Path locationSource = temp.resolve("expected");
- RoCrateWriter writer = new RoCrateWriter(new FolderWriter());
- writer.save(roCrate, locationSource.toString());
-
- Path newFile = temp.resolve("new_file");
- FileUtils.writeStringToFile(newFile.toFile(), "fkladjsl;fjasd;lfjda;lkf", Charset.defaultCharset());
-
- res.addDataEntity(new FileEntity.FileEntityBuilder()
- .setEncodingFormat("setnew")
- .setLocationWithExceptions(newFile)
- .setId("new_file")
- .build());
-
- Path destinationDir = temp.resolve("result");
- FileUtils.forceMkdir(destinationDir.toFile());
- writer.save(res, destinationDir.toFile().toString());
-
- assertFalse(HelpFunctions.compareTwoDir(locationSource.toFile(), destinationDir.toFile()));
- HelpFunctions.compareTwoMetadataJsonNotEqual(roCrate, res);
+ @Override
+ protected ZipStreamStrategy newReaderStrategyWithTmp(Path tmpDirectory, boolean useUuidSubfolder) {
+ ZipStreamStrategy strategy = new ZipStreamStrategy(tmpDirectory, useUuidSubfolder);
+ assertFalse(strategy.isExtracted());
+ if (useUuidSubfolder) {
+ assertEquals(strategy.getTemporaryFolder().getFileName().toString(), strategy.getID());
+ } else {
+ assertEquals(strategy.getTemporaryFolder().getFileName().toString(), tmpDirectory.getFileName().toString());
+ }
+ assertTrue(strategy.getTemporaryFolder().startsWith(tmpDirectory));
+ return strategy;
}
- @Test
- void testReadingBasicCrateWithCustomPath(@TempDir Path temp) throws IOException {
- RoCrate roCrate = new RoCrate.RoCrateBuilder(
- "minimal",
- "minimal RO_crate",
- "2024",
- "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .build();
-
- Path zipPath = temp.resolve("result.zip");
-
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- roCrateZipWriter.save(roCrate, zipPath.toString());
-
- File zipFile = zipPath.toFile();
- assertTrue(zipFile.isFile());
-
- Path differentFolder = temp.resolve("differentFolder");
- ZipStreamReader readerType = new ZipStreamReader(differentFolder, true);
- assertFalse(readerType.isExtracted());
- assertEquals(readerType.getTemporaryFolder().getFileName().toString(), readerType.getID());
- assertTrue(readerType.getTemporaryFolder().startsWith(differentFolder));
-
- RoCrateReader roCrateFolderReader = new RoCrateReader(readerType);
- Crate crate = roCrateFolderReader.readCrate(new FileInputStream(zipFile));
- assertTrue(readerType.isExtracted());
- HelpFunctions.compareTwoCrateJson(roCrate, crate);
-
- {
- // try it again without the UUID subfolder and test if the directory is being cleaned up (using coverage).
- ZipStreamReader newReaderType = new ZipStreamReader(differentFolder, false);
- assertFalse(newReaderType.isExtracted());
- assertNotEquals(newReaderType.getTemporaryFolder().getFileName().toString(), newReaderType.getID());
- assertTrue(newReaderType.getTemporaryFolder().startsWith(differentFolder));
-
- RoCrateReader newRoCrateFolderReader = new RoCrateReader(newReaderType);
- Crate crate2 = newRoCrateFolderReader.readCrate(new FileInputStream(zipFile));
- assertTrue(newReaderType.isExtracted());
- HelpFunctions.compareTwoCrateJson(roCrate, crate2);
- }
+ @Override
+ protected Crate readCrate(ZipStreamStrategy strategy, Path source) throws IOException {
+ Crate importedCrate = new CrateReader<>(strategy)
+ .readCrate(new FileInputStream(source.toFile()));
+ assertTrue(strategy.isExtracted());
+ return importedCrate;
}
}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/writer/CrateWriterTest.java b/src/test/java/edu/kit/datamanager/ro_crate/writer/CrateWriterTest.java
new file mode 100644
index 00000000..0e6e51e0
--- /dev/null
+++ b/src/test/java/edu/kit/datamanager/ro_crate/writer/CrateWriterTest.java
@@ -0,0 +1,280 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import edu.kit.datamanager.ro_crate.Crate;
+import edu.kit.datamanager.ro_crate.HelpFunctions;
+import edu.kit.datamanager.ro_crate.RoCrate;
+import edu.kit.datamanager.ro_crate.entities.data.DataSetEntity;
+import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
+import edu.kit.datamanager.ro_crate.preview.AutomaticPreview;
+import edu.kit.datamanager.ro_crate.preview.PreviewGenerator;
+import net.lingala.zip4j.ZipFile;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+abstract class CrateWriterTest {
+
+ /**
+ * Saves the crate with the writer fitting to this test class.
+ *
+ * @param crate the crate to save
+ * @param target the target path to the save location
+ * @throws IOException if an error occurs while saving the crate
+ */
+ abstract protected void saveCrate(Crate crate, Path target) throws IOException;
+
+ /**
+ * Test where the writer needs to rename files or folders in order to make a valid crate.
+ * The content will therefore not be equal to its source!
+ *
+ * @param tempDir the temporary directory given by junit for our test
+ * @throws IOException if an error occurs while writing the crate
+ */
+ @Test
+ void testFilesBeingAdjusted(@TempDir Path tempDir) throws IOException {
+ Path correctCrate = tempDir.resolve("compare_with_me");
+ Path pathToFile = correctCrate.resolve("you-will-need-to-rename-this-file.ai");
+ Path pathToDir = correctCrate.resolve("you-will-need-to-rename-this-dir");
+ this.createManualCrateStructure(correctCrate, pathToFile, pathToDir);
+
+ Path writtenCrate = tempDir.resolve("written-crate");
+ Path extractionPath = tempDir.resolve("checkMe");
+ {
+ RoCrate builtCrate = getCrateWithFileAndDir(pathToFile, pathToDir).build();
+ this.saveCrate(builtCrate, writtenCrate);
+ this.ensureCrateIsExtractedIn(writtenCrate, extractionPath);
+ }
+
+ printFileTree(correctCrate);
+ printFileTree(extractionPath);
+
+ // The actual file name should **not** appear in the crate
+ String fileName = pathToFile.getFileName().toString();
+ assertFalse(
+ Files.isRegularFile(extractionPath.resolve(fileName)),
+ "The directory should not be present, because '%s' is a file in the crate".formatted(fileName)
+ );
+ // Instead, the file should be present with the name of the ID
+ assertTrue(
+ Files.isRegularFile(extractionPath.resolve("cp7glop.ai")),
+ "The file 'cp7glop.ai' should be present and have the name adjusted to the ID"
+ );
+ // The actual directory name should **not** appear in the crate
+ String dirName = pathToDir.getFileName().toString();
+ assertFalse(
+ Files.isDirectory(extractionPath.resolve(dirName)),
+ "The directory should not be present, because '%s' is a file in the crate".formatted(dirName)
+ );
+ // Instead, the directory should be present with the name of the ID
+ assertTrue(
+ Files.isDirectory(extractionPath.resolve("lots_of_little_files/")),
+ "The directory 'lots_of_little_files' should be present"
+ );
+ }
+
+ /**
+ * Test where the writer should make an exact copy of our defined folder.
+ *
+ * @param tempDir the temporary directory given by junit for our test
+ * @throws IOException if an error occurs while writing the crate
+ */
+ @Test
+ void testWritingMakesCopy(@TempDir Path tempDir) throws IOException {
+ // We need a correct directory to compare with.
+ // It is built manually to ensure we meet our expectations.
+ // Reader-writer-consistency is tested at {@link CrateReaderTest}
+ Path correctCrate = tempDir.resolve("compare_with_me");
+ Path pathToFile = correctCrate.resolve("cp7glop.ai");
+ Path pathToDir = correctCrate.resolve("lots_of_little_files");
+
+ this.createManualCrateStructure(correctCrate, pathToFile, pathToDir);
+
+ // Now use the builder to build the same crate independently.
+ // The files will be reused (we need a place to take a copy from)
+ RoCrate builtCrate = getCrateWithFileAndDir(pathToFile, pathToDir).build();
+
+ Path pathToZip = tempDir.resolve("written-needs_testing.zip");
+ this.saveCrate(builtCrate, pathToZip);
+
+ // extract the zip file to a temporary directory
+ Path extractionPath = tempDir.resolve("extracted_for_testing");
+ this.ensureCrateIsExtractedIn(pathToZip, extractionPath);
+ printFileTree(correctCrate);
+ printFileTree(extractionPath);
+
+ // compare the extracted directory with the correct one
+ assertTrue(HelpFunctions.compareTwoDir(
+ correctCrate.toFile(),
+ extractionPath.toFile()));
+ HelpFunctions.compareCrateJsonToFileInResources(
+ builtCrate,
+ "/json/crate/fileAndDir.json");
+ }
+
+ /**
+ * Test where the writer should only consider the files that are added to the metadata json.
+ * The crate should not contain any files that are not part of it.
+ *
+ * @param tempDir the temporary directory given by junit for our test
+ * @throws IOException if an error occurs while writing the crate
+ */
+ @Test
+ void testWritingOnlyConsidersAddedFiles(@TempDir Path tempDir) throws IOException {
+ Path correctCrate = tempDir.resolve("compare_with_me");
+ Path pathToFile = correctCrate.resolve("cp7glop.ai");
+ Path pathToDir = correctCrate.resolve("lots_of_little_files");
+
+ this.createManualCrateStructure(correctCrate, pathToFile, pathToDir);
+ {
+ // This file is not part of the crate, and should therefore not be present
+ Path falseFile = correctCrate.resolve("new");
+ FileUtils.writeStringToFile(
+ falseFile.toFile(),
+ "this file contains something else",
+ Charset.defaultCharset());
+ }
+
+ // create the RO_Crate including the files that should be present in it
+ RoCrate roCrate = getCrateWithFileAndDir(pathToFile, pathToDir).build();
+
+ Path pathToZip = tempDir.resolve("writing-needs_testing.zip");
+ this.saveCrate(roCrate, pathToZip);
+
+
+ // extract and compare
+ Path extractionPath = tempDir.resolve("extracted_for_testing");
+ ensureCrateIsExtractedIn(pathToZip, extractionPath);
+ printFileTree(correctCrate);
+ printFileTree(extractionPath);
+
+ assertFalse(HelpFunctions.compareTwoDir(
+ correctCrate.toFile(),
+ extractionPath.toFile()),
+ "The crate should not contain the file that was not part of the metadata");
+ HelpFunctions.compareCrateJsonToFileInResources(
+ roCrate,
+ "/json/crate/fileAndDir.json");
+ }
+
+ /**
+ * Prints the file tree of the given directory for debugging and understanding
+ * a test more quickly.
+ *
+ * @param directoryToPrint the directory to print
+ * @throws IOException if an error occurs while printing the file tree
+ */
+ @SuppressWarnings("resource")
+ protected static void printFileTree(Path directoryToPrint) throws IOException {
+ // Print all files recursively in a tree structure for debugging
+ System.out.printf("Files in %s:%n", directoryToPrint.getFileName().toString());
+ Files.walk(directoryToPrint)
+ .forEach(path -> {
+ if (!path.toAbsolutePath().equals(directoryToPrint.toAbsolutePath())) {
+ int depth = path.relativize(directoryToPrint).getNameCount();
+ String prefix = " ".repeat(depth);
+ System.out.printf("%s%s%s%n", prefix, "└── ", path.getFileName());
+ }
+ });
+ }
+
+ /**
+ * Ensures the crate is in extracted form in the given path.
+ *
+ * @param pathToCrate the path to the crate, may not be a folder yet
+ * @param expectedPath the path where the crate should be in extracted form
+ * @throws IOException if an error occurs while extracting the crate
+ */
+ protected void ensureCrateIsExtractedIn(Path pathToCrate, Path expectedPath) throws IOException {
+ try (ZipFile zf = new ZipFile(pathToCrate.toFile())) {
+ zf.extractAll(expectedPath.toFile().getAbsolutePath());
+ }
+ }
+
+ /**
+ * Creates a crate structure manually.
+ *
+ * @param correctCrate the path to the crate
+ * @param pathToFile the path to the file
+ * @param pathToDir the path to the directory
+ * @throws IOException if an error occurs while creating the crate structure
+ */
+ protected void createManualCrateStructure(Path correctCrate, Path pathToFile, Path pathToDir) throws IOException {
+ FileUtils.forceMkdir(correctCrate.toFile());
+ InputStream fileJson = ZipStreamStrategyTest.class
+ .getResourceAsStream("/json/crate/fileAndDir.json");
+ Assertions.assertNotNull(fileJson);
+ // fill the directory with expected files and dirs
+ // starting with the .json of our crate
+ Path json = correctCrate.resolve("ro-crate-metadata.json");
+ FileUtils.copyInputStreamToFile(fileJson, json.toFile());
+ // create preview
+ PreviewGenerator.generatePreview(correctCrate.toFile().getAbsolutePath());
+ // create the files and directories
+ FileUtils.writeStringToFile(pathToFile.toFile(), "content of Local File", Charset.defaultCharset());
+ // creates the directory and a subdirectory
+ Path subdir = pathToDir.resolve("subdir");
+ FileUtils.forceMkdir(subdir.toFile());
+ FileUtils.writeStringToFile(
+ subdir.resolve("subsubfirst.txt").toFile(),
+ "content of subsub file in subsubdir",
+ Charset.defaultCharset());
+ FileUtils.writeStringToFile(
+ pathToDir.resolve("first.txt").toFile(),
+ "content of first file in dir",
+ Charset.defaultCharset());
+ FileUtils.writeStringToFile(
+ pathToDir.resolve("second.txt").toFile(),
+ "content of second file in dir",
+ Charset.defaultCharset());
+ FileUtils.writeStringToFile(
+ pathToDir.resolve("third.txt").toFile(),
+ "content of third file in dir",
+ Charset.defaultCharset());
+ }
+
+ /**
+ * Creates a crate resembling the one we manually create in these tests.
+ *
+ * @param pathToFile the file to add
+ * @param pathToSubdir the directory to add
+ * @return the crate builder
+ */
+ protected RoCrate.RoCrateBuilder getCrateWithFileAndDir(Path pathToFile, Path pathToSubdir) {
+ return new RoCrate.RoCrateBuilder(
+ "Example RO-Crate",
+ "The RO-Crate Root Data Entity",
+ "2024",
+ "https://creativecommons.org/licenses/by-nc-sa/3.0/au/"
+ )
+ .addDataEntity(
+ new FileEntity.FileEntityBuilder()
+ .addProperty("name", "Diagram showing trend to increase")
+ .addProperty("contentSize", "383766")
+ .addProperty("description", "Illustrator file for Glop Pot")
+ .setEncodingFormat("application/pdf")
+ .setLocationWithExceptions(pathToFile)
+ .setId("cp7glop.ai")
+ .build()
+ )
+ .addDataEntity(
+ new DataSetEntity.DataSetBuilder()
+ .addProperty("name", "Too many files")
+ .addProperty("description",
+ "This directory contains many small files, that we're not going to describe in detail.")
+ .setLocationWithExceptions(pathToSubdir)
+ .setId("lots_of_little_files/")
+ .build()
+ )
+ .setPreview(new AutomaticPreview());
+ }
+}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/writer/FolderWriterTest.java b/src/test/java/edu/kit/datamanager/ro_crate/writer/FolderWriterTest.java
index ba6ecc1a..7a469465 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/writer/FolderWriterTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/writer/FolderWriterTest.java
@@ -1,214 +1,26 @@
package edu.kit.datamanager.ro_crate.writer;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
import java.nio.file.Path;
-import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.entities.data.DataSetEntity;
-import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
-import edu.kit.datamanager.ro_crate.preview.AutomaticPreview;
-import edu.kit.datamanager.ro_crate.preview.CustomPreview;
-import edu.kit.datamanager.ro_crate.preview.PreviewGenerator;
+import edu.kit.datamanager.ro_crate.Crate;
import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
/**
* @author Nikola Tzotchev on 9.2.2022 г.
* @version 1
*/
-class FolderWriterTest {
-
- @Test
- void writeToFolderCorrectNames(@TempDir Path tempDir) throws IOException {
- Path fileWithoutID = tempDir.resolve("spo.txt");
- FileUtils.writeStringToFile(fileWithoutID.toFile(), "content", Charset.defaultCharset());
- Path file1 = tempDir.resolve("input.txt");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = tempDir.resolve("dir");
- FileUtils.forceMkdir(dirInCrate.toFile());
- Path dirInDirInCrate = dirInCrate.resolve("last_dir");
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInDirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
+class FolderWriterTest extends CrateWriterTest {
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(file1)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .setPreview(new AutomaticPreview())
- .build();
-
- Path result = tempDir.resolve("dest");
-
- RoCrateWriter folderRoCrateWriter = new RoCrateWriter(new FolderWriter());
- folderRoCrateWriter.save(roCrate, result.toFile().toString());
- // test if the names of the files in the crate are correct,
- // when there is an ID the file should be called the same as the entity.
- assertTrue(Files.isRegularFile(result.resolve("cp7glop.ai")));
- assertTrue(Files.isDirectory(result.resolve("lots_of_little_files/")));
- // assertTrue(Files.isRegularFile(result.resolve(fileWithoutID.getFileName())));
+ @Override
+ protected void saveCrate(Crate crate, Path target) throws IOException {
+ Writers.newFolderWriter()
+ .save(crate, target.toAbsolutePath().toString());
}
-
- @Test
- void writeToFolderTest(@TempDir Path tempDir) throws IOException {
- RoCrateWriter folderRoCrateWriter = new RoCrateWriter(new FolderWriter());
- Path roDir = tempDir.resolve("ro_dir");
- FileUtils.forceMkdir(roDir.toFile());
-
- // the .json of our crate
- InputStream fileJson
- = FolderWriterTest.class.getResourceAsStream("/json/crate/fileAndDir.json");
-
- // fill the expected directory with files and dirs
- Path json = roDir.resolve("ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(fileJson, json.toFile());
-
- //create preview via rochtml or custom as fallback
- if (PreviewGenerator.isRochtmlAvailable()) {
- PreviewGenerator.generatePreview(roDir.toString());
- } else {
- new CustomPreview().saveAllToFolder(roDir.toFile());
- }
- Path file1 = roDir.resolve("cp7glop.ai");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = roDir.resolve("lots_of_little_files");
- FileUtils.forceMkdir(dirInCrate.toFile());
- Path dirInDirInCrate = dirInCrate.resolve("last_dir");
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInDirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
-
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(file1)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .setPreview(new AutomaticPreview())
- .build();
-
- Path result = tempDir.resolve("dest");
- folderRoCrateWriter.save(roCrate, result.toFile().toString());
- assertTrue(HelpFunctions.compareTwoDir(result.toFile(), roDir.toFile()));
-
- // just so we know the metadata is still valid
- HelpFunctions.compareCrateJsonToFileInResources(roCrate, "/json/crate/fileAndDir.json");
- }
-
- @Test
- void writeToFolderWrongTest(@TempDir Path tempDir) throws IOException {
- RoCrateWriter folderRoCrateWriter = new RoCrateWriter(new FolderWriter());
- Path roDir = tempDir.resolve("ro_dir");
- FileUtils.forceMkdir(roDir.toFile());
-
- // the .json of our crate
- InputStream fileJson
- = FolderWriterTest.class.getResourceAsStream("/json/crate/fileAndDir.json");
- // fill the expected directory with files and dirs
- Path json = roDir.resolve("ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(fileJson, json.toFile());
-
- PreviewGenerator.generatePreview(roDir.toString());
-
- Path file1 = roDir.resolve("cp7glop.ai");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = roDir.resolve("lots_of_little_files");
- FileUtils.forceMkdir(dirInCrate.toFile());
- Path dirInDirInCrate = dirInCrate.resolve("last_dir");
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInDirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
- // false file, this test case should fal
- Path falseFile = tempDir.resolve("new");
- FileUtils.writeStringToFile(falseFile.toFile(), "this file contains something else", Charset.defaultCharset());
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(falseFile)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .setId("lots_of_little_files/")
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .build();
-
- Path result = tempDir.resolve("dest");
- folderRoCrateWriter.save(roCrate, result.toFile().toString());
- assertFalse(HelpFunctions.compareTwoDir(result.toFile(), roDir.toFile()));
-
- HelpFunctions.compareCrateJsonToFileInResources(roCrate, "/json/crate/fileAndDir.json");
+ @Override
+ protected void ensureCrateIsExtractedIn(Path pathToCrate, Path expectedPath) throws IOException {
+ FileUtils.copyDirectory(pathToCrate.toFile(), expectedPath.toFile());
}
}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriterSpec12Test.java b/src/test/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriterSpec12Test.java
index b6d4ed40..90161e4d 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriterSpec12Test.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/writer/RoCrateWriterSpec12Test.java
@@ -10,13 +10,12 @@
import java.nio.file.Path;
import java.nio.file.Paths;
+import edu.kit.datamanager.ro_crate.reader.Readers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import edu.kit.datamanager.ro_crate.Crate;
import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.reader.FolderReader;
-import edu.kit.datamanager.ro_crate.reader.RoCrateReader;
class RoCrateWriterSpec12Test {
@@ -27,14 +26,11 @@ void writeDoesNotModifyTest(@TempDir Path tempDir) throws IOException, URISyntax
URL internalOriginalCrateURL = this.getClass().getResource("/" + internalOriginalCratePath);
assertNotNull(internalOriginalCrateURL);
- Crate crate = new RoCrateReader(new FolderReader()).readCrate(internalOriginalCrateURL.getPath());
+ Crate crate = Readers.newFolderReader().readCrate(internalOriginalCrateURL.getPath());
Path targetDir = tempDir.resolve("spec12writeUnmodified");
- {
- // save to disk
- RoCrateWriter folderRoCrateWriter = new RoCrateWriter(new FolderWriter());
- folderRoCrateWriter.save(crate, targetDir.toFile().getPath());
- }
+ Writers.newFolderWriter()
+ .save(crate, targetDir.toAbsolutePath().toString());
// compare directories
Path srcDir = Paths.get(internalOriginalCrateURL.toURI());
@@ -51,7 +47,7 @@ void writeDoesNotModifyTest(@TempDir Path tempDir) throws IOException, URISyntax
// original metadata file
new File(srcDir.resolve("ro-crate-metadata.json").toString()));
// Compare loaded crate object with crate object made of export
- Crate crate2 = new RoCrateReader(new FolderReader()).readCrate(targetDir.toString());
+ Crate crate2 = Readers.newFolderReader().readCrate(targetDir.toString());
HelpFunctions.compareTwoCrateJson(crate, crate2);
}
}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipStreamStrategyTest.java b/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipStreamStrategyTest.java
new file mode 100644
index 00000000..2ba74518
--- /dev/null
+++ b/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipStreamStrategyTest.java
@@ -0,0 +1,18 @@
+package edu.kit.datamanager.ro_crate.writer;
+
+import java.io.*;
+import java.nio.file.Path;
+
+import edu.kit.datamanager.ro_crate.Crate;
+
+/**
+ * @author jejkal
+ */
+class ZipStreamStrategyTest extends CrateWriterTest {
+
+ @Override
+ protected void saveCrate(Crate crate, Path target) throws IOException {
+ FileOutputStream stream = new FileOutputStream(target.toFile());
+ Writers.newZipStreamWriter().save(crate, stream);
+ }
+}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipStreamWriterTest.java b/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipStreamWriterTest.java
deleted file mode 100644
index 2aa39bf3..00000000
--- a/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipStreamWriterTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package edu.kit.datamanager.ro_crate.writer;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.nio.file.Path;
-
-import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.entities.data.DataSetEntity;
-import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
-import edu.kit.datamanager.ro_crate.preview.AutomaticPreview;
-import edu.kit.datamanager.ro_crate.preview.PreviewGenerator;
-import net.lingala.zip4j.ZipFile;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-/**
- * @author jejkal
- */
-class ZipStreamWriterTest {
-
- @Test
- void testWritingToZipStream(@TempDir Path tempDir) throws IOException {
- // create the RO_crate directory in the tempDir
- Path roDir = tempDir.resolve("ro_dir");
- FileUtils.forceMkdir(roDir.toFile());
-
- // the .json of our crate
- InputStream fileJson=
- ZipStreamWriterTest.class.getResourceAsStream("/json/crate/fileAndDir.json");
-
- // fill the expected directory with files and dirs
-
- Path json = roDir.resolve("ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(fileJson, json.toFile());
-
- PreviewGenerator.generatePreview(roDir.toFile().getAbsolutePath());
-
- Path file1 = roDir.resolve("cp7glop.ai");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = roDir.resolve("dir");
- FileUtils.forceMkdir(dirInCrate.toFile());
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(file1)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .setPreview(new AutomaticPreview())
- .build();
-
- // safe the crate in the test.zip file
- Path test = tempDir.resolve("test.zip");
- // create a Writer for writing RoCrates to zip
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipStreamWriter());
-
-
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, test.toFile().getAbsolutePath());
- Path res = tempDir.resolve("dest");
- try (ZipFile zf = new ZipFile(test.toFile())) {
- zf.extractAll(res.toFile().getAbsolutePath());
- }
- assertTrue(HelpFunctions.compareTwoDir(roDir.toFile(), res.toFile()));
-
- // just so we know the metadata is still valid
- HelpFunctions.compareCrateJsonToFileInResources(roCrate, "/json/crate/fileAndDir.json");
- }
-
-
- @Test
- void testWritingToZipFail(@TempDir Path tempDir) throws IOException {
- // create the RO_crate directory in the tempDir
- Path roDir = tempDir.resolve("ro_dir");
- FileUtils.forceMkdir(roDir.toFile());
-
- // the .json of our crate
- InputStream fileJson=
- ZipStreamWriterTest.class.getResourceAsStream("/json/crate/fileAndDir.json");
-
- // fill the expected directory with files and dirs
-
- Path json = roDir.resolve("ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(fileJson, json.toFile());
-
- PreviewGenerator.generatePreview(roDir.toFile().getAbsolutePath());
-
- Path file1 = roDir.resolve("input.txt");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = roDir.resolve("dir");
- FileUtils.forceMkdir(dirInCrate.toFile());
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
- // false file, this test case should fal
- Path falseFile = tempDir.resolve("new");
- FileUtils.writeStringToFile(falseFile.toFile(), "this file contains something else", Charset.defaultCharset());
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(falseFile)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .setPreview(new AutomaticPreview())
- .build();
-
- // safe the crate in the test.zip file
- Path test = tempDir.resolve("test.zip");
- // create a Writer for writing RoCrates to zip
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipStreamWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, test.toFile().getAbsolutePath());
- Path res = tempDir.resolve("dest");
- try (ZipFile zf = new ZipFile(test.toFile())) {
- zf.extractAll(res.toFile().getAbsolutePath());
- }
- assertFalse(HelpFunctions.compareTwoDir(roDir.toFile(), res.toFile()));
-
- // just so we know the metadata is still valid
- HelpFunctions.compareCrateJsonToFileInResources(roCrate, "/json/crate/fileAndDir.json");
- }
-}
diff --git a/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipWriterTest.java b/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipWriterTest.java
index a3a2e231..3b8b1fc0 100644
--- a/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipWriterTest.java
+++ b/src/test/java/edu/kit/datamanager/ro_crate/writer/ZipWriterTest.java
@@ -1,175 +1,14 @@
package edu.kit.datamanager.ro_crate.writer;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
import java.nio.file.Path;
-import edu.kit.datamanager.ro_crate.HelpFunctions;
-import edu.kit.datamanager.ro_crate.RoCrate;
-import edu.kit.datamanager.ro_crate.entities.data.DataSetEntity;
-import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
-import edu.kit.datamanager.ro_crate.preview.AutomaticPreview;
-import edu.kit.datamanager.ro_crate.preview.CustomPreview;
-import edu.kit.datamanager.ro_crate.preview.PreviewGenerator;
-import net.lingala.zip4j.ZipFile;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-/**
- * @author Nikola Tzotchev on 9.2.2022 г.
- * @version 1
- */
-class ZipWriterTest {
-
- @Test
- void testWritingToZip(@TempDir Path tempDir) throws IOException {
- // create the RO_crate directory in the tempDir
- Path roDir = tempDir.resolve("ro_dir");
- FileUtils.forceMkdir(roDir.toFile());
-
- // the .json of our crate
- InputStream fileJson
- = ZipWriterTest.class.getResourceAsStream("/json/crate/fileAndDir.json");
-
- // fill the expected directory with files and dirs
- Path json = roDir.resolve("ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(fileJson, json.toFile());
-
- //create preview via rochtml or custom as fallback
- if (PreviewGenerator.isRochtmlAvailable()) {
- PreviewGenerator.generatePreview(roDir.toString());
- } else {
- new CustomPreview().saveAllToFolder(roDir.toFile());
- }
- Path file1 = roDir.resolve("cp7glop.ai");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = roDir.resolve("dir");
- FileUtils.forceMkdir(dirInCrate.toFile());
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
-
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(file1)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .setPreview(new AutomaticPreview())
- .build();
-
- // safe the crate in the test.zip file
- Path test = tempDir.resolve("test.zip");
- // create a Writer for writing RoCrates to zip
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, test.toString());
- roCrateZipWriter.save(roCrate, "/Users/jejkal/cra.zip");
-
- Path res = tempDir.resolve("dest");
- try (ZipFile zf = new ZipFile(test.toFile())) {
- zf.extractAll(res.toString());
- }
- assertTrue(HelpFunctions.compareTwoDir(roDir.toFile(), res.toFile()));
-
- // just so we know the metadata is still valid
- HelpFunctions.compareCrateJsonToFileInResources(roCrate, "/json/crate/fileAndDir.json");
- }
-
- @Test
- void testWritingToZipFail(@TempDir Path tempDir) throws IOException {
- // create the RO_crate directory in the tempDir
- Path roDir = tempDir.resolve("ro_dir");
- FileUtils.forceMkdir(roDir.toFile());
-
- // the .json of our crate
- InputStream fileJson
- = ZipWriterTest.class.getResourceAsStream("/json/crate/fileAndDir.json");
-
- // fill the expected directory with files and dirs
- Path json = roDir.resolve("ro-crate-metadata.json");
- FileUtils.copyInputStreamToFile(fileJson, json.toFile());
-
- PreviewGenerator.generatePreview(roDir.toFile().getAbsolutePath());
-
- Path file1 = roDir.resolve("input.txt");
- FileUtils.writeStringToFile(file1.toFile(), "content of Local File", Charset.defaultCharset());
- Path dirInCrate = roDir.resolve("dir");
- FileUtils.forceMkdir(dirInCrate.toFile());
- FileUtils.writeStringToFile(dirInCrate.resolve("first.txt").toFile(),
- "content of first file in dir", Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("second.txt").toFile(),
- "content of second file in dir",
- Charset.defaultCharset());
- FileUtils.writeStringToFile(dirInCrate.resolve("third.txt").toFile(),
- "content of third file in dir",
- Charset.defaultCharset());
- // false file, this test case should fal
- Path falseFile = tempDir.resolve("new");
- FileUtils.writeStringToFile(falseFile.toFile(), "this file contains something else", Charset.defaultCharset());
- // create the RO_Crate including the files that should be present in it
- RoCrate roCrate = new RoCrate.RoCrateBuilder("Example RO-Crate",
- "The RO-Crate Root Data Entity", "2024", "https://creativecommons.org/licenses/by-nc-sa/3.0/au/")
- .addDataEntity(
- new FileEntity.FileEntityBuilder()
- .addProperty("name", "Diagram showing trend to increase")
- .addProperty("contentSize", "383766")
- .addProperty("description", "Illustrator file for Glop Pot")
- .setEncodingFormat("application/pdf")
- .setLocationWithExceptions(falseFile)
- .setId("cp7glop.ai")
- .build()
- )
- .addDataEntity(
- new DataSetEntity.DataSetBuilder()
- .addProperty("name", "Too many files")
- .addProperty("description",
- "This directory contains many small files, that we're not going to describe in detail.")
- .setLocationWithExceptions(dirInCrate)
- .setId("lots_of_little_files/")
- .build()
- )
- .build();
-
- // safe the crate in the test.zip file
- Path test = tempDir.resolve("test.zip");
- // create a Writer for writing RoCrates to zip
- RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
- // save the content of the roCrate to the dest zip
- roCrateZipWriter.save(roCrate, test.toFile().getAbsolutePath());
- Path res = tempDir.resolve("dest");
- try (ZipFile zf = new ZipFile(test.toFile())) {
- zf.extractAll(res.toFile().getAbsolutePath());
- }
- assertFalse(HelpFunctions.compareTwoDir(roDir.toFile(), res.toFile()));
+import edu.kit.datamanager.ro_crate.Crate;
- // just so we know the metadata is still valid
- HelpFunctions.compareCrateJsonToFileInResources(roCrate, "/json/crate/fileAndDir.json");
+class ZipWriterTest extends CrateWriterTest {
+ @Override
+ protected void saveCrate(Crate crate, Path target) throws IOException {
+ Writers.newZipPathWriter()
+ .save(crate, target.toAbsolutePath().toString());
}
}