Skip to content

Commit

Permalink
Feat/binary model representation (#441)
Browse files Browse the repository at this point in the history
  • Loading branch information
jobulcke authored Dec 27, 2023
1 parent 636d3a7 commit 9bbd659
Show file tree
Hide file tree
Showing 26 changed files with 302 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.util.List;

public class StartingTreeNodeFinder {
Expand Down Expand Up @@ -38,8 +39,8 @@ public StartingTreeNode determineStartingTreeNode(final StartingNodeRequest star
return selectStartingNode(startingNodeRequest, model);
}

private Model getModelFromResponse(Lang lang, String response, String baseUrl) {
return RDFParser.fromString(response).lang(lang).base(baseUrl).build().toModel();
private Model getModelFromResponse(Lang lang, byte[] responseBody, String baseUrl) {
return RDFParser.source(new ByteArrayInputStream(responseBody)).lang(lang).base(baseUrl).build().toModel();
}

private StartingTreeNode selectStartingNode(StartingNodeRequest startingNodeRequest, Model model) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.RDFParser;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.List;

Expand Down Expand Up @@ -41,8 +43,8 @@ public TreeNodeResponse fetchTreeNode(TreeNodeRequest treeNodeRequest) {
}

private TreeNodeResponse createOkResponse(TreeNodeRequest treeNodeRequest, Response response) {
final String responseBody = response.getBody().orElseThrow();
final Model model = RDFParser.fromString(responseBody).forceLang(treeNodeRequest.getLang()).base(treeNodeRequest.getTreeNodeUrl()).toModel();
final InputStream responseBody = response.getBody().map(ByteArrayInputStream::new).orElseThrow();
final Model model = RDFParser.source(responseBody).forceLang(treeNodeRequest.getLang()).base(treeNodeRequest.getTreeNodeUrl()).toModel();
final ModelResponse modelResponse = new ModelResponse(model);
final MutabilityStatus mutabilityStatus = getMutabilityStatus(response);
return new TreeNodeResponse(modelResponse.getRelations(), modelResponse.getMembers(), mutabilityStatus);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.*;

import java.io.OutputStream;

import static be.vlaanderen.informatievlaanderen.ldes.ldi.rdf.formatter.PrefixAdder.*;

public class GenericRdfWriter implements LdiRdfWriter {
private final LdiRdfWriterProperties properties;
private final RDFWriterBuilder rdfWriter;

public GenericRdfWriter(LdiRdfWriterProperties properties) {
this.properties = properties;
this.rdfWriter = RDFWriter.create().lang(properties.getLang());
}

@Override
public String write(Model model) {
return RDFWriter.source(addPrefixesToModel(model)).lang(properties.getLang()).asString();
return rdfWriter.source(addPrefixesToModel(model)).asString();
}

@Override
public void writeToOutputStream(Model model, OutputStream outputStream) {
rdfWriter.source(addPrefixesToModel(model)).output(outputStream);
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
package be.vlaanderen.informatievlaanderen.ldes.ldi.rdf.formatter;

import com.github.jsonldjava.core.JsonLdOptions;
import org.apache.jena.atlas.json.JSON;
import org.apache.jena.atlas.json.JsonObject;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.JsonLDWriteContext;
import org.apache.jena.riot.RDFFormat;
import org.apache.jena.riot.RDFWriter;
import org.apache.jena.riot.RDFWriterBuilder;
import org.apache.jena.riot.writer.JsonLD10Writer;
import org.apache.jena.sparql.util.Context;

import com.github.jsonldjava.core.JsonLdOptions;
import java.io.OutputStream;

import static be.vlaanderen.informatievlaanderen.ldes.ldi.rdf.formatter.PrefixAdder.addPrefixesToModel;

public class JsonLdFrameWriter implements LdiRdfWriter {
private final String frame;
private final RDFWriterBuilder rdfWriter;

public JsonLdFrameWriter(LdiRdfWriterProperties properties) {
this.frame = properties.getJsonLdFrame();
String frame = properties.getJsonLdFrame();
this.rdfWriter = RDFWriter.create().context(getFramedContext(frame)).format(RDFFormat.JSONLD10_FRAME_PRETTY);
}

@Override
public String write(Model model) {
return RDFWriter.source(addPrefixesToModel(model))
.context(getFramedContext(frame))
.format(RDFFormat.JSONLD10_FRAME_PRETTY)
.asString();
return rdfWriter.source(addPrefixesToModel(model)).asString();
}

@Override
public void writeToOutputStream(Model model, OutputStream outputStream) {
rdfWriter.source(addPrefixesToModel(model)).output(outputStream);
}

protected static Context getFramedContext(String context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.RDFFormat;
import org.apache.jena.riot.RDFWriter;
import org.apache.jena.riot.RDFWriterBuilder;

import java.io.OutputStream;

import static be.vlaanderen.informatievlaanderen.ldes.ldi.rdf.formatter.PrefixAdder.addPrefixesToModel;

public class JsonLdPrettyWriter implements LdiRdfWriter {
private final RDFWriterBuilder rdfWriter;

public JsonLdPrettyWriter() {
this.rdfWriter = RDFWriter.create().format(RDFFormat.JSONLD10_PRETTY);
}

@Override
public String write(Model model) {
return RDFWriter.source(addPrefixesToModel(model))
.format(RDFFormat.JSONLD10_PRETTY)
.asString();
return rdfWriter.source(addPrefixesToModel(model)).asString();
}

@Override
public void writeToOutputStream(Model model, OutputStream outputStream) {
rdfWriter.source(addPrefixesToModel(model)).output(outputStream);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.Lang;

import java.io.OutputStream;

import static org.apache.commons.lang3.StringUtils.isBlank;

public interface LdiRdfWriter {
String write(Model model);

void writeToOutputStream(Model model, OutputStream outputStream);

static LdiRdfWriter getRdfWriter(LdiRdfWriterProperties properties) {
if (Lang.JSONLD.equals(properties.getLang())) {
return isBlank(properties.getJsonLdFrame())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package be.vlaanderen.informatievlaanderen.ldes.ldi.rdf.formatter;

import com.github.jsonldjava.core.JsonLdOptions;
import org.apache.jena.atlas.json.JSON;
import org.apache.jena.atlas.json.JsonObject;
import org.apache.jena.rdf.model.Model;
Expand All @@ -8,93 +9,73 @@
import org.apache.jena.riot.RDFParser;
import org.apache.jena.riot.writer.JsonLD10Writer;
import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.Map;
import java.util.Objects;

import com.github.jsonldjava.core.JsonLdOptions;
import java.util.stream.Stream;

import static be.vlaanderen.informatievlaanderen.ldes.ldi.rdf.formatter.LdiRdfWriterProperties.FRAME;
import static org.junit.jupiter.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;

class LdiRdfWriterTest {

@Test
void formatModel_jsonLD() throws IOException, URISyntaxException {
String input = getFileContentString("rdf/formatter/product.jsonld");

Model model = RDFParser.fromString(input)
.lang(Lang.JSONLD)
.toModel();

Model model = RDFParser.source("rdf/formatter/product.jsonld").lang(Lang.JSONLD).toModel();
String frame = getFileContentString("rdf/formatter/product.frame.jsonld");
Model expected = RDFParser.fromString(getFileContentString("rdf/formatter/expected/product.jsonld"))
.lang(Lang.JSONLD).toModel();

Model expected = RDFParser.source("rdf/formatter/expected/product.jsonld").lang(Lang.JSONLD).toModel();
LdiRdfWriterProperties writerProperties = new LdiRdfWriterProperties(Map.of(FRAME, frame));

String output = LdiRdfWriter.getRdfWriter(writerProperties.withLang(Lang.JSONLD)).write(model);

JsonObject outputJson = JSON.parse(output);
Model outputModel = RDFParser.fromString(output).lang(Lang.JSONLD).toModel();

assertFalse(outputJson.hasKey("@graph"));
assertTrue(outputModel.isIsomorphicWith(expected));
assertThat(outputJson.hasKey("@graph")).isFalse();
assertThat(outputModel).matches(expected::isIsomorphicWith);
}

@Test
void formatModel_jsonLD_withoutFrame() throws IOException, URISyntaxException {
String input = getFileContentString("rdf/formatter/product.jsonld");

Model model = RDFParser.fromString(input)
.lang(Lang.JSONLD)
.toModel();

LdiRdfWriterProperties writerProperties = new LdiRdfWriterProperties();

String output = LdiRdfWriter.getRdfWriter(writerProperties.withLang(Lang.JSONLD)).write(model);
void formatModel_jsonLD_withoutFrame() {
Model model = RDFParser.source("rdf/formatter/product.jsonld").lang(Lang.JSONLD).toModel();
LdiRdfWriterProperties writerProperties = new LdiRdfWriterProperties().withLang(Lang.JSONLD);

String output = LdiRdfWriter.getRdfWriter(writerProperties).write(model);
JsonObject outputJson = JSON.parse(output);

assertNotNull(outputJson);
assertThat(outputJson).isNotNull();
}

@Test
void formatModel_turtle() throws IOException, URISyntaxException {
String input = getFileContentString("rdf/formatter/product.jsonld");

Model model = RDFParser.fromString(input)
.lang(Lang.JSONLD)
.toModel();
void formatModel_turtle() {
Model inputModel = RDFParser.source("rdf/formatter/product.jsonld").lang(Lang.JSONLD).toModel();
Model expectedModel = RDFParser.source("rdf/formatter/expected/product.ttl").lang(Lang.TURTLE).toModel();

String output = LdiRdfWriter.getRdfWriter(new LdiRdfWriterProperties().withLang(Lang.TURTLE)).write(model);
String expected = getFileContentString("rdf/formatter/expected/product.ttl");
String output = LdiRdfWriter.getRdfWriter(new LdiRdfWriterProperties().withLang(Lang.TURTLE)).write(inputModel);
Model outputModel = RDFParser.fromString(output).lang(Lang.TURTLE).toModel();

assertTrue(RDFParser.fromString(output)
.lang(Lang.TURTLE)
.toModel()
.isIsomorphicWith(RDFParser.fromString(expected).lang(Lang.TURTLE).toModel()));
assertThat(outputModel).matches(expectedModel::isIsomorphicWith);
}

@Test
void formatModel_nquads() throws IOException, URISyntaxException {
String input = getFileContentString("rdf/formatter/product.jsonld");

Model model = RDFParser.fromString(input)
.lang(Lang.JSONLD)
.toModel();
void formatModel_nquads() {
Model model = RDFParser.source("rdf/formatter/product.jsonld").lang(Lang.JSONLD).toModel();
Model expectedModel = RDFParser.source("rdf/formatter/expected/product.nq").lang(Lang.NQUADS).toModel();

String output = LdiRdfWriter.getRdfWriter(new LdiRdfWriterProperties().withLang(Lang.NQUADS)).write(model);
String expected = getFileContentString("rdf/formatter/expected/product.nq");
Model outputModel = RDFParser.fromString(output).lang(Lang.NQUADS).toModel();

assertTrue(RDFParser.fromString(output)
.lang(Lang.NQUADS)
.toModel()
.isIsomorphicWith(RDFParser.fromString(expected).lang(Lang.NQUADS).toModel()));
assertThat(outputModel).matches(expectedModel::isIsomorphicWith);
}

@Test
Expand All @@ -107,16 +88,39 @@ void getFramedContext() {
""";

JsonLDWriteContext context = (JsonLDWriteContext) JsonLdFrameWriter.getFramedContext(frame);

JsonObject frameObject = JSON.parse((String) context.get(JsonLD10Writer.JSONLD_FRAME));
assertTrue(frameObject.hasKey("@type"));
assertTrue(frameObject.hasKey("@context"));
assertTrue(((JsonLdOptions) context.get(JsonLD10Writer.JSONLD_OPTIONS)).getOmitGraph());

assertThat(frameObject)
.matches(json -> json.hasKey("@type"))
.matches(json -> json.hasKey("@context"));
assertThat(((JsonLdOptions) context.get(JsonLD10Writer.JSONLD_OPTIONS)).getOmitGraph())
.isTrue();
}

@ParameterizedTest
@ArgumentsSource(LangProvider.class)
void test_WritingWithByteArrayStream(Lang outputLang) {
Model model = RDFParser.source("rdf/formatter/product.jsonld").lang(Lang.JSONLD).toModel();
Model expectedModel = RDFParser.source("rdf/formatter/expected/product.nq").lang(Lang.NQUADS).toModel();

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
LdiRdfWriter.getRdfWriter(new LdiRdfWriterProperties().withLang(outputLang)).writeToOutputStream(model, byteArrayOutputStream);
byte[] modelBytes = byteArrayOutputStream.toByteArray();
Model outputModel = RDFParser.source(new ByteArrayInputStream(modelBytes)).lang(outputLang).toModel();

assertThat(outputModel).matches(expectedModel::isIsomorphicWith);
}

private String getFileContentString(String resource) throws URISyntaxException, IOException {
File file = new File(
Objects.requireNonNull(getClass().getClassLoader().getResource(resource)).toURI());
return Files.readString(file.toPath());
}

static class LangProvider implements ArgumentsProvider {
@Override
public Stream<Arguments> provideArguments(ExtensionContext extensionContext) {
return Stream.of(Lang.RDFPROTO, Lang.RDFTHRIFT, Lang.TURTLE).map(Arguments::of);
}
}
}
4 changes: 4 additions & 0 deletions ldi-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
</dependency>

<!-- Test -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public EdcRequestExecutor(RequestExecutor requestExecutor, TokenService tokenSer
public Response execute(Request request) {
final Request edcRequest = createEdcRequest(request);
var response = requestExecutor.execute(edcRequest);
if (response.isFobidden()) {
if (response.isForbidden()) {
tokenService.invalidateToken();
return execute(request);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

import java.nio.charset.StandardCharsets;

Expand All @@ -34,7 +34,7 @@ private HttpRequestBase createRequest() {
final PostRequest postRequest = (PostRequest) request;
final ContentType contentType = ContentType.create(postRequest.getContentType(),
StandardCharsets.UTF_8);
post.setEntity(new StringEntity(postRequest.getBody(), contentType));
post.setEntity(new ByteArrayEntity(postRequest.getBody(), contentType));
yield post;
}
default -> throw new IllegalStateException("Http method not supported: " + request.getMethod());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public DefaultResponse(Request request, HttpResponse httpResponse) {
public Response getResponse() throws IOException {
final List<Header> headers = Arrays.stream(httpResponse.getAllHeaders()).toList();
final int statusCode = httpResponse.getStatusLine().getStatusCode();
final String body = httpResponse.getEntity() != null ? EntityUtils.toString(httpResponse.getEntity()) : null;
final byte[] body = httpResponse.getEntity() != null ? EntityUtils.toByteArray(httpResponse.getEntity()) : null;
return new Response(request, headers, statusCode, body);
}

Expand Down
Loading

0 comments on commit 9bbd659

Please sign in to comment.