TurtleWriterTest.java
/*******************************************************************************
* Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.rio.turtle;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.StringReader;
import java.io.StringWriter;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.impl.DynamicModelFactory;
import org.eclipse.rdf4j.model.util.Models;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.Rio;
import org.eclipse.rdf4j.rio.WriterConfig;
import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings;
import org.eclipse.rdf4j.rio.helpers.TurtleWriterSettings;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/**
* @author Arjohn Kampman
*/
public class TurtleWriterTest extends AbstractTurtleWriterTest {
private final IRI uri1;
private final IRI uri2;
private final String exNs;
public TurtleWriterTest() {
super(new TurtleWriterFactory(), new TurtleParserFactory());
exNs = "http://example.org/";
uri1 = vf.createIRI(exNs, "uri1");
uri2 = vf.createIRI(exNs, "uri2");
}
@Override
protected void setupWriterConfig(WriterConfig config) {
config.set(BasicWriterSettings.PRETTY_PRINT, false);
}
@Test
public void testBlankNodeInlining1() throws Exception {
Model expected = Rio.parse(
new StringReader(
String.join("\n", "",
"@prefix ex: <http://example.com/ns#> .",
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .",
"@prefix sh: <http://www.w3.org/ns/shacl#> .",
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .",
"",
"_:bn1 a sh:ValidationReport;",
" sh:result _:bn2 .",
"",
"_:bn2 a sh:ValidationResult;",
" sh:detail _:bn3 .",
"",
"_:bn3 a sh:ValidationResult;",
" sh:sourceShape _:bn4 .",
"",
"_:bn4 a sh:NodeShape;",
" sh:datatype xsd:string .",
"",
"_:bn3 sh:value \"123\" .",
"",
"_:bn2 sh:focusNode ex:validPerson1;",
" sh:sourceShape _:bn5 .",
"",
"_:bn5 a sh:PropertyShape;",
" sh:not _:bn4;",
" sh:path ex:age .",
"",
"_:bn2 sh:value \"123\" ."
)
), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBlankNodeInlining2() throws Exception {
Model expected = Rio.parse(
new StringReader(
String.join("\n", "",
"_:b1 <http://www.w3.org/ns/shacl#focusNode> <http://example.com/ns#validPerson1>, _:b3;",
" <http://www.w3.org/ns/shacl#value> _:b3;",
" <http://www.w3.org/ns/shacl#sourceShape> [ a <http://www.w3.org/ns/shacl#PropertyShape>; a [ a [] ] ] .",
"[] a [a []]."
)
), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
/**
* Test that blank node subjects are processed in correct order even when not supplied in order.
*/
@Test
public void testBlanknodeInlining_SubjectOrder() throws Exception {
String data = "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"@prefix rep: <http://www.openrdf.org/config/repository#> .\n" +
"@prefix sr: <http://www.openrdf.org/config/repository/sail#> .\n" +
"@prefix sail: <http://www.openrdf.org/config/sail#> .\n" +
"@prefix sb: <http://www.openrdf.org/config/sail/base#> .\n" +
"@prefix ms: <http://www.openrdf.org/config/sail/memory#> .\n" +
"\n" +
"_:node1eemcmeprx2 rep:repositoryType \"openrdf:SailRepository\";\n" +
" sr:sailImpl _:node1eemcmeprx3 .\n" +
"\n" +
"_:node1eemcmeprx1 a rep:Repository;\n" +
" rep:repositoryID \"test-strict\";\n" +
" rep:repositoryImpl _:node1eemcmeprx2 .\n" +
"\n" +
"_:node1eemcmeprx3 sail:sailType \"openrdf:MemoryStore\";\n" +
" sb:evaluationStrategyFactory \"org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategyFactory\" .\n";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
// System.out.println(stringWriter.toString());
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testNoBuffering() throws Exception {
String data = "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"@prefix rep: <http://www.openrdf.org/config/repository#> .\n" +
"@prefix sr: <http://www.openrdf.org/config/repository/sail#> .\n" +
"@prefix sail: <http://www.openrdf.org/config/sail#> .\n" +
"@prefix sb: <http://www.openrdf.org/config/sail/base#> .\n" +
"@prefix ms: <http://www.openrdf.org/config/sail/memory#> .\n" +
"\n" +
"_:node1eemcmeprx2 rep:repositoryType \"openrdf:SailRepository\";\n" +
" sr:sailImpl _:node1eemcmeprx3 .\n" +
"\n" +
"_:node1eemcmeprx1 a rep:Repository;\n" +
" rep:repositoryID \"test-strict\";\n" +
" rep:repositoryImpl _:node1eemcmeprx2 .\n" +
"\n" +
"_:node1eemcmeprx3 sail:sailType \"openrdf:MemoryStore\";\n" +
" sb:evaluationStrategyFactory \"org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategyFactory\" .\n";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, false);
config.set(BasicWriterSettings.PRETTY_PRINT, false);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testUnusualIrisAndPrefixesParseWriteCompare() throws Exception {
String data = "@prefix server-news: <news:comp.infosystems.www.servers.> .\n" +
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" +
"server-news:unix rdfs:label \"News on Unix\" .\n" +
"server-news:windows rdfs:label \"News on Windows\" .\n";
var expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
var stringWriter = new StringWriter();
var config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, false);
config.set(BasicWriterSettings.PRETTY_PRINT, false);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
var actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertThat(Models.isomorphic(expected, actual)).as("isomorphic").isTrue();
// Requires https://github.com/eclipse-rdf4j/rdf4j/issues/4929 to be fixed
// assertThat(stringWriter.toString()).isEqualTo(data);
}
@Test
public void testUnusualIrisAndPrefixesWriteParserWriteCompare() throws Exception {
var prefix = "server-news";
var ns = "news:comp.infosystems.www.servers.";
var config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, false);
config.set(BasicWriterSettings.PRETTY_PRINT, false);
var expectedModel = new DynamicModelFactory().createEmptyModel();
expectedModel.setNamespace(prefix, ns);
expectedModel.setNamespace(RDFS.PREFIX, RDFS.NAMESPACE);
expectedModel.add(vf.createIRI(ns, "unix"), RDFS.LABEL, vf.createLiteral("News on Unix"));
expectedModel.add(vf.createIRI(ns, "windows"), RDFS.LABEL, vf.createLiteral("News on Windows"));
var turtle1 = new StringWriter();
Rio.write(expectedModel, turtle1, RDFFormat.TURTLE, config);
var actualModel = Rio.parse(new StringReader(turtle1.toString()), "", RDFFormat.TURTLE);
assertThat(Models.isomorphic(expectedModel, actualModel)).as("isomorphic").isTrue();
var turtle2 = new StringWriter();
Rio.write(actualModel, turtle2, RDFFormat.TURTLE, config);
// Requires https://github.com/eclipse-rdf4j/rdf4j/issues/4929 to be fixed
// assertThat(turtle2.toString()).isEqualTo(turtle1.toString());
}
@Test
@Disabled
public void anotherBnodeTest() throws Exception {
String data = "@prefix ex: <http://example.com/ns#> .\n" +
"@prefix sh: <http://www.w3.org/ns/shacl#> .\n" +
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" +
"@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n" +
"\n" +
"_:b0 a sh:PropertyShape ;\n" +
" sh:not [ a sh:NodeShape ;\n" +
" sh:and [ rdf:first [ a sh:NodeShape ;\n" +
" sh:in ( ex:steve )\n" +
" ] ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" ) ;\n" +
" rdf:rest ( _:b1\n" +
" )\n" +
" ]\n" +
" ] ;\n" +
" sh:path ex:knows .\n" +
"\n" +
"_:b1 a sh:NodeShape ;\n" +
" sh:in [ rdf:first ex:pete ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve ) ;\n" +
" rdf:rest ( ex:steve )\n" +
" ] .\n" +
"\n" +
"[ a sh:ValidationReport ;\n" +
" <http://rdf4j.org/schema/rdf4j#truncated>\n" +
" false ;\n" +
" sh:conforms false ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ] ;\n" +
" sh:result [ a sh:ValidationResult ;\n" +
" sh:focusNode ex:validPerson1 ;\n" +
" sh:resultPath ex:knows ;\n" +
" sh:resultSeverity sh:Violation ;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent ;\n" +
" sh:sourceShape _:b0 ;\n" +
" sh:value ex:steve\n" +
" ]\n" +
"] .\n";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBNodeValuesInList() throws Exception {
String data = "" +
"@prefix ex: <http://example.com/ns#> .\n" +
"\n" +
"ex:a ex:list (_:b0 _:b0) .";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBNodeValuesInList2() throws Exception {
String data = "" +
"@prefix ex: <http://example.com/ns#> .\n" +
"\n" +
"ex:a ex:list (_:b0 _:b1) .";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBNodeValuesInList3() throws Exception {
String data = "" +
"@prefix ex: <http://example.com/ns#> .\n" +
"\n" +
"ex:a ex:list (_:b0 _:b1) .\n" +
"_:b1 ex:foo ex:bar.\n";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testInvalidList_nonListPredicate() throws Exception {
String data = "@prefix ex: <http://example.com/ns#> .\n" +
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" +
"\n" +
"ex:ex1 ex:list [ rdf:first [ ] ;\n" +
" rdf:rest rdf:nil ;\n" +
" ex:abc ex:def\n" +
" ]\n" +
" .\n" +
"";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testInvalidList_multipleRdfRestPredicates() throws Exception {
String data = "@prefix ex: <http://example.com/ns#> .\n" +
"@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"@prefix sh: <http://www.w3.org/ns/shacl#> .\n" +
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" +
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" +
"\n" +
"_:node1ei5i7ns4x11752 a sh:ValidationReport;\n" +
" sh:conforms false;\n" +
" <http://rdf4j.org/schema/rdf4j#truncated> false;\n" +
" sh:result _:5f9908e9-caee-4059-aa52-69227a27ac20, _:3a37be3d-7af5-4b74-b7cf-b6358196bf0e,\n" +
" _:ba3bb72d-eb40-4aec-987a-bf2a3d925f06, _:6c86bbd3-a6ea-4b4f-8881-d479cff3aff5, _:ff167b12-c1b4-4341-bf63-187bed54e1ed,\n"
+
" _:c3c6878c-7a69-41c8-b65b-50ab02da9519, _:f07f8ae4-1137-454c-ac6a-f385631b592e, _:a7b959ba-a7b4-4922-9974-9f363fdaccdf .\n"
+
"\n" +
"_:5f9908e9-caee-4059-aa52-69227a27ac20 a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7sdex1 a sh:PropertyShape;\n" +
" sh:path ex:knows;\n" +
" sh:not _:node1ei5i7sdex2 .\n" +
"\n" +
"_:node1ei5i7sdex2 a sh:NodeShape;\n" +
" sh:and _:node1ei5i7sdex3 .\n" +
"\n" +
"_:node1ei5i7sdex3 rdf:first _:node1ei5i7sdex4;\n" +
" rdf:rest _:node1ei5i7ns4x11754, _:node1ei5i7ns4x11756, _:node1ei5i7ns4x11758, _:node1ei5i7ns4x11760,\n"
+
" _:node1ei5i7ns4x11763, _:node1ei5i7ns4x11765, _:node1ei5i7ns4x11767, _:node1ei5i7ns4x11769 .\n" +
"\n" +
"_:node1ei5i7ns4x11754 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7sdex4 a sh:NodeShape;\n" +
" sh:in _:node1ei5i7sdex5 .\n" +
"\n" +
"_:node1ei5i7sdex5 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7sdex7 a sh:NodeShape;\n" +
" sh:in _:node1ei5i7sdex8 .\n" +
"\n" +
"_:node1ei5i7sdex8 rdf:first ex:pete;\n" +
" rdf:rest _:node1ei5i7ns4x11755, _:node1ei5i7ns4x11757, _:node1ei5i7ns4x11759, _:node1ei5i7ns4x11761,\n"
+
" _:node1ei5i7ns4x11764, _:node1ei5i7ns4x11766, _:node1ei5i7ns4x11768, _:node1ei5i7ns4x11770 .\n" +
"\n" +
"_:node1ei5i7ns4x11755 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:3a37be3d-7af5-4b74-b7cf-b6358196bf0e a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11756 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11757 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:ba3bb72d-eb40-4aec-987a-bf2a3d925f06 a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11758 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11759 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:6c86bbd3-a6ea-4b4f-8881-d479cff3aff5 a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11760 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11761 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:ff167b12-c1b4-4341-bf63-187bed54e1ed a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11763 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11764 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:c3c6878c-7a69-41c8-b65b-50ab02da9519 a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11765 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11766 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:f07f8ae4-1137-454c-ac6a-f385631b592e a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11767 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11768 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:a7b959ba-a7b4-4922-9974-9f363fdaccdf a sh:ValidationResult;\n" +
" sh:focusNode ex:validPerson1;\n" +
" sh:value ex:steve;\n" +
" sh:resultPath ex:knows;\n" +
" sh:sourceConstraintComponent sh:NotConstraintComponent;\n" +
" sh:resultSeverity sh:Violation;\n" +
" sh:sourceShape _:node1ei5i7sdex1 .\n" +
"\n" +
"_:node1ei5i7ns4x11769 rdf:first _:node1ei5i7sdex7;\n" +
" rdf:rest rdf:nil .\n" +
"\n" +
"_:node1ei5i7ns4x11770 rdf:first ex:steve;\n" +
" rdf:rest rdf:nil .\n";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBlankNodeInlining_directCircularReference() throws Exception {
String data = "@prefix dc: <http://purl.org/dc/terms/> .\n" +
"@prefix ns0: <http://www.w3.org/ns/earl#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"\n" +
"<http://example.org/DISPLAY_NAME>\n" +
" a <http://www.w3.org/ns/earl#TestCriterion> ;\n" +
" dc:hasPart _:genid3 .\n" +
"\n" +
"_:genid3\n" +
" a ns0:TestCase ;\n" +
" ns0:assertions [\n" +
" a ns0:Assertion ;\n" +
" ns0:test _:genid3 \n" + // direct circular reference between two blank nodes
" ] .";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
// System.out.println("### EXPECTED ###");
// System.out.println(data);
// System.out.println("#################\n");
//
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
// System.out.println("### ACTUAL ###");
// System.out.println(stringWriter.toString());
// System.out.println("#################\n");
//
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBlankNodeInlining_indirectCircularReference() throws Exception {
String data = "@prefix dc: <http://purl.org/dc/terms/> .\n" +
"@prefix ns0: <http://www.w3.org/ns/earl#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"\n" +
"<http://example.org/DISPLAY_NAME>\n" +
" a <http://www.w3.org/ns/earl#TestCriterion> ;\n" +
" dc:hasPart _:genid3 .\n" +
"\n" +
"_:genid3\n" +
" a ns0:TestCase ;\n" +
" ns0:assertions [\n" +
" a ns0:Assertion ;\n" +
" ns0:test [ ns0:reference _:genid3 ] \n" + // indirect blank node cycle
" ] .";
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
// System.out.println("### EXPECTED ###");
// System.out.println(data);
// System.out.println("#################\n");
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
// System.out.println("### ACTUAL ###");
// System.out.println(stringWriter.toString());
// System.out.println("#################\n");
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testBlankNodeInlining_indirectCircularReferenceWithIRI() throws Exception {
String data = "@prefix dc: <http://purl.org/dc/terms/> .\n" +
"@prefix ns0: <http://www.w3.org/ns/earl#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" +
"\n" +
"<http://example.org/DISPLAY_NAME>\n" +
" a <http://www.w3.org/ns/earl#TestCriterion> ;\n" +
" dc:hasPart _:genid3 .\n" +
"\n" +
"_:genid3\n" +
" a ns0:TestCase ;\n" +
" ns0:assertions [\n" +
" a ns0:Assertion ;\n" +
" ns0:test ns0:testSubject \n" +
" ] ." +
" ns0:testSubject ns0:reference _:genid3 ."; // blank node cycle broken with an IRI subject
Model expected = Rio.parse(new StringReader(data), "", RDFFormat.TURTLE);
// System.out.println("### EXPECTED ###");
// System.out.println(data);
// System.out.println("#################\n");
StringWriter stringWriter = new StringWriter();
WriterConfig config = new WriterConfig();
config.set(BasicWriterSettings.INLINE_BLANK_NODES, true);
Rio.write(expected, stringWriter, RDFFormat.TURTLE, config);
// System.out.println("### ACTUAL ###");
// System.out.println(stringWriter.toString());
// System.out.println("#################\n");
//
Model actual = Rio.parse(new StringReader(stringWriter.toString()), "", RDFFormat.TURTLE);
assertTrue(Models.isomorphic(expected, actual));
}
@Test
public void testIriNamespace() {
Model model = new DynamicModelFactory().createEmptyModel();
String prefix = "foo-bar";
String ns = "foo:this.is.my.bar.";
model.setNamespace(prefix, ns);
model.add(vf.createIRI(ns, "lala"), vf.createIRI(ns, "lulu"), vf.createIRI(ns, "lolo"));
StringWriter stringWriter = new StringWriter();
Rio.write(model, stringWriter, RDFFormat.TURTLE);
assertThat(stringWriter.toString()).contains("foo-bar:lala foo-bar:lulu foo-bar:lolo .");
}
@Test
public void testIgnoreAbbreviateNumbers() {
StringWriter sw = new StringWriter();
WriterConfig config = new WriterConfig();
// abbreviate numbers should be ignored when pretty print is false
config.set(BasicWriterSettings.PRETTY_PRINT, false)
.set(TurtleWriterSettings.ABBREVIATE_NUMBERS, true);
Rio.write(getAbbrevTestModel(), sw, RDFFormat.TURTLE, config);
String result = sw.toString();
assertTrue(result.contains("\"1234567.89\"^^<http://www.w3.org/2001/XMLSchema#double>"));
assertTrue(result.contains("\"-2\"^^<http://www.w3.org/2001/XMLSchema#integer>"));
assertTrue(result.contains("\"55.66\"^^<http://www.w3.org/2001/XMLSchema#decimal>"));
}
}