This is an automated email from the ASF dual-hosted git repository.

afs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 0aa9feeafd GH-4091: Make quads a 1st class results format
0aa9feeafd is described below

commit 0aa9feeafdd77f3fbe01768413979146cdc5c5d1
Author: Andy Seaborne <[email protected]>
AuthorDate: Mon Jul 27 21:46:01 2026 +0100

    GH-4091: Make quads a 1st class results format
---
 .../jena/sparql/resultset/ResultsFormat.java       | 154 +++++++++++----------
 .../apache/jena/sparql/util/QueryExecUtils.java    |  10 +-
 .../apache/jena/sparql/resultset/TS_ResultSet.java |   1 +
 .../jena/sparql/resultset/TestResultsFormat.java   |  73 ++++++++++
 4 files changed, 157 insertions(+), 81 deletions(-)

diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsFormat.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsFormat.java
index 1ac7b520e7..141bdf322e 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsFormat.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsFormat.java
@@ -28,49 +28,57 @@ import org.apache.jena.riot.resultset.ResultSetLang;
 import org.apache.jena.sparql.util.TranslationTable;
 
 /**
- * The output formats for all query types.
- * Result sets, boolean graphs.
+ * The output formats for all query types. This allows the APi to given a 
results
+ * choice before the kind of query is known.
  * <p>
- * This does not include results sets as RDF. They are  provided for tests 
with {@link RDFInput} and {@link RDFOutput}.
+ * This does not include results sets as RDF. They are provided for tests with
+ * {@link RDFInput} and {@link RDFOutput}.
+ * <p>
+ * A {@code ResultsFormat} item has three parts, result format, triples format 
(e.g.
+ * CONSTRUCT), and quads (for extended CONSTRUCT). These are stored in a 
lookup table
+ * for string to {@code ResultsFormat}, which is used by commands.
  */
 
 public enum ResultsFormat {
-    // Results formats, by surface syntax.
-    // Used by commands.
+    // Does not cover boolean results.
 
-    XML(ResultSetLang.RS_XML, RDFFormat.RDFXML_ABBREV),
-    JSON(ResultSetLang.RS_JSON, RDFFormat.JSONLD11),
-    TEXT(ResultSetLang.RS_Text, RDFFormat.TURTLE),
+    XML(ResultSetLang.RS_XML, RDFFormat.RDFXML_ABBREV, null),
+    JSON(ResultSetLang.RS_JSON, RDFFormat.JSONLD, RDFFormat.JSONLD),
+    TEXT(ResultSetLang.RS_Text, RDFFormat.TURTLE, RDFFormat.TRIG),
 
-    CSV(ResultSetLang.RS_CSV, null),
-    TSV(ResultSetLang.RS_TSV, null),
+    CSV(ResultSetLang.RS_CSV, null, null),
+    TSV(ResultSetLang.RS_TSV, null, null),
 
-    THRIFT(ResultSetLang.RS_Thrift, RDFFormat.RDF_THRIFT),
-    PROTOBUF(ResultSetLang.RS_Protobuf, RDFFormat.RDF_PROTO),
+    THRIFT(ResultSetLang.RS_Thrift, RDFFormat.RDF_THRIFT, 
RDFFormat.RDF_THRIFT),
+    PROTOBUF(ResultSetLang.RS_Protobuf, RDFFormat.RDF_PROTO, 
RDFFormat.RDF_PROTO),
 
     // result set as RDF is handled specially
-    TTL(null, RDFFormat.TURTLE),
-    NT(null, RDFFormat.NTRIPLES),
-    RDFXML(null, RDFFormat.RDFXML),
-    RDF_JSONLD(null, RDFFormat.JSONLD),
+    TTL(null, RDFFormat.TURTLE, null),
+    NT(null, RDFFormat.NTRIPLES, null),
+
+    TRIG(null, RDFFormat.TRIG, RDFFormat.TRIG),
+    NQ(null, RDFFormat.NQUADS, RDFFormat.NQUADS),
+
+    RDFXML(null, RDFFormat.RDFXML, null),
+    JSONLD(null, RDFFormat.JSONLD, RDFFormat.JSONLD),
 
     // Special name.
-    COUNT(null, null),
+    COUNT(null, null, null),
 
-    NONE(ResultSetLang.RS_None, RDFFormat.RDFNULL),
+    NONE(ResultSetLang.RS_None, RDFFormat.RDFNULL, RDFFormat.RDFNULL),
 
-    SSE(null, null),
-    TUPLES(null, null)
-    ;
+    SSE(null, null, null)
+   ;
 
     private final Lang resultSetLang;
-    private final RDFFormat rdfFormat;
+    private final RDFFormat triplesFormat;
+    private final RDFFormat quadsFormat;
     //private final boolean supportsBoolean;
 
-    private ResultsFormat(Lang resultSetLang, RDFFormat rdfFormat) {
+    private ResultsFormat(Lang resultSetLang, RDFFormat triplesFormat, 
RDFFormat quadsFormat) {
         this.resultSetLang = resultSetLang;
-        this.rdfFormat = rdfFormat;
-
+        this.triplesFormat = triplesFormat;
+        this.quadsFormat = quadsFormat;
         //this.supportsBoolean = supportsBoolean;
     }
 
@@ -78,18 +86,21 @@ public enum ResultsFormat {
         return resultSetLang;
     }
 
-    public RDFFormat rdfFormat() {
-        return rdfFormat;
+    public RDFFormat triplesFormat() {
+        return triplesFormat;
+    }
+
+    public RDFFormat quadsFormat() {
+        return quadsFormat;
     }
 
-//
 //    public boolean supportsBoolean() {
 //        return supportsBoolean;
 //    }
-//
-//    public boolean isResultSet() {
-//        return ResultSetLang.isRegistered(lang());
-//    }
+
+    public boolean isResultSet() {
+        return ResultSetLang.isRegistered(resultSetLang);
+    }
 
     /** Guess the syntax of a result set URL */
     public static ResultsFormat guessSyntax(String resultsFilename) {
@@ -107,7 +118,7 @@ public enum ResultsFormat {
     }
 
     /**
-     * Look up a short name for a result set FMT_
+     * Look up a short name for an output format.
      *
      * @param shortname Short name
      * @return ResultSetFormat
@@ -117,59 +128,50 @@ public enum ResultsFormat {
     }
 
     // Common names to symbol (used by arq.rset)
-    private static TranslationTable<ResultsFormat> names = new 
TranslationTable<>(true) ;
+    private static TranslationTable<ResultsFormat> names = new 
TranslationTable<>(true);
     static {
-        names.put("srx",         XML) ;
-        names.put("xml",         XML) ;
+        names.put("srx",         XML);
+        names.put("srj",         JSON);
+        names.put("srt",         THRIFT);
+        names.put("srp",         PROTOBUF);
+        names.put("srpb",        PROTOBUF);
+
+        names.put("rt",          THRIFT);
+        names.put("trdf",        THRIFT);
 
-        names.put("json",        JSON) ;
-        names.put("srj",         JSON) ;
+        names.put("rpb",         PROTOBUF);
+        names.put("pbrdf",       PROTOBUF);
 
-        names.put("srt",         THRIFT) ;
-        names.put("srp",         PROTOBUF) ;
+        names.put("rdfxml",      RDFXML);
 
-        names.put("rdfxml",      RDFXML) ;
-        names.put("rdf",         TTL) ;
+        names.put("xml",         XML);
+        names.put("json",        JSON);
+
+        names.put("rdf",         TTL);
         names.put("ttl",         TTL);
         names.put("turtle",      TTL);
 
+        names.put("trig",        TRIG);
+
         names.put("n-triples",   NT);
         names.put("ntriples",    NT);
         names.put("nt",          NT);
 
-        // Thrift/RDF
-        // Protobuf/RDF
-
-
-        names.put("jsonld",      RDF_JSONLD) ;
-        names.put("json-ld",     RDF_JSONLD) ;
-
-        names.put("sse",         SSE) ;
-        names.put("csv",         CSV) ;
-        names.put("tsv",         TSV) ;
-        names.put("text",        TEXT) ;
-        names.put("count",       COUNT) ;
-        names.put("tuples",      TUPLES) ;
-        names.put("none",        NONE) ;
-
-        //names.put("rdf",         ???) ;
-
-//        names.put("rdf",         RDF_XML) ;
-//        names.put("rdf/n3",      RDF_N3) ;
-//        names.put("rdf/xml",     RDF_XML) ;
-//        names.put("n3",          RDF_N3) ;
-//        names.put("ttl",         RDF_TTL) ;
-//        names.put("turtle",      RDF_TTL) ;
-//        names.put("graph",       RDF_TTL) ;
-//        names.put("nt",          RDF_NT) ;
-//        names.put("n-triples",   RDF_NT) ;
-//        names.put("ntriples",    RDF_NT) ;
-//        names.put("jsonld",      RDF_JSONLD) ;
-//        names.put("json-ld",     RDF_JSONLD) ;
-//
-//        names.put("nq",          RDF_NQ) ;
-//        names.put("nquads",      RDF_NQ) ;
-//        names.put("n-quads",     RDF_NQ) ;
-//        names.put("trig",        RDF_TRIG) ;
+        names.put("n-quads",     NQ);
+        names.put("nquads",      NQ);
+        names.put("nq",          NQ);
+
+        names.put("jsonld",      JSONLD);
+        names.put("json-ld",     JSONLD);
+
+        names.put("sse",         SSE);
+        names.put("csv",         CSV);
+        names.put("tsv",         TSV);
+
+        names.put("text",        TEXT);
+        names.put("txt",         TEXT);
+        names.put("count",       COUNT);
+
+        names.put("none",        NONE);
     }
 }
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java
index b8acdd21a6..0d58de5c19 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java
@@ -201,7 +201,7 @@ public class QueryExecUtils {
         Lang rsLang = outputFormat.resultSetLang();
 
         if ( rsLang == null ) {
-            RDFFormat asRDF = outputFormat.rdfFormat();
+            RDFFormat asRDF = outputFormat.triplesFormat();
             Model model = RDFOutput.encodeAsModel(resultSet);
             RDFWriter.source(model).format(asRDF).output(output);
             return;
@@ -260,7 +260,7 @@ public class QueryExecUtils {
 
         Lang rsLang = outputFormat.resultSetLang();
         if ( rsLang == null ) {
-            RDFFormat asRDF = outputFormat.rdfFormat();
+            RDFFormat asRDF = outputFormat.triplesFormat();
             Model model = RDFOutput.encodeAsModel(resultBoolean);
             RDFWriter.source(model).format(asRDF).output(output);
             return;
@@ -270,15 +270,15 @@ public class QueryExecUtils {
     }
 
     private static void writeModel(Model model, ResultsFormat outputFormat, 
OutputStream output) {
-        RDFFormat rdfFormat = RDFFormat.TURTLE_PRETTY;
+        RDFFormat rdfFormat = outputFormat.triplesFormat();
         RDFWriter.source(model).format(rdfFormat).output(output);
         return;
     }
 
     private static void writeDataset(Dataset dataset, ResultsFormat 
outputFormat, OutputStream output) {
-        RDFFormat rdfFormat = outputFormat.rdfFormat();
+        RDFFormat rdfFormat = outputFormat.quadsFormat();
         if ( rdfFormat == null )
-            throw noFormatException("No dataset output format for : 
"+outputFormat.name());
+            throw noFormatException("No dataset output format for: 
"+outputFormat.name());
         RDFWriter.source(dataset).format(rdfFormat).output(output);
         return;
     }
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TS_ResultSet.java 
b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TS_ResultSet.java
index f0d13db30c..3abf8e04b6 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TS_ResultSet.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TS_ResultSet.java
@@ -29,6 +29,7 @@ import org.junit.platform.suite.api.Suite;
     TestResultSet.class
     , TestResultSetWriting.class
     , TestResultSetParsing.class
+    , TestResultsFormat.class
 })
 public class TS_ResultSet
 {
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultsFormat.java
 
b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultsFormat.java
new file mode 100644
index 0000000000..91b822636d
--- /dev/null
+++ 
b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultsFormat.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *   SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.sparql.resultset;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFFormat;
+import org.apache.jena.riot.resultset.ResultSetLang;
+
+public class TestResultsFormat {
+
+    @Test public void entry_srj()       { test("srj", ResultsFormat.JSON, 
ResultSetLang.RS_JSON, RDFFormat.JSONLD, RDFFormat.JSONLD); }
+    @Test public void entry_srx()       { test("srx", ResultsFormat.XML, 
ResultSetLang.RS_XML, RDFFormat.RDFXML, null); }
+
+    @Test public void entry_ttl1()      { test("ttl", ResultsFormat.TTL, null, 
RDFFormat.TURTLE, null); }
+    @Test public void entry_ttl2()      { test("turtle", ResultsFormat.TTL, 
null, RDFFormat.TURTLE, null); }
+
+    @Test public void entry_nt1()       { test("nt", ResultsFormat.NT, null, 
RDFFormat.NTRIPLES, null); }
+    @Test public void entry_nt2()       { test("n-triples", ResultsFormat.NT, 
null, RDFFormat.NTRIPLES, null); }
+
+    @Test public void entry_trig1()     { test("trig", ResultsFormat.TRIG, 
null, RDFFormat.TRIG, RDFFormat.TRIG); }
+
+    @Test public void entry_nq1()       { test("NQ", ResultsFormat.NQ, null, 
RDFFormat.NQUADS, RDFFormat.NQUADS); }
+    @Test public void entry_nq2()       { test("n-quads", ResultsFormat.NQ, 
null, RDFFormat.NQUADS, RDFFormat.NQUADS); }
+
+    @Test public void entry_text1()     { test("text", ResultsFormat.TEXT, 
ResultSetLang.RS_Text, RDFFormat.TURTLE, RDFFormat.TRIG); }
+    @Test public void entry_text2()     { test("txt", ResultsFormat.TEXT, 
ResultSetLang.RS_Text, RDFFormat.TURTLE, RDFFormat.TRIG); }
+    @Test public void entry_text3()     { test("TXT", ResultsFormat.TEXT, 
ResultSetLang.RS_Text, RDFFormat.TURTLE, RDFFormat.TRIG); }
+
+    @Test public void entry_xml()       { test("xml", ResultsFormat.XML, 
ResultSetLang.RS_XML, RDFFormat.RDFXML, null); }
+    @Test public void entry_rdfxml()    { test("rdfxml", ResultsFormat.RDFXML, 
null, RDFFormat.RDFXML, null); }
+
+    @Test public void entry_json()      { test("json", ResultsFormat.JSON, 
ResultSetLang.RS_JSON, RDFFormat.JSONLD, RDFFormat.JSONLD); }
+    @Test public void entry_jsonld()    { test("jsonld", ResultsFormat.JSONLD, 
null, RDFFormat.JSONLD, RDFFormat.JSONLD); }
+
+    @Test public void entry_bad() { testBad("SHACL"); }
+
+    private void test(String string, ResultsFormat expected, Lang rsLang, 
RDFFormat triplesFormat, RDFFormat quadsFormat) {
+        ResultsFormat rFmt = ResultsFormat.lookup(string);
+        assertEquals(expected, rFmt);
+        assertEquals(rsLang, rFmt.resultSetLang());
+        assertEquals(triplesFormat, rFmt.triplesFormat());
+        assertEquals(quadsFormat, rFmt.quadsFormat());
+    }
+
+    private void testBad(String string) {
+        ResultsFormat rFmt = ResultsFormat.lookup(string);
+        assertNull(rFmt);
+    }
+}

Reply via email to