Skip to content

Commit 51610ff

Browse files
committed
Added streamReader, fixed an issue with zipReader adding crate metadata as plain content, set CustomPreview as default preview in builder, updated README
1 parent 3098d13 commit 51610ff

8 files changed

Lines changed: 788 additions & 304 deletions

File tree

README.md

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,24 @@ PersonEntity person = ORCIDProvider.getPerson("https://orcid.org/*")
117117
OrganizationEntity organization = RORProvider.getOrganization("https://ror.org/*");
118118
```
119119

120-
### Writing Crate to folder or zip file
120+
### Writing Crate to folder, zip file, or zip stream
121121

122122
Writing to folder:
123123
```java
124124
RoCrateWriter folderRoCrateWriter = new RoCrateWriter(new FolderWriter());
125-
folderRoCrateWriter.save(roCrate, "destination");
125+
folderRoCrateWriter.save(roCrate, "destinationFolder");
126126
```
127127

128128
Writing to zip file:
129129
```java
130130
RoCrateWriter roCrateZipWriter = new RoCrateWriter(new ZipWriter());
131-
roCrateZipWriter.save(roCrate, "destination");
131+
roCrateZipWriter.save(roCrate, "destinationFolder");
132+
```
133+
134+
Writing to zip stream:
135+
```java
136+
RoCrateWriter roCrateZipStreamWriter = new RoCrateWriter(new ZipStreamWriter());
137+
roCrateZipStreamWriter.save(roCrate, outputStream);
132138
```
133139

134140
More writing strategies can be implemented, if required.
@@ -138,25 +144,48 @@ More writing strategies can be implemented, if required.
138144
Reading from folder:
139145
```java
140146
RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader());
141-
RoCrate res = roCrateFolderReader.readCrate("source");
147+
RoCrate res = roCrateFolderReader.readCrate("destinationFolder");
142148
```
143149

144150
Reading from zip file:
145151
```java
146152
RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipReader());
147-
RoCrate crate = roCrateFolderReader.readCrate("source");
153+
RoCrate crate = roCrateFolderReader.readCrate("sourceZipFile");
154+
```
155+
156+
Reading from zip stream:
157+
```java
158+
RoCrateReader roCrateFolderReader = new RoCrateReader(new ZipStreamReader());
159+
RoCrate crate = roCrateFolderReader.readCrate(inputStream);
148160
```
149161

150162
### RO-Crate Website (HTML preview file)
151-
By setting the preview to an `AutomaticPreview`, the library will automatically create a preview using the [ro-crate-html-js](https://www.npmjs.com/package/ro-crate-html-js) tool.
152-
It has to be installed using `npm install --global ro-crate-html-js` in order to use it.
153-
If you want to use a custom-made preview, you can set it using the `CustomPreview` class. `AutomaticPreview` is currently **not** set by default.
163+
ro-crate-java offers tree different kinds of previews:
164+
165+
* AutomaticPreview: Uses third-party library [ro-crate-html-js](https://www.npmjs.com/package/ro-crate-html-js), which must be installed separately.
166+
* CustomPreview: Pure Java-based preview using an included template processed by the FreeMarker template engine. At the same time, CustomPreview is the fallback for AutomaticPreview if ro-crate-html-js is not installed.
167+
* StaticPreview: Allows to provide a static HTML page (including additional dependencies, e.g., CSS, JS) which is then shipped with the RO-Crate.
168+
169+
When creating a new RO-Crate using the builder, the default setting is to use CustomPreview. If you want to change this behaviour, thr preview method is set as follows:
170+
154171
```java
155172
RoCrate roCrate = new RoCrateBuilder("name", "description", "datePublished", "licenseIdentifier")
156173
.setPreview(new AutomaticPreview())
157174
.build();
158175
```
159176

177+
Keep in mind that, if you want to use AutomaticPreview, you have to install ro-crate-html-js via `npm install --global ro-crate-html-js` first.
178+
179+
For StaticPreview, the constuctor is a bit different, such that it looks as follows:
180+
181+
```java
182+
File pathToMainPreviewHtml = new File("localPath");
183+
File pathToAdditionalFiles = new File("localFolder");
184+
RoCrate roCrate = new RoCrateBuilder("name", "description", "datePublished", "licenseIdentifier")
185+
.setPreview(new StaticPreview(pathToMainPreviewHtml, pathToAdditionalFiles)
186+
.build();
187+
```
188+
160189
### RO-Crate validation (machine-readable crate profiles)
161190
Right now, the only implemented way of validating a RO-crate is to use a [JSON-Schema](https://json-schema.org/) that the crates metadata JSON file should match. JSON-Schema is an established standard and therefore a good choice for a crate profile. Example:
162191

@@ -395,8 +424,6 @@ The web resource does not use `.setSource()`, but uses the ID to indicate the fi
395424
{"@id": "data2.txt"}
396425
]
397426
},
398-
399-
400427
{
401428
"@id": "data1.txt",
402429
"@type": "File",
@@ -637,7 +664,6 @@ If there is no special method for including relative entities (ID properties) on
637664
.addIdProperty("additionalType", nucSec)
638665
.addIdProperty("encodingFormat", fasta)
639666
.build();
640-
641667
ContextualEntity clnParam = new ContextualEntity.ContextualEntityBuilder()
642668
.addType("FormalParameter")
643669
.setId("#6c703fee-6af7-4fdb-a57d-9e8bc4486044")
@@ -646,7 +672,6 @@ If there is no special method for including relative entities (ID properties) on
646672
.addIdProperty("additionalType", nucSec)
647673
.addIdProperty("encodingFormat", ban)
648674
.build();
649-
650675
ContextualEntity alignParam = new ContextualEntity.ContextualEntityBuilder()
651676
.addType("FormalParameter")
652677
.setId("#2f32b861-e43c-401f-8c42-04fd84273bdf")

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import edu.kit.datamanager.ro_crate.payload.CratePayload;
1818
import edu.kit.datamanager.ro_crate.payload.RoCratePayload;
1919
import edu.kit.datamanager.ro_crate.preview.CratePreview;
20+
import edu.kit.datamanager.ro_crate.preview.CustomPreview;
2021
import edu.kit.datamanager.ro_crate.special.CrateVersion;
2122
import edu.kit.datamanager.ro_crate.special.JsonUtilFunctions;
2223
import edu.kit.datamanager.ro_crate.validation.JsonSchemaValidation;
@@ -251,7 +252,7 @@ public static class RoCrateBuilder {
251252
private static final String PROPERTY_DESCRIPTION = "description";
252253

253254
CratePayload payload;
254-
CratePreview preview;
255+
CratePreview preview = new CustomPreview();
255256
CrateMetadataContext metadataContext;
256257
ContextualEntity license;
257258
RootDataEntity rootDataEntity;

src/main/java/edu/kit/datamanager/ro_crate/preview/CustomPreview.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import edu.kit.datamanager.ro_crate.preview.model.ROCratePreviewModel;
66
import edu.kit.datamanager.ro_crate.util.ZipUtil;
7+
import edu.kit.datamanager.ro_crate.writer.RoCrateWriter;
8+
import freemarker.core.ParseException;
79
import freemarker.template.Configuration;
10+
import freemarker.template.MalformedTemplateNameException;
811
import freemarker.template.Template;
912
import freemarker.template.TemplateException;
1013
import freemarker.template.TemplateExceptionHandler;
14+
import freemarker.template.TemplateNotFoundException;
1115
import java.io.File;
1216
import java.io.FileOutputStream;
1317
import java.io.FileWriter;
@@ -24,6 +28,8 @@
2428
import net.lingala.zip4j.exception.ZipException;
2529
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
2630
import org.apache.commons.io.FileUtils;
31+
import org.slf4j.Logger;
32+
import org.slf4j.LoggerFactory;
2733

2834
/**
2935
* This class generates a custom preview without requiring external
@@ -34,17 +40,24 @@
3440
*/
3541
public class CustomPreview implements CratePreview {
3642

43+
private final static Logger logger = LoggerFactory.getLogger(CustomPreview.class);
44+
3745
private final Configuration cfg;
46+
private Template template = null;
3847

3948
public CustomPreview() {
4049
cfg = new Configuration(Configuration.VERSION_2_3_34);
4150
cfg.setClassForTemplateLoading(CustomPreview.class, "/");
4251
cfg.setDefaultEncoding("UTF-8");
4352
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
44-
53+
try {
54+
template = cfg.getTemplate("templates/custom_preview.ftl");
55+
} catch (IOException ex) {
56+
logger.error("Failed to read template for CustomPreview.", ex);
57+
}
4558
}
4659

47-
public ROCratePreviewModel mapFromJson(String metadata) throws IOException {
60+
private ROCratePreviewModel mapFromJson(String metadata) throws IOException {
4861
ObjectMapper mapper = new ObjectMapper();
4962
JsonNode root = (JsonNode) mapper.readValue(metadata, JsonNode.class);
5063
JsonNode graph = root.get("@graph");
@@ -126,6 +139,9 @@ public ROCratePreviewModel mapFromJson(String metadata) throws IOException {
126139

127140
@Override
128141
public void saveAllToZip(ZipFile zipFile) throws IOException {
142+
if (template == null) {
143+
throw new IOException("Preview template did not load. Unable to proceed.");
144+
}
129145
if (zipFile == null) {
130146
throw new IOException("Argument zipFile must not be null.");
131147
}
@@ -139,9 +155,9 @@ public void saveAllToZip(ZipFile zipFile) throws IOException {
139155
try {
140156
Map<String, Object> dataModel = new HashMap<>();
141157
dataModel.put("crateModel", mapFromJson(metadata));
142-
Template temp = cfg.getTemplate("templates/custom_preview.ftl");
158+
143159
try (Writer out = new OutputStreamWriter(new FileOutputStream("temp/ro-crate-preview.html"))) {
144-
temp.process(dataModel, out);
160+
template.process(dataModel, out);
145161
out.flush();
146162
}
147163
zipFile.addFile("temp/ro-crate-preview.html");
@@ -158,16 +174,18 @@ public void saveAllToZip(ZipFile zipFile) throws IOException {
158174

159175
@Override
160176
public void saveAllToFolder(File folder) throws IOException {
177+
if (template == null) {
178+
throw new IOException("Preview template did not load. Unable to proceed.");
179+
}
161180
if (folder == null || !folder.exists()) {
162181
throw new IOException("Preview target folder " + folder + " does not exist.");
163182
}
164183
String metadata = FileUtils.readFileToString(new File(folder, "ro-crate-metadata.json"), "UTF-8");
165184
try {
166185
Map<String, Object> dataModel = new HashMap<>();
167186
dataModel.put("crateModel", mapFromJson(metadata));
168-
Template temp = cfg.getTemplate("templates/custom_preview.ftl");
169187
try (Writer out = new OutputStreamWriter(new FileOutputStream(new File(folder, "ro-crate-preview.html")))) {
170-
temp.process(dataModel, out);
188+
template.process(dataModel, out);
171189
out.flush();
172190
}
173191
} catch (TemplateException ex) {
@@ -177,6 +195,9 @@ public void saveAllToFolder(File folder) throws IOException {
177195

178196
@Override
179197
public void saveAllToStream(String metadata, ZipOutputStream stream) throws IOException {
198+
if (template == null) {
199+
throw new IOException("Preview template did not load. Unable to proceed.");
200+
}
180201
try {
181202
//prepare metadata for template
182203
Map<String, Object> dataModel = new HashMap<>();
@@ -187,8 +208,7 @@ public void saveAllToStream(String metadata, ZipOutputStream stream) throws IOEx
187208
//load and process template
188209
try (FileWriter writer = new FileWriter(new File("temp/ro-crate-preview.html"))) {
189210
//load and process template
190-
Template temp = cfg.getTemplate("templates/custom_preview.frm");
191-
temp.process(dataModel, writer);
211+
template.process(dataModel, writer);
192212
writer.flush();
193213
}
194214

0 commit comments

Comments
 (0)