Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
cdecbed
test: add parameterized test for reading ELN crates from URLs
Pfeil May 5, 2025
c7e0afc
refactor: enable readers to implement subsets of tests if they make s…
Pfeil May 5, 2025
2e0df35
feat: reading zip files now searches for a crate in subdirectories.
Pfeil May 5, 2025
ccc0fe8
chore: fix deprecation warning in ElnFileFormatTest and enable better…
Pfeil May 5, 2025
0434a73
fix: improve error reporting for JSON schema validation
Pfeil May 5, 2025
966255f
refactor: replace deprecated setAll method with setAllIfValid and set…
Pfeil May 5, 2025
d0c1103
refactor: use try-with-resources for CloseableHttpClient in RoCrateMe…
Pfeil May 5, 2025
cdb897c
fix: correct typos and improve formatting in documentation and error …
Pfeil May 5, 2025
160ba97
docs: enhance documentation and add tests for setAllIfValid and setAl…
Pfeil May 5, 2025
86654f6
fix: invalid entities from our providers should be logged and not wri…
Pfeil May 5, 2025
7e4a30f
refactor: optimize file search in ZipStrategy by using directory filter
Pfeil May 6, 2025
49f1b2c
fix: improve metadata file resolution in ZipStreamStrategy to search …
Pfeil May 6, 2025
6f1948c
fix: handle directory entries in ZipStreamStrategy to ensure proper e…
Pfeil May 6, 2025
5dd5421
fix: integrate Apache Commons Compress for improved zip file handling…
Pfeil May 6, 2025
a704a0b
Revert "fix: integrate Apache Commons Compress for improved zip file …
Pfeil May 8, 2025
586276b
Revert "fix: invalid entities from our providers should be logged and…
Pfeil May 8, 2025
eac3a75
fix: propagate IOException in crate reading and writing methods
Pfeil May 8, 2025
62b1b0c
refactor: setAll method now uses setAllIfValid to avoid code duplication
Pfeil May 8, 2025
d3f7986
tests: add blacklist functionality for unsupported ELN files in tests
Pfeil May 8, 2025
cca2cd5
tests: remove possible side effects between tests in LearnByExampleTe…
Pfeil May 8, 2025
6fd9ac2
refactor: pull DataEntity saveToStream logic into writer.ZipStreamStr…
Pfeil May 8, 2025
b58d6bd
refactor: propagate IOExceptions properly in writer.ZipStreamStrategy…
Pfeil May 8, 2025
6e1dae6
refactor: propagate IOExceptions properly in writer.FolderStrategy
Pfeil May 8, 2025
82cee04
refactor: propagate IOExceptions properly in writer.ZipStrategy
Pfeil May 8, 2025
bee2917
refactor: pull DataEntity saveToZip logic into writer.ZipStrategy
Pfeil May 8, 2025
08a5f10
refactor: remove outdated saveToStream method documentation in writer…
Pfeil May 8, 2025
0fc94e7
refactor: move savetoFile logic from DataEntity to FolderStrategy
Pfeil May 8, 2025
e41cfcf
refactor: propagate IOException handling in reader.FolderStrategy and…
Pfeil May 8, 2025
bccbf0b
tests: implement ELN style crate writer test for ZipWriterTest
Pfeil May 9, 2025
b46be7f
feat: implement eln style writing for reader.ZipStrategy
Pfeil May 9, 2025
a296f91
test: add test for withRootSubdirectory
Pfeil May 9, 2025
b25d1eb
fix: remove IOException documentation from usingElnStyle and withRoot…
Pfeil May 9, 2025
a09d6f0
docs: add return documentation for usingElnStyle and withRootSubdirec…
Pfeil May 9, 2025
00ee66e
test: share alias test with all eln writers and implement test for Zi…
Pfeil May 12, 2025
e2a4bf3
feat: support ELN format in ZipStreamStrategy
Pfeil May 12, 2025
8455f4f
test: add tests for saving previews to ZipOutputStream in PreviewTest
Pfeil May 19, 2025
5ef25d4
fix: enforce correct subfolder name for additional files in StaticPre…
Pfeil May 19, 2025
e4d91d0
Merge pull request #261 from kit-data-manager/fix-preview-additional-…
Pfeil May 19, 2025
cfa6f73
refactor: prefix reader strategies and writer strategies with Read or…
Pfeil May 19, 2025
92ce1cb
refactor: remove unused import in ZipWriterTest
Pfeil May 19, 2025
87f790b
refactor: rename ZipStreamStrategyTest to ZipStreamWriterTest and upd…
Pfeil May 19, 2025
b22e70b
docs: Improve reader and writer documentation, and related type param…
Pfeil May 19, 2025
896018d
refactor: started sharing code between WriteZipStrategy and WriteZipS…
Pfeil May 19, 2025
fd9b84d
refactor: factor out common tmp directory handling in zip readers
Pfeil May 19, 2025
1e2da11
refactor: simplify WriteZipStrategy by delegating save operations to …
Pfeil May 19, 2025
9cf26b1
docs: add IOException documentation to readCrate method and clarify C…
Pfeil May 19, 2025
06b2146
test: add not-null-assertions for crate and person entity
Pfeil May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ dependencies {
implementation("org.freemarker:freemarker:2.3.34")
}

// enable -Xlint:deprecation
tasks.withType(JavaCompile).configureEach {
options.compilerArgs << "-Xlint:deprecation"
}

logging.captureStandardOutput LogLevel.INFO

def signingTasks = tasks.withType(Sign)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ public boolean checkEntity(AbstractEntity entity) {
node.remove("@id");
node.remove("@type");

Set<String> types = objectMapper.convertValue(entity.getProperties().get("@type"),
new TypeReference<>() {
});
Set<String> types = objectMapper.convertValue(
entity.getProperties().path("@type"),
new TypeReference<>() {}
);
// check if the items in the array of types are present in the context
for (String s : types) {
// special cases:
Expand Down Expand Up @@ -174,15 +175,14 @@ public void addToContextFromUrl(String url) {
}
}
if (jsonNode == null) {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response;
try {
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
response = httpclient.execute(httpGet);
jsonNode = objectMapper.readValue(response.getEntity().getContent(),
JsonNode.class);
} catch (IOException e) {
System.err.println(String.format("Cannot get context from url %s", url));
System.err.printf("Cannot get context from url %s%n", url);
return;
}
if (url.equals(DEFAULT_CONTEXT)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,20 +558,62 @@ public T addIdFromCollectionOfEntities(String name, Collection<AbstractEntity> e
}

/**
* This sets everything from a json object to the property. Can be
* useful when the entity is already available somewhere.
* Deprecated. Equivalent to {@link #setAllIfValid(ObjectNode)}.
*
* @param properties the Json representing all the properties.
* @return the generic builder.
* @return the generic builder, either including all given properties
* * or unchanged.
*
* @deprecated To enforce the user know what this method does,
* we want the user to use one of the more explicitly named
* methods {@link #setAllIfValid(ObjectNode)} or
* {@link #setAllIfValid(ObjectNode)}.
* @see #setAllIfValid(ObjectNode)
*/
@Deprecated(since = "2.1.0", forRemoval = true)
public T setAll(ObjectNode properties) {
return setAllIfValid(properties);
}

/**
* This sets everything from a json object to the property,
* <b>if the result is valid</b>. Otherwise, it will do <b>nothing</b>.
* <p>
* Valid means here that the json object needs to be flat as specified
* in the RO-Crate specification. In principle, this means that
* primitives and objects referencing an ID are allowed,
* as well as arrays of these.
*
* @param properties the Json representing all the properties.
* @return the generic builder, either including all given properties
* or unchanged.
*/
public T setAllIfValid(ObjectNode properties) {
if (AbstractEntity.entityValidation.entityValidation(properties)) {
this.properties = properties;
this.relatedItems.addAll(JsonUtilFunctions.getIdPropertiesFromJsonNode(properties));
}
return self();
}

/**
* This sets everything from a json object to the property. Can be
* useful when the entity is already available somewhere.
* <p>
* Errors on validation are printed, but everything will be added.
* For more about validation, see {@link #setAllIfValid(ObjectNode)}.
*
* @param properties the Json representing all the properties.
* @return the generic builder with all properties added.
*/
public T setAllUnsafe(ObjectNode properties) {
// This will currently only print errors.
AbstractEntity.entityValidation.entityValidation(properties);
this.properties = properties;
this.relatedItems.addAll(JsonUtilFunctions.getIdPropertiesFromJsonNode(properties));
return self();
}

public abstract T self();

public abstract AbstractEntity build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

public class JsonDescriptor extends ContextualEntity {

private static final String CONFORMS_TO = "conformsTo";
protected static final String ID = "ro-crate-metadata.json";
protected static final String CONFORMS_TO = "conformsTo";
public static final String ID = "ro-crate-metadata.json";

/**
* Returns a JsonDescriptor with the conformsTo value set to the latest stable
Expand All @@ -39,7 +39,7 @@ private JsonDescriptor(ContextualEntityBuilder builder) {

/**
* Builder for the JsonDescriptor.
*
* <p>
* Defaults to the latest stable crate version and no other conformsTo values.
*/
public static final class Builder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,11 @@
import edu.kit.datamanager.ro_crate.entities.AbstractEntity;
import edu.kit.datamanager.ro_crate.entities.contextual.ContextualEntity;
import static edu.kit.datamanager.ro_crate.special.IdentifierUtils.isUrl;
import edu.kit.datamanager.ro_crate.util.ZipUtil;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import org.apache.commons.io.FileUtils;

/**
* The base class of every data entity.
Expand Down Expand Up @@ -56,54 +48,6 @@ public void addAuthorId(String id) {
this.addIdProperty("author", id);
}

/**
* If the data entity contains a physical file. This method will write it
* when the crate is being written to a zip archive.
*
* @param zipFile the zipFile where it should be written.
* @throws ZipException when something goes wrong with the writing to the
* zip file.
*/
public void saveToZip(ZipFile zipFile) throws ZipException {
if (this.path != null) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(this.getId());
zipFile.addFile(this.path.toFile(), zipParameters);
}
}

/**
* If the data entity contains a physical file. This method will write it
* when the crate is being written to a zip archive.
*
* @param zipStream The zip output stream where it should be written.
* @throws ZipException when something goes wrong with the writing to the
* zip file.
* @throws IOException If opening the file input stream fails.
*/
public void saveToStream(ZipOutputStream zipStream) throws ZipException, IOException {
if (this.path != null) {
ZipUtil.addFileToZipStream(zipStream, this.path.toFile(), this.getId());
}
}

/**
* If the data entity contains a physical file. This method will write it
* when the crate is being written to a folder.
*
* @param file the folder location where the entity should be written.
* @throws IOException if something goes wrong with the writing.
*/
public void savetoFile(File file) throws IOException {
if (this.getPath() != null) {
if (this.getPath().toFile().isDirectory()) {
FileUtils.copyDirectory(this.getPath().toFile(), file.toPath().resolve(this.getId()).toFile());
} else {
FileUtils.copyFile(this.getPath().toFile(), file.toPath().resolve(this.getId()).toFile());
}
}
}

@JsonIgnore
public Path getPath() {
return path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import edu.kit.datamanager.ro_crate.entities.serializers.HasPartSerializer;
import edu.kit.datamanager.ro_crate.util.ZipUtil;
import java.io.IOException;

import java.util.HashSet;
import java.util.Set;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;

/**
* A helping class for the creating of Data entities of type Dataset.
Expand Down Expand Up @@ -43,26 +37,6 @@ public void removeFromHasPart(String str) {
this.hasPart.remove(str);
}

@Override
public void saveToZip(ZipFile zipFile) throws ZipException {
if (this.getPath() != null) {
ZipParameters parameters = new ZipParameters();
parameters.setRootFolderNameInZip(this.getId());
parameters.setIncludeRootFolder(false);
zipFile.addFolder(this.getPath().toFile(), parameters);
}
}

@Override
public void saveToStream(ZipOutputStream zipOutputStream) throws IOException {
if (this.getPath() != null) {
ZipUtil.addFolderToZipStream(
zipOutputStream,
this.getPath().toAbsolutePath().toString(),
this.getId());
}
}

public void addToHasPart(String id) {
this.hasPart.add(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public boolean validateEntity(JsonNode entity) {
Set<ValidationMessage> errors = this.entitySchema.validate(entity);
if (errors.size() != 0) {
System.err.println("This entity does not comply to the basic RO-Crate entity structure.");
errors.forEach(error -> System.err.println(error.getMessage()));
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ private static void addToCrateFromZotero(String url, Crate crate) {
for (var entity : graph) {
if (entity.get("@id").asText().equals(mainId)) {
var dataEntity = new DataEntity.DataEntityBuilder()
.setAll((ObjectNode) entity).build();
.setAllUnsafe((ObjectNode) entity).build();
crate.addDataEntity(dataEntity);
} else {
// here we have to think of a way to differentiate between data and contextual entities.
var contextualEntity = new ContextualEntity.ContextualEntityBuilder()
.setAll((ObjectNode) entity).build();
.setAllUnsafe((ObjectNode) entity).build();
crate.addContextualEntity(contextualEntity);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static PersonEntity getPerson(String url) {
node.set(element.getKey(), element.getValue());
}
}
return new PersonEntity.PersonEntityBuilder().setAll(node).build();
return new PersonEntity.PersonEntityBuilder().setAllUnsafe(node).build();
} catch (IOException e) {
String errorMessage = String.format("IO error: %s", e.getMessage());
logger.error(errorMessage);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package edu.kit.datamanager.ro_crate.preview;

import edu.kit.datamanager.ro_crate.util.ZipUtil;
import edu.kit.datamanager.ro_crate.util.ZipStreamUtil;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
Expand All @@ -10,9 +10,9 @@
import org.apache.commons.io.FileUtils;

/**
* The default preview should use the rochtml tool
* (https://www.npmjs.com/package/ro-crate-html-js) for creating a simple
* preview file.
* The default preview should use the
* <a href="https://www.npmjs.com/package/ro-crate-html-js">rochtml tool</a>
* for creating a simple preview file.
*
* @author Nikola Tzotchev on 6.2.2022 г.
* @version 1
Expand Down Expand Up @@ -66,13 +66,13 @@ public void saveAllToStream(String metadata, ZipOutputStream stream) throws IOEx
if (PreviewGenerator.isRochtmlAvailable()) {
try {
FileUtils.forceMkdir(new File("temp"));
try (FileWriter writer = new FileWriter(new File("temp/ro-crate-metadata.json"))) {
try (FileWriter writer = new FileWriter("temp/ro-crate-metadata.json")) {
writer.write(metadata);
writer.flush();
}
if (PreviewGenerator.isRochtmlAvailable()) {
PreviewGenerator.generatePreview("temp");
ZipUtil.addFileToZipStream(stream, new File("temp/ro-crate-preview.html"), "ro-crate-preview.html");
ZipStreamUtil.addFileToZipStream(stream, new File("temp/ro-crate-preview.html"), "ro-crate-preview.html");
}
} finally {
try {
Expand Down
Loading