Skip to content

Commit cde7c63

Browse files
authored
Merge pull request #255 from kit-data-manager/development
Next Version (v2.1.0-rc2)
2 parents a12a068 + ee9bdb1 commit cde7c63

File tree

74 files changed

+2956
-1549
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2956
-1549
lines changed

.github/workflows/gradle.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ on:
1111
push:
1212
branches: [ main, development ]
1313
pull_request:
14-
branches: [ main, development ]
1514
workflow_dispatch:
1615

1716
env:

README.md

Lines changed: 19 additions & 672 deletions
Large diffs are not rendered by default.

build.gradle

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ repositories {
3838
}
3939

4040
ext {
41-
jacksonVersion = '2.18.3'
41+
jacksonVersion = '2.19.0'
4242
}
4343

4444
dependencies {
@@ -67,10 +67,15 @@ dependencies {
6767
implementation group: "com.networknt", name: "json-schema-validator", version: "1.5.6"
6868
implementation 'org.glassfish:jakarta.json:2.0.1'
6969
//JTE for template processing
70-
implementation('gg.jte:jte:3.2.0')
70+
implementation('gg.jte:jte:3.2.1')
7171
implementation("org.freemarker:freemarker:2.3.34")
7272
}
7373

74+
// enable -Xlint:deprecation
75+
tasks.withType(JavaCompile).configureEach {
76+
options.compilerArgs << "-Xlint:deprecation"
77+
}
78+
7479
logging.captureStandardOutput LogLevel.INFO
7580

7681
def signingTasks = tasks.withType(Sign)

gradle/wrapper/gradle-wrapper.jar

59 Bytes
Binary file not shown.

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

gradlew

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ case "$( uname )" in #(
114114
NONSTOP* ) nonstop=true ;;
115115
esac
116116

117-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
117+
CLASSPATH="\\\"\\\""
118118

119119

120120
# Determine the Java command to use to start the JVM.
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
213213
set -- \
214214
"-Dorg.gradle.appname=$APP_BASE_NAME" \
215215
-classpath "$CLASSPATH" \
216-
org.gradle.wrapper.GradleWrapperMain \
216+
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
217217
"$@"
218218

219219
# Stop when "xargs" is not available.

gradlew.bat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ goto fail
7070
:execute
7171
@rem Setup the command line
7272

73-
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73+
set CLASSPATH=
7474

7575

7676
@rem Execute Gradle
77-
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
77+
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
7878

7979
:end
8080
@rem End local scope for the variables with windows NT shell

src/main/java/edu/kit/datamanager/ro_crate/RoCrate.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@
1010
import edu.kit.datamanager.ro_crate.entities.AbstractEntity;
1111
import edu.kit.datamanager.ro_crate.entities.contextual.ContextualEntity;
1212
import edu.kit.datamanager.ro_crate.entities.contextual.JsonDescriptor;
13-
import edu.kit.datamanager.ro_crate.entities.contextual.OrganizationEntity;
1413
import edu.kit.datamanager.ro_crate.entities.data.DataEntity;
15-
import edu.kit.datamanager.ro_crate.entities.data.DataEntity.DataEntityBuilder;
16-
import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
14+
1715
import edu.kit.datamanager.ro_crate.entities.data.RootDataEntity;
1816
import edu.kit.datamanager.ro_crate.externalproviders.dataentities.ImportFromDataCite;
19-
import edu.kit.datamanager.ro_crate.externalproviders.organizationprovider.RorProvider;
2017
import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
2118
import edu.kit.datamanager.ro_crate.payload.CratePayload;
2219
import edu.kit.datamanager.ro_crate.payload.RoCratePayload;
@@ -26,12 +23,9 @@
2623
import edu.kit.datamanager.ro_crate.special.JsonUtilFunctions;
2724
import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
2825
import edu.kit.datamanager.ro_crate.validation.Validator;
29-
import edu.kit.datamanager.ro_crate.writer.FolderWriter;
30-
import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
3126

3227
import java.io.File;
3328
import java.net.URI;
34-
import java.nio.file.Paths;
3529
import java.util.*;
3630
import java.util.stream.Collectors;
3731
import java.util.stream.StreamSupport;
@@ -354,6 +348,18 @@ public RoCrateBuilder addName(String name) {
354348
return this;
355349
}
356350

351+
/**
352+
* Adds an "identifier" property to the root data entity.
353+
* <p>
354+
* This is useful e.g. to assign e.g. a DOI to this crate.
355+
* @param identifier the identifier to add.
356+
* @return this builder.
357+
*/
358+
public RoCrateBuilder addIdentifier(String identifier) {
359+
this.rootDataEntity.addProperty("identifier", identifier.strip());
360+
return this;
361+
}
362+
357363
public RoCrateBuilder addDescription(String description) {
358364
this.rootDataEntity.addProperty(PROPERTY_DESCRIPTION, description);
359365
return this;

src/main/java/edu/kit/datamanager/ro_crate/context/RoCrateMetadataContext.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,10 @@ public boolean checkEntity(AbstractEntity entity) {
113113
node.remove("@id");
114114
node.remove("@type");
115115

116-
Set<String> types = objectMapper.convertValue(entity.getProperties().get("@type"),
117-
new TypeReference<>() {
118-
});
116+
Set<String> types = objectMapper.convertValue(
117+
entity.getProperties().path("@type"),
118+
new TypeReference<>() {}
119+
);
119120
// check if the items in the array of types are present in the context
120121
for (String s : types) {
121122
// special cases:
@@ -174,15 +175,14 @@ public void addToContextFromUrl(String url) {
174175
}
175176
}
176177
if (jsonNode == null) {
177-
CloseableHttpClient httpclient = HttpClients.createDefault();
178178
HttpGet httpGet = new HttpGet(url);
179179
CloseableHttpResponse response;
180-
try {
180+
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
181181
response = httpclient.execute(httpGet);
182182
jsonNode = objectMapper.readValue(response.getEntity().getContent(),
183183
JsonNode.class);
184184
} catch (IOException e) {
185-
System.err.println(String.format("Cannot get context from url %s", url));
185+
System.err.printf("Cannot get context from url %s%n", url);
186186
return;
187187
}
188188
if (url.equals(DEFAULT_CONTEXT)) {

src/main/java/edu/kit/datamanager/ro_crate/entities/AbstractEntity.java

Lines changed: 107 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -239,33 +239,61 @@ private static boolean addProperty(ObjectNode whereToAdd, String key, JsonNode v
239239
* @param id the "id" of the property.
240240
*/
241241
public void addIdProperty(String name, String id) {
242-
JsonNode jsonNode = addToIdProperty(name, id, this.properties.get(name));
243-
if (jsonNode != null) {
244-
this.linkedTo.add(id);
245-
this.properties.set(name, jsonNode);
246-
this.notifyObservers();
247-
}
242+
if (id == null || id.isBlank()) { return; }
243+
mergeIdIntoValue(id, this.properties.get(name))
244+
.ifPresent(newValue -> {
245+
this.properties.set(name, newValue);
246+
});
247+
this.linkedTo.add(id);
248+
this.notifyObservers();
248249
}
249250

250-
private static JsonNode addToIdProperty(String name, String id, JsonNode property) {
251-
ObjectMapper objectMapper = MyObjectMapper.getMapper();
252-
if (name != null && id != null) {
253-
if (property == null) {
254-
return objectMapper.createObjectNode().put("@id", id);
255-
} else {
256-
if (property.isArray()) {
257-
ArrayNode ns = (ArrayNode) property;
258-
ns.add(objectMapper.createObjectNode().put("@id", id));
259-
return ns;
260-
} else {
261-
ArrayNode newNodes = objectMapper.createArrayNode();
262-
newNodes.add(property);
263-
newNodes.add(objectMapper.createObjectNode().put("@id", id));
264-
return newNodes;
265-
}
266-
}
251+
/**
252+
* Merges the given id into the current value,
253+
* using this representation: {"@id" : "id"}.
254+
* <p>
255+
* The current value can be null without errors.
256+
* Only the id will be considered in this case.
257+
* <p>
258+
* If the id is null-ish, it will not be added, similar to a null-ish value.
259+
* If the id is already present, nothing will be done.
260+
* If it is not an array and the id is not present, an array will be applied.
261+
*
262+
* @param id the id to add.
263+
* @param currentValue the current value of the property.
264+
* @return The updated value of the property.
265+
* Empty if value does not change!
266+
*/
267+
protected static Optional<JsonNode> mergeIdIntoValue(String id, JsonNode currentValue) {
268+
if (id == null || id.isBlank()) { return Optional.empty(); }
269+
270+
ObjectMapper jsonBuilder = MyObjectMapper.getMapper();
271+
ObjectNode newIdObject = jsonBuilder.createObjectNode().put("@id", id);
272+
if (currentValue == null || currentValue.isNull() || currentValue.isMissingNode()) {
273+
return Optional.ofNullable(newIdObject);
274+
}
275+
276+
boolean isIdAlready = currentValue.asText().equals(id);
277+
boolean isIdObjectAlready = currentValue.path("@id").asText().equals(id);
278+
boolean isArrayWithIdPresent = currentValue.valueStream()
279+
.anyMatch(node -> node
280+
.path("@id")
281+
.asText()
282+
.equals(id));
283+
if (isIdAlready || isIdObjectAlready || isArrayWithIdPresent) {
284+
return Optional.empty();
285+
}
286+
287+
if (currentValue.isArray() && currentValue instanceof ArrayNode currentValueAsArray) {
288+
currentValueAsArray.add(newIdObject);
289+
return Optional.of(currentValueAsArray);
290+
} else {
291+
// property is not an array, so we make it an array
292+
ArrayNode newNodes = jsonBuilder.createArrayNode();
293+
newNodes.add(currentValue);
294+
newNodes.add(newIdObject);
295+
return Optional.of(newNodes);
267296
}
268-
return null;
269297
}
270298

271299
/**
@@ -369,6 +397,11 @@ protected String getId() {
369397
/**
370398
* Setting the id property of the entity, if the given value is not
371399
* null. If the id is not encoded, the encoding will be done.
400+
* <p>
401+
* <b>NOTE: IDs are not just names!</b> The ID may have effects
402+
* on parts of your crate! For example: If the entity represents a
403+
* file which will be copied into the crate, writers must use the
404+
* ID as filename.
372405
*
373406
* @param id the String representing the id.
374407
* @return the generic builder.
@@ -486,11 +519,11 @@ public T addProperty(String key, boolean value) {
486519
* @return the generic builder
487520
*/
488521
public T addIdProperty(String name, String id) {
489-
JsonNode jsonNode = AbstractEntity.addToIdProperty(name, id, this.properties.get(name));
490-
if (jsonNode != null) {
491-
this.properties.set(name, jsonNode);
492-
this.relatedItems.add(id);
493-
}
522+
AbstractEntity.mergeIdIntoValue(id, this.properties.get(name))
523+
.ifPresent(newValue -> {
524+
this.properties.set(name, newValue);
525+
this.relatedItems.add(id);
526+
});
494527
return self();
495528
}
496529

@@ -526,20 +559,62 @@ public T addIdFromCollectionOfEntities(String name, Collection<AbstractEntity> e
526559
}
527560

528561
/**
529-
* This sets everything from a json object to the property. Can be
530-
* useful when the entity is already available somewhere.
562+
* Deprecated. Equivalent to {@link #setAllIfValid(ObjectNode)}.
531563
*
532564
* @param properties the Json representing all the properties.
533-
* @return the generic builder.
565+
* @return the generic builder, either including all given properties
566+
* * or unchanged.
567+
*
568+
* @deprecated To enforce the user know what this method does,
569+
* we want the user to use one of the more explicitly named
570+
* methods {@link #setAllIfValid(ObjectNode)} or
571+
* {@link #setAllIfValid(ObjectNode)}.
572+
* @see #setAllIfValid(ObjectNode)
534573
*/
574+
@Deprecated(since = "2.1.0", forRemoval = true)
535575
public T setAll(ObjectNode properties) {
576+
return setAllIfValid(properties);
577+
}
578+
579+
/**
580+
* This sets everything from a json object to the property,
581+
* <b>if the result is valid</b>. Otherwise, it will do <b>nothing</b>.
582+
* <p>
583+
* Valid means here that the json object needs to be flat as specified
584+
* in the RO-Crate specification. In principle, this means that
585+
* primitives and objects referencing an ID are allowed,
586+
* as well as arrays of these.
587+
*
588+
* @param properties the Json representing all the properties.
589+
* @return the generic builder, either including all given properties
590+
* or unchanged.
591+
*/
592+
public T setAllIfValid(ObjectNode properties) {
536593
if (AbstractEntity.entityValidation.entityValidation(properties)) {
537594
this.properties = properties;
538595
this.relatedItems.addAll(JsonUtilFunctions.getIdPropertiesFromJsonNode(properties));
539596
}
540597
return self();
541598
}
542599

600+
/**
601+
* This sets everything from a json object to the property. Can be
602+
* useful when the entity is already available somewhere.
603+
* <p>
604+
* Errors on validation are printed, but everything will be added.
605+
* For more about validation, see {@link #setAllIfValid(ObjectNode)}.
606+
*
607+
* @param properties the Json representing all the properties.
608+
* @return the generic builder with all properties added.
609+
*/
610+
public T setAllUnsafe(ObjectNode properties) {
611+
// This will currently only print errors.
612+
AbstractEntity.entityValidation.entityValidation(properties);
613+
this.properties = properties;
614+
this.relatedItems.addAll(JsonUtilFunctions.getIdPropertiesFromJsonNode(properties));
615+
return self();
616+
}
617+
543618
public abstract T self();
544619

545620
public abstract AbstractEntity build();

src/main/java/edu/kit/datamanager/ro_crate/entities/contextual/JsonDescriptor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
public class JsonDescriptor extends ContextualEntity {
1515

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

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

4040
/**
4141
* Builder for the JsonDescriptor.
42-
*
42+
* <p>
4343
* Defaults to the latest stable crate version and no other conformsTo values.
4444
*/
4545
public static final class Builder {

0 commit comments

Comments
 (0)