You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2023/12/23 12:40:41 UTC
(jena) 02/02: GH-2083: Convert default graph quads to triples when writing triples syntax.
This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
commit f8a677f2c3d10564673e8aad683609a2b79f495e
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Fri Dec 22 14:01:37 2023 +0000
GH-2083: Convert default graph quads to triples when writing triples syntax.
---
.../java/org/apache/jena/riot/out/NodeFmtLib.java | 6 +++
.../apache/jena/riot/system/StreamRDFWrapper.java | 3 +-
.../apache/jena/riot/system/StreamRDFWriter.java | 10 +++++
.../apache/jena/riot/system/StreamTriplesOnly.java | 44 ++++++++++++++++++----
.../jena/riot/writer/WriterStreamRDFBase.java | 1 -
jena-cmds/src/main/java/riotcmd/CmdLangParse.java | 13 ++++---
6 files changed, 61 insertions(+), 16 deletions(-)
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java b/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java
index 5064fa2e32..60bc9abbdf 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java
@@ -164,6 +164,12 @@ public class NodeFmtLib
return displayStrNodes(t.getSubject(), t.getPredicate(), t.getObject());
}
+ public static String displayStr(Quad q) {
+ if ( q == null )
+ return nullStr;
+ return displayStrNodes(q.getGraph(), q.getSubject(), q.getPredicate(), q.getObject());
+ }
+
public static String displayStr(Node node) {
if ( node == null )
return nullStr;
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWrapper.java b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWrapper.java
index ced0853038..e1c68c8984 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWrapper.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWrapper.java
@@ -28,9 +28,10 @@ import org.apache.jena.sparql.core.Quad ;
public class StreamRDFWrapper implements StreamRDF
{
protected final StreamRDF other ;
+ public final StreamRDF get() { return other; }
public StreamRDFWrapper(StreamRDF other) { this.other = other ; }
-
+
@Override
public void start()
{ other.start() ; }
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWriter.java b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWriter.java
index 01d231d59c..094b05d0e4 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWriter.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFWriter.java
@@ -225,9 +225,19 @@ public class StreamRDFWriter {
if ( context == null )
context = RIOT.getContext().copy();
StreamRDF stream = x.create(output, format, context);
+ if ( ! RDFLanguages.isQuads(format.getLang()) )
+ stream = triplesOnly(stream);
return stream ;
}
+
+ /* What to do if a quad is seen when writing in a triples-only syntax. */
+ private static StreamRDF triplesOnly(StreamRDF stream) {
+ // StreamTriplesOnly converts default graph quads to triples.
+ // Otherwise, throw exception.
+ return StreamTriplesOnly.exceptionOnQuads(stream);
+ }
+
public static boolean registered(Lang lang) {
RDFFormat fmt = registry.defaultSerialization(lang) ;
return registry.contains(fmt) ;
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamTriplesOnly.java b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamTriplesOnly.java
index b3c1f3dda7..413bcd4fb8 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamTriplesOnly.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamTriplesOnly.java
@@ -18,6 +18,10 @@
package org.apache.jena.riot.system;
+import java.util.function.Function;
+
+import org.apache.jena.riot.RiotException;
+import org.apache.jena.riot.out.NodeFmtLib;
import org.apache.jena.sparql.core.Quad;
/**
@@ -27,27 +31,51 @@ import org.apache.jena.sparql.core.Quad;
*/
public class StreamTriplesOnly extends StreamRDFWrapper {
- public static StreamRDF actionIfQuads(StreamRDF stream, Runnable action) {
+ public static enum QuadPolicy { CALL, IGNORE }
+
+ /** Exception on non-delfault graph quad */
+ private static Function<Quad, QuadPolicy> actionException = (q) -> {
+ throw new RiotException("Quad in Triple output: "+NodeFmtLib.str(q));
+ };
+
+ /** Replace an existing wrapper with a new policy for quads */
+ public static StreamRDF setActionIfQuads(StreamRDF stream, Function<Quad, QuadPolicy> action) {
+ // Strip existing layers.
+ while ( stream instanceof StreamTriplesOnly stream2 ) {
+ stream = stream2.get();
+ }
+ return addActionIfQuads(stream, action);
+ }
+
+ /** Add a new policy layer for quads */
+ public static StreamRDF addActionIfQuads(StreamRDF stream, Function<Quad, QuadPolicy> action) {
return new StreamTriplesOnly(stream, action);
}
- private boolean seenQuads = false;
- private final Runnable action;
+ /** Throw a {@link RiotException} if a non-default graph quad is seen. */
+ public static StreamRDF exceptionOnQuads(StreamRDF stream) {
+ return new StreamTriplesOnly(stream, actionException);
+ }
+
+ private QuadPolicy quadAction = QuadPolicy.CALL;
+ // The policy when seeing a quad that isn't in the default graph.
+ // Return true for "continue calling"
+ // Return false for "don't call again, ignore from now on"
+ private final Function<Quad, QuadPolicy> action;
- private StreamTriplesOnly(StreamRDF sink, Runnable action) {
+ private StreamTriplesOnly(StreamRDF sink, Function<Quad, QuadPolicy> action) {
super(sink) ;
this.action = action;
}
@Override
public void quad(Quad quad) {
- if ( quad.isTriple() || quad.isDefaultGraph() || quad.isUnionGraph() ) {
+ if ( quad.getGraph() == null || quad.isTriple() || quad.isDefaultGraph() ) {
triple(quad.asTriple()) ;
return;
}
- if ( ! seenQuads ) {
- action.run();
- seenQuads = true;
+ if ( quadAction == QuadPolicy.CALL ) {
+ quadAction = action.apply(quad);
}
}
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBase.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBase.java
index f4aba272a7..cd826bb35d 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBase.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBase.java
@@ -47,7 +47,6 @@ import org.apache.jena.sparql.util.Context;
* <p>
* For N-Quads and N-triples use {@link WriterStreamRDFPlain}.
*/
-
public abstract class WriterStreamRDFBase implements StreamRDF
{
// What did we do last?
diff --git a/jena-cmds/src/main/java/riotcmd/CmdLangParse.java b/jena-cmds/src/main/java/riotcmd/CmdLangParse.java
index 2f9d1a4a66..a682697ce3 100644
--- a/jena-cmds/src/main/java/riotcmd/CmdLangParse.java
+++ b/jena-cmds/src/main/java/riotcmd/CmdLangParse.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Function;
import java.util.zip.GZIPOutputStream;
import arq.cmdline.ModContext;
@@ -82,12 +83,12 @@ public abstract class CmdLangParse extends CmdGeneral {
}
protected List<ParseRecord> outcomes = new ArrayList<>();
-
protected OutputStream outputWrite = System.out;
protected StreamRDF parserOutputStream = null;
protected String parserBaseIRI = null;
protected boolean passRelativeURIs = false;
protected String writerBaseIRI = null;
+
@Override
protected void processModulesAndArgs() {
cmdStrictMode = super.contains(argStrict);
@@ -202,18 +203,18 @@ public abstract class CmdLangParse extends CmdGeneral {
if ( ! modLangParse.mergeQuads() && ! isQuadsOutput() ) {
// Only pass through triples.
- final StreamRDF dest = parserOutputStream;
if ( isStreamingOutput() ) {
- Runnable action = () -> {
+ Function<Quad, StreamTriplesOnly.QuadPolicy> action = (quad) -> {
// dest may be significantly buffered over the top of the output stream.
// The log message does not necessarily come out in the right place - it may be early.
+ // "Best effort" attempt to align log message to output.
IO.flush(outputWrite);
Log.warn(SysRIOT.getLogger(), "Quads in triples output - quads ignored.");
+ return StreamTriplesOnly.QuadPolicy.IGNORE;
};
- parserOutputStream = StreamTriplesOnly.actionIfQuads(parserOutputStream, action);
- } else {
- // Not streaming - code can issue error before formatting.
+ parserOutputStream = StreamTriplesOnly.setActionIfQuads(parserOutputStream, action);
}
+ // If not streaming, leave to the writer,
}
// If QuadsToTriples is added here, then counts will be "triples only"