jena-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a...@apache.org
Subject [03/11] jena git commit: JENA-1454: Introduce builder pattern for result set reading and writing.
Date Sun, 31 Dec 2017 10:52:41 GMT
http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java
new file mode 100644
index 0000000..e13cc23
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java
@@ -0,0 +1,247 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import static org.apache.jena.riot.resultset.rw.JSONResultsKW.*;
+
+import java.io.InputStream;
+import java.util.*;
+
+import org.apache.jena.atlas.json.JSON;
+import org.apache.jena.atlas.json.JsonArray;
+import org.apache.jena.atlas.json.JsonObject;
+import org.apache.jena.atlas.json.JsonValue;
+import org.apache.jena.atlas.logging.Log;
+import org.apache.jena.datatypes.RDFDatatype;
+import org.apache.jena.datatypes.TypeMapper;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.riot.lang.LabelToNode;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.resultset.ResultSetReader;
+import org.apache.jena.riot.resultset.ResultSetReaderFactory;
+import org.apache.jena.riot.system.SyntaxLabels;
+import org.apache.jena.sparql.core.Var;
+import org.apache.jena.sparql.engine.QueryIterator;
+import org.apache.jena.sparql.engine.ResultSetStream;
+import org.apache.jena.sparql.engine.binding.Binding;
+import org.apache.jena.sparql.engine.binding.BindingFactory;
+import org.apache.jena.sparql.engine.binding.BindingMap;
+import org.apache.jena.sparql.engine.iterator.QueryIterPlainWrapper;
+import org.apache.jena.sparql.graph.GraphFactory;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.SPARQLResult;
+import org.apache.jena.sparql.util.Context;
+
+/** Read JSON format SPARQL Results.
+ * <p>
+ * <a href="https://www.w3.org/TR/sparql11-results-json/">SPARQL 1.1 Query Results JSON Format</a>
+ */
+public class ResultSetReaderJSON implements ResultSetReader {
+    
+    public static final ResultSetReaderFactory factory = lang -> {
+        if (!Objects.equals(lang, ResultSetLang.SPARQLResultSetJSON ) )
+            throw new ResultSetException("ResultSet for JSON asked for a "+lang); 
+        return new ResultSetReaderJSON(); 
+    };
+    
+    private ResultSetReaderJSON() {}
+    
+    // TODO Streaming version of JSON Result set processing
+
+    @Override
+    public SPARQLResult readAny(InputStream in, Context context) {
+        return process(in, null, context);
+    }
+
+    static private SPARQLResult process(InputStream in, Model model, Context context) {
+        if ( context == null )
+            context = ARQ.getContext();
+        RS_JSON exec = new RS_JSON(context);
+        exec.parse(in);
+        if ( model == null )
+            model = GraphFactory.makeJenaDefaultModel();
+        if ( exec.rows != null ) {
+            QueryIterator qIter = new QueryIterPlainWrapper(exec.rows.iterator());
+            ResultSet rs = new ResultSetStream(Var.varNames(exec.vars), model, qIter);
+            return new SPARQLResult(rs); 
+        } else
+            return new SPARQLResult(exec.booleanResult);
+    }
+
+    /** 
+     * Parse a result set - whether rows (SELECT) or a boolean results (ASK).
+     * This object is one-time use and exists to carry the results as they are built-up.
+     */
+    static class RS_JSON {
+        final Context   context;
+        Boolean         booleanResult = null; // Valid if rows is null.
+        List<Binding>   rows          = null;
+        List<Var>       vars          = null;
+        final LabelToNode labelMap;
+
+        RS_JSON(Context context) {
+            this.context = context;
+            boolean inputGraphBNodeLabels = (context != null) && context.isTrue(ARQ.inputGraphBNodeLabels);
+            this.labelMap = inputGraphBNodeLabels
+                ? SyntaxLabels.createLabelToNodeAsGiven()
+                : SyntaxLabels.createLabelToNode();
+            this.rows = null ;
+        }
+
+        private void parse(InputStream in) {
+            JsonObject obj = JSON.parse(in);
+
+            // Boolean?
+            if ( obj.hasKey(kBoolean) ) {
+                checkContains(obj, true, true, kHead, kBoolean);
+                booleanResult = obj.get(kBoolean).getAsBoolean().value();
+                rows = null;
+                return;
+            }
+
+            // ResultSet.
+            rows = new ArrayList<>(1000);
+
+            checkContains(obj, true, true, kHead, kResults);
+
+            // process head
+            if ( !obj.get(kHead).isObject() )
+                throw new ResultSetException("Key 'head' must have a JSON object as value: found: " + obj.get(kHead));
+            JsonObject head = obj.get(kHead).getAsObject();
+
+            // ---- Head
+            // -- Link - array.
+            if ( head.hasKey(kLink) ) {
+                List<String> links = new ArrayList<>();
+
+                if ( head.get(kLink).isString() ) {
+                    Log.warn(this, "Link field is a string, should be an array of strings");
+                    links.add(head.get(kLink).getAsString().value());
+                } else {
+                    if ( !head.get(kLink).isArray() )
+                        throw new ResultSetException("Key 'link' must have be an array: found: " + obj.get(kLink));
+
+                    for ( JsonValue v : head.get(kLink).getAsArray() ) {
+                        if ( !v.isString() )
+                            throw new ResultSetException("Key 'link' must have be an array of strings: found: " + v);
+                        links.add(v.getAsString().value());
+                    }
+                }
+            }
+            // -- Vars
+            vars = parseVars(head);
+
+            // ---- Results
+            JsonObject results = obj.get(kResults).getAsObject();
+            if ( !results.get(kBindings).isArray() )
+                throw new ResultSetException("'bindings' must be an array");
+            JsonArray array = results.get(kBindings).getAsArray();
+            Iterator<JsonValue> iter = array.iterator();
+
+            for ( ; iter.hasNext() ; ) {
+                BindingMap b = BindingFactory.create();
+                JsonValue v = iter.next();
+                if ( !v.isObject() )
+                    throw new ResultSetException("Entry in 'bindings' array must be an object {}");
+                JsonObject x = v.getAsObject();
+                Set<String> varNames = x.keys();
+                for ( String vn : varNames ) {
+                    // if ( ! vars.contains(vn) ) {}
+                    JsonValue vt = x.get(vn);
+                    if ( !vt.isObject() )
+                        throw new ResultSetException("Binding for variable '" + vn + "' is not a JSON object: " + vt);
+                    Node n = parseOneTerm(vt.getAsObject(), labelMap);
+                    b.add(Var.alloc(vn), n);
+                }
+                rows.add(b);
+            }
+        }
+
+        private static List<Var> parseVars(JsonObject obj) {
+            if ( !obj.get(kVars).isArray() )
+                throw new ResultSetException("Key 'vars' must be a JSON array");
+            JsonArray a = obj.get(kVars).getAsArray();
+            Iterator<JsonValue> iter = a.iterator();
+            List<Var> vars = new ArrayList<>();
+            for ( ; iter.hasNext() ; ) {
+                JsonValue v = iter.next();
+                if ( !v.isString() )
+                    throw new ResultSetException("Entries in vars array must be strings");
+                Var var = Var.alloc(v.getAsString().value());
+                vars.add(var);
+            }
+            return vars;
+        }
+
+        private static Node parseOneTerm(JsonObject term, LabelToNode labelMap) {
+            checkContains(term, false, false, kType, kValue, kXmlLang, kDatatype);
+
+            String type = stringOrNull(term, kType);
+            String v = stringOrNull(term, kValue);
+
+            if ( kUri.equals(type) ) {
+                checkContains(term, false, true, kType, kValue);
+                String uri = v;
+                Node n = NodeFactory.createURI(v);
+                return n;
+            }
+
+            if ( kLiteral.equals(type) || kTypedLiteral.equals(type) ) {
+                String lang = stringOrNull(term, kXmlLang);
+                String dtStr = stringOrNull(term, kDatatype);
+                if ( lang != null && dtStr != null )
+                    throw new ResultSetException("Both language and datatype defined: " + term);
+                RDFDatatype dt = TypeMapper.getInstance().getSafeTypeByName(dtStr);
+                return NodeFactory.createLiteral(v, lang, dt);
+            }
+
+            if ( kBnode.equals(type) )
+                return labelMap.get(null, v);
+
+            throw new ResultSetException("Object key not recognized as valid for an RDF term: " + term);
+        }
+
+        private static String stringOrNull(JsonObject obj, String key) {
+            JsonValue v = obj.get(key);
+            if ( v == null )
+                return null;
+            if ( !v.isString() )
+                throw new ResultSetException("Not a string: key: " + key);
+            return v.getAsString().value();
+        }
+
+        private static void checkContains(JsonObject term, boolean allowUndefinedKeys, boolean requireAllExpectedKeys, String... keys) {
+            List<String> expectedKeys = Arrays.asList(keys);
+            Set<String> declared = new HashSet<>();
+            for ( String k : term.keys() ) {
+                if ( !expectedKeys.contains(k) && !allowUndefinedKeys )
+                    throw new ResultSetException("Expected only object keys " + Arrays.asList(keys) + " but encountered '" + k + "'");
+                if ( expectedKeys.contains(k) )
+                    declared.add(k);
+            }
+
+            if ( requireAllExpectedKeys && declared.size() < expectedKeys.size() )
+                throw new ResultSetException("One or more of the required keys " + expectedKeys + " was not found");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderThrift.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderThrift.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderThrift.java
new file mode 100644
index 0000000..bc7523f
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderThrift.java
@@ -0,0 +1,60 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Objects;
+
+import org.apache.jena.atlas.lib.NotImplemented;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.resultset.ResultSetReader;
+import org.apache.jena.riot.resultset.ResultSetReaderFactory;
+import org.apache.jena.riot.thrift.BinRDF;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.SPARQLResult;
+import org.apache.jena.sparql.util.Context;
+
+public class ResultSetReaderThrift implements ResultSetReader {
+    
+    public static ResultSetReaderFactory factory = lang->{
+        if (!Objects.equals(lang, ResultSetLang.SPARQLResultSetThrift ) )
+            throw new ResultSetException("ResultSetReadernot  for Thrift asked for a "+lang); 
+        return new ResultSetReaderThrift(); 
+    };
+    
+    private ResultSetReaderThrift() {}
+    
+    @Override
+    public ResultSet read(InputStream in, Context context) {
+        return BinRDF.readResultSet(in);
+    }
+
+    @Override
+    public ResultSet read(Reader in, Context context) {
+        throw new NotImplemented("Reading binary data from a java.io.Reader is not possible");
+    }
+
+    @Override
+    public SPARQLResult readAny(InputStream in, Context context) {
+        return new SPARQLResult(read(in, context));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderXML.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderXML.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderXML.java
new file mode 100644
index 0000000..65a2a7c
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderXML.java
@@ -0,0 +1,54 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Objects;
+
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.resultset.ResultSetReader;
+import org.apache.jena.riot.resultset.ResultSetReaderFactory;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.SPARQLResult;
+import org.apache.jena.sparql.util.Context;
+
+public class ResultSetReaderXML implements ResultSetReader {
+    
+    public static final ResultSetReaderFactory factory = lang -> {
+        if (!Objects.equals(lang, ResultSetLang.SPARQLResultSetXML ) )
+            throw new ResultSetException("ResultSet for XML asked for a "+lang); 
+        return new ResultSetReaderXML(); 
+    };
+    
+    private ResultSetReaderXML() {}
+    
+    @Override
+    public SPARQLResult readAny(InputStream in, Context context) {
+        SPARQLResult result = ResultsStAX.read(in, null, context);
+        return result;
+    }
+    
+    @Override
+    public ResultSet read(Reader in, Context context) {
+        SPARQLResult result = ResultsStAX.read(in, null, context);
+        return result.getResultSet();
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterJSON.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterJSON.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterJSON.java
new file mode 100644
index 0000000..8291b03
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterJSON.java
@@ -0,0 +1,305 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import static org.apache.jena.riot.resultset.rw.JSONResultsKW.*;
+
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.Objects;
+
+import org.apache.jena.atlas.io.IO;
+import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.atlas.json.io.JSWriter;
+import org.apache.jena.atlas.logging.Log;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.Literal;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.impl.Util;
+import org.apache.jena.riot.out.NodeToLabel;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.resultset.ResultSetWriter;
+import org.apache.jena.riot.resultset.ResultSetWriterFactory;
+import org.apache.jena.riot.system.SyntaxLabels;
+import org.apache.jena.sparql.resultset.ResultSetApply;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.ResultSetProcessor;
+import org.apache.jena.sparql.util.Context;
+
+public class ResultSetWriterJSON implements ResultSetWriter {
+
+    public static ResultSetWriterFactory factory = lang->{
+        if (!Objects.equals(lang, ResultSetLang.SPARQLResultSetJSON ) )
+            throw new ResultSetException("ResultSetWriter for JSON asked for a "+lang); 
+        return new ResultSetWriterJSON(); 
+    };
+    
+    private ResultSetWriterJSON() {}
+    
+    @Override
+    public void write(Writer out, ResultSet resultSet, Context context) {
+        throw new UnsupportedOperationException("Writing JSON results to a java.io.Writer. Use an OutputStream.") ;
+    }
+
+    @Override
+    public void write(OutputStream outStream, boolean result, Context context) {
+        JSWriter out = new JSWriter(outStream);
+        out.startOutput();
+        out.startObject();
+        out.key(kHead);
+        out.startObject();
+        out.finishObject();
+        out.pair(kBoolean, result);
+        out.finishObject();
+        out.finishOutput();
+        IO.flush(outStream);
+    }
+    
+    @Override
+    public void write(OutputStream out, ResultSet resultSet, Context context) {
+        JSONOutputResultSet jsonOut = new JSONOutputResultSet(out, context);
+        ResultSetApply a = new ResultSetApply(resultSet, jsonOut);
+        a.apply();
+    }
+
+    private static class JSONOutputResultSet implements ResultSetProcessor {
+        private static final boolean multiLineValues   = false;
+        private static final boolean multiLineVarNames = false;
+
+        private final IndentedWriter out;
+        private final NodeToLabel    labels;
+
+        private JSONOutputResultSet(OutputStream outStream, Context context) {
+            this(new IndentedWriter(outStream), context);
+        }
+
+        private JSONOutputResultSet(IndentedWriter indentedOut, Context context) {
+            out = indentedOut;
+            boolean outputGraphBNodeLabels = (context != null) && context.isTrue(ARQ.outputGraphBNodeLabels);
+            labels = outputGraphBNodeLabels
+                ? SyntaxLabels.createNodeToLabelAsGiven()
+                : SyntaxLabels.createNodeToLabel();
+        }
+
+        @Override
+        public void start(ResultSet rs) {
+            println("{");
+            out.incIndent();
+            doHead(rs);
+            println(quoteName(kResults), ": {");
+            out.incIndent();
+            println(quoteName(kBindings), ": [");
+            out.incIndent();
+            firstSolution = true;
+        }
+
+        @Override
+        public void finish(ResultSet rs) {
+            // Close last binding.
+            out.println();
+
+            out.decIndent();    // bindings
+            println("]");
+            out.decIndent();
+            println("}");       // results
+            out.decIndent();
+            println("}");       // top level {}
+            out.flush();
+        }
+
+        private void doHead(ResultSet rs) {
+            println(quoteName(kHead),": {");
+            out.incIndent();
+            doLink(rs);
+            doVars(rs);
+            out.decIndent();
+            println("} ,");
+        }
+
+        private void doLink(ResultSet rs) {
+            // ---- link
+            // out.println("\"link\": []") ;
+        }
+
+        private void doVars(ResultSet rs) {
+            // On one line.
+            print(quoteName(kVars), ": [ ");
+            if ( multiLineVarNames )
+                out.println();
+            out.incIndent();
+            for ( Iterator<String> iter = rs.getResultVars().iterator() ; iter.hasNext() ; ) {
+                String varname = iter.next();
+                print("\"", varname, "\"");
+                if ( multiLineVarNames )
+                    println();
+                if ( iter.hasNext() )
+                    print(" , ");
+            }
+            println(" ]");
+            out.decIndent();
+        }
+
+        boolean firstSolution          = true;
+        boolean firstBindingInSolution = true;
+
+        // NB assumes are on end of previous line.
+        @Override
+        public void start(QuerySolution qs) {
+            if ( !firstSolution )
+                println(" ,");
+            firstSolution = false;
+            println("{");
+            out.incIndent();
+            firstBindingInSolution = true;
+        }
+
+        @Override
+        public void finish(QuerySolution qs) {
+            println(); // Finish last binding
+            out.decIndent();
+            print("}"); // NB No newline
+        }
+
+        @Override
+        public void binding(String varName, RDFNode value) {
+            if ( value == null )
+                return;
+
+            if ( !firstBindingInSolution )
+                println(" ,");
+            firstBindingInSolution = false;
+
+            // Do not use quoteName - varName may not be JSON-safe as a bare name.
+            print(quote(varName), ": { ");
+            if ( multiLineValues )
+                out.println();
+
+            out.incIndent();
+            // Old, explicit unbound
+            // if ( value == null )
+            //     printUnbound() ;
+            // else
+            if ( value.isLiteral() )
+                printLiteral((Literal)value);
+            else if ( value.isResource() )
+                printResource((Resource)value);
+            else
+                Log.warn(this, "Unknown RDFNode type in result set: " + value.getClass());
+            out.decIndent();
+
+            if ( !multiLineValues )
+                print(" ");
+            print("}"); // NB No newline
+        }
+
+         private void printUnbound() {
+             print(quoteName(kType), ": ", quote(kUnbound), " , ") ;
+             if ( multiLineValues ) 
+                 println() ;
+             print(quoteName(kValue), ": null") ;
+             if ( multiLineValues )
+                 println() ;
+         }
+
+        private void printLiteral(Literal literal) {
+            String datatype = literal.getDatatypeURI();
+            String lang = literal.getLanguage();
+
+            if ( Util.isSimpleString(literal) || Util.isLangString(literal) ) {
+                print(quoteName(kType), ": ", quote(kLiteral), " , ");
+                if ( multiLineValues )
+                    println();
+
+                if ( lang != null && !lang.equals("") ) {
+                    print(quoteName(kXmlLang), ": ", quote(lang), " , ");
+                    if ( multiLineValues )
+                        println();
+                }
+            } else {
+                print(quoteName(kType), ": ", quote(kLiteral), " , ");
+                if ( multiLineValues )
+                    println();
+
+                print(quoteName(kDatatype), ": ", quote(datatype), " , ");
+                if ( multiLineValues )
+                    println();
+            }
+
+            print(quoteName(kValue), ": ", quote(literal.getLexicalForm()));
+            if ( multiLineValues )
+                println();
+        }
+
+        private void printResource(Resource resource) {
+            if ( resource.isAnon() ) {
+                String label = labels.get(null, resource.asNode());
+                // Comes with leading "_:"
+                label = label.substring(2);
+
+                print(quoteName(kType), ": ", quote(kBnode), " , ");
+                if ( multiLineValues )
+                    out.println();
+
+                print(quoteName(kValue), ": ", quote(label));
+
+                if ( multiLineValues )
+                    println();
+            } else {
+                print(quoteName(kType), ": ", quote(kUri), " , ");
+                if ( multiLineValues )
+                    println();
+                print(quoteName(kValue), ": ", quote(resource.getURI()));
+                if ( multiLineValues )
+                    println();
+                return;
+            }
+        }
+        
+        private void print(String... strings) {
+            for ( String s : strings )
+                out.print(s);
+        }
+
+        private void println(String... strings) {
+            print(strings);
+            out.println();
+        }
+
+        private static String quote(String string) {
+            // Scope for efficiency improvement.
+            return JSWriter.outputQuotedString(string);
+        }
+
+        // Quote a name (known to be JSON-safe)
+        // Never the RHS of a member entry (for example "false")
+        // Some (the Java JSON code for one) JSON parsers accept an unquoted
+        // string as a name of a name/value pair.
+
+        private static String quoteName(String string) {
+            // All calls to quoteName are builtin keywords which are already safe.
+            // but need the "" added.
+            //return "\""+string+"\"";
+            return quote(string);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterThrift.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterThrift.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterThrift.java
new file mode 100644
index 0000000..ee5aef5
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterThrift.java
@@ -0,0 +1,54 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Objects;
+
+import org.apache.jena.atlas.lib.NotImplemented;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.resultset.ResultSetWriter;
+import org.apache.jena.riot.resultset.ResultSetWriterFactory;
+import org.apache.jena.riot.thrift.BinRDF;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.util.Context;
+
+public class ResultSetWriterThrift implements ResultSetWriter {
+    
+    public static ResultSetWriterFactory factory = lang -> {
+        if (!Objects.equals(lang, ResultSetLang.SPARQLResultSetThrift ) )
+            throw new ResultSetException("ResultSetWriter for RDF/Thift asked for a "+lang); 
+        return new ResultSetWriterThrift(); 
+    };
+
+    @Override
+    public void write(OutputStream out, ResultSet resultSet, Context context)
+    { BinRDF.writeResultSet(out, resultSet) ; }
+
+    @Override
+    public void write(Writer out, ResultSet resultSet, Context context) {
+        throw new NotImplemented("Writing binary data to a java.io.Writer is not possible") ;
+    }
+    
+    @Override
+    public void write(OutputStream out, boolean result, Context context)
+    { throw new NotImplemented("No Thrift RDF encoding defined for boolean results"); }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterXML.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterXML.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterXML.java
new file mode 100644
index 0000000..92fd5c4
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetWriterXML.java
@@ -0,0 +1,380 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Objects;
+
+import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.atlas.logging.Log;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.Literal;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.impl.Util;
+import org.apache.jena.riot.out.NodeToLabel;
+import org.apache.jena.riot.resultset.ResultSetLang;
+import org.apache.jena.riot.resultset.ResultSetWriter;
+import org.apache.jena.riot.resultset.ResultSetWriterFactory;
+import org.apache.jena.riot.system.SyntaxLabels;
+import org.apache.jena.sparql.SystemARQ;
+import org.apache.jena.sparql.resultset.ResultSetApply;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.ResultSetProcessor;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.util.Symbol;
+
+public class ResultSetWriterXML implements ResultSetWriter {
+
+    public static final Symbol xmlInstruction = SystemARQ.allocSymbol("xmlInstruction");
+    public static final Symbol xmlStylesheet = SystemARQ.allocSymbol("xmlStylesheet");
+    
+    public static ResultSetWriterFactory factory = lang->{
+        if (!Objects.equals(lang, ResultSetLang.SPARQLResultSetXML ) )
+            throw new ResultSetException("ResultSetWriter for XML asked for a "+lang); 
+        return new ResultSetWriterXML(); 
+    };
+    
+    private ResultSetWriterXML() {}
+    
+    @Override
+    public void write(Writer out, ResultSet resultSet, Context context) {
+        throw new UnsupportedOperationException("Writing XML results to a java.io.Writer. Use an OutputStream.") ;
+    }
+
+    @Override
+    public void write(OutputStream outStream, boolean result, Context context) {
+        XMLOutputASK out = new XMLOutputASK(outStream);
+        if ( context != null && context.isDefined(xmlInstruction) )
+            out.xmlInst = context.isTrue(xmlInstruction);
+        if ( context != null && context.isDefined(xmlStylesheet) )
+            out.stylesheetURL = (String)(context.get(xmlStylesheet));
+        out.exec(result);
+    }
+    
+    @Override
+    public void write(OutputStream outStream, ResultSet resultSet, Context context) {
+        XMLOutputResultSet xOut = new XMLOutputResultSet(outStream, context);
+        if ( context != null && context.isDefined(xmlInstruction) )
+            xOut.setXmlInst(context.isTrue(xmlInstruction));
+        if ( context != null && context.isDefined(xmlStylesheet) )
+            xOut.setStylesheetURL((String)(context.get(xmlStylesheet)));
+        ResultSetApply a = new ResultSetApply(resultSet, xOut);
+        a.apply();
+    }
+    
+    private class XMLOutputASK implements XMLResults {
+        String         stylesheetURL = null;
+        IndentedWriter out;
+        int            bNodeCounter  = 0;
+        boolean        xmlInst       = true;
+
+        public XMLOutputASK(OutputStream outStream) {
+            this(outStream, null);
+        }
+
+        public XMLOutputASK(OutputStream outStream, String stylesheetURL) {
+            this(new IndentedWriter(outStream), stylesheetURL);
+        }
+
+        public XMLOutputASK(IndentedWriter indentedOut, String stylesheetURL) {
+            out = indentedOut;
+            this.stylesheetURL = stylesheetURL;
+        }
+
+        public void exec(boolean result) {
+            if ( xmlInst )
+                out.println("<?xml version=\"1.0\"?>");
+
+            if ( stylesheetURL != null )
+                out.println("<?xml-stylesheet type=\"text/xsl\" href=\"" + stylesheetURL + "\"?>");
+
+            out.println("<" + dfRootTag + " xmlns=\"" + dfNamespace + "\">");
+            out.incIndent(INDENT);
+
+            // Head
+            out.println("<" + dfHead + ">");
+            out.incIndent(INDENT);
+            if ( false ) {
+                String link = "UNSET";
+                out.println("<link href=\"" + link + "\"/>");
+            }
+            out.decIndent(INDENT);
+            out.println("</" + dfHead + ">");
+
+            if ( result )
+                out.println("<boolean>true</boolean>");
+            else
+                out.println("<boolean>false</boolean>");
+            out.decIndent(INDENT);
+            out.println("</" + dfRootTag + ">");
+            out.flush();
+        }
+    }
+
+    private static class XMLOutputResultSet implements ResultSetProcessor, XMLResults
+    {
+        private static boolean outputExplicitUnbound = false ;
+        
+        private int index = 0 ;                     // First index is 1 
+        private String stylesheetURL = null ;
+        private boolean xmlInst = true ;
+
+        private final IndentedWriter  out ;
+        private int bNodeCounter = 0 ;
+        private final NodeToLabel bNodeMap;
+        
+        private XMLOutputResultSet(OutputStream outStream, Context context) {
+            this(new IndentedWriter(outStream), context);
+        }
+
+        private XMLOutputResultSet(IndentedWriter indentedOut, Context context) {
+            out = indentedOut;
+            boolean outputGraphBNodeLabels = (context != null) && context.isTrue(ARQ.outputGraphBNodeLabels);
+            bNodeMap = outputGraphBNodeLabels
+                ? SyntaxLabels.createNodeToLabelAsGiven()
+                : SyntaxLabels.createNodeToLabel();
+        }
+
+        @Override
+        public void start(ResultSet rs) {
+            if ( xmlInst )
+                out.println("<?xml version=\"1.0\"?>");
+
+            if ( stylesheetURL != null ) {
+                out.print("<?xml-stylesheet type=\"text/xsl\" href=\"");
+                out.print(stylesheetURL);
+                out.println("\"?>");
+            }
+
+            // ---- Root
+            out.print("<");
+            out.print(dfRootTag);
+            out.print(" xmlns=\"");
+            out.print(dfNamespace);
+            out.println("\">");
+
+            // ---- Header
+
+            out.incIndent(INDENT);
+            out.print("<");
+            out.print(dfHead);
+            out.println(">");
+
+            if ( false ) {
+                String link = "UNSET";
+                out.print("<link href=\"");
+                out.print(link);
+                out.println("\"/>");
+            }
+
+            for ( String n : rs.getResultVars() ) {
+                out.incIndent(INDENT);
+                out.print("<");
+                out.print(dfVariable);
+                out.print(" ");
+                out.print(dfAttrVarName);
+                out.print("=\"");
+                out.print(n);
+                out.print("\"");
+                out.println("/>");
+                out.decIndent(INDENT);
+            }
+            out.print("</");
+            out.print(dfHead);
+            out.println(">");
+            out.decIndent(INDENT);
+
+            // Start results proper
+            out.incIndent(INDENT);
+            out.print("<");
+            out.print(dfResults);
+            out.println(">");
+            out.incIndent(INDENT);
+        }
+
+        @Override
+        public void finish(ResultSet rs) {
+            out.decIndent(INDENT);
+            out.print("</");
+            out.print(dfResults);
+            out.println(">");
+            out.decIndent(INDENT);
+            out.print("</");
+            out.print(dfRootTag);
+            out.println(">");
+            out.flush();
+        }
+
+        @Override
+        public void start(QuerySolution qs) {
+            out.print("<");
+            out.print(dfSolution);
+            out.println(">");
+            index++;
+            out.incIndent(INDENT);
+        }
+
+        @Override
+        public void finish(QuerySolution qs) {
+            out.decIndent(INDENT);
+            out.print("</");
+            out.print(dfSolution);
+            out.println(">");
+        }
+
+        @Override
+        public void binding(String varName, RDFNode node) {
+            if ( node == null && !outputExplicitUnbound )
+                return;
+
+            out.print("<");
+            out.print(dfBinding);
+            out.print(" name=\"");
+            out.print(varName);
+            out.println("\">");
+            out.incIndent(INDENT);
+            printBindingValue(node);
+            out.decIndent(INDENT);
+            out.print("</");
+            out.print(dfBinding);
+            out.println(">");
+        }
+
+        void printBindingValue(RDFNode node) {
+            if ( node == null ) {
+                // Unbound
+                out.print("<");
+                out.print(dfUnbound);
+                out.println("/>");
+                return;
+            }
+
+            if ( node instanceof Literal ) {
+                printLiteral((Literal)node);
+                return;
+            }
+
+            if ( node instanceof Resource ) {
+                printResource((Resource)node);
+                return;
+            }
+
+            Log.warn(this, "Unknown RDFNode type in result set: " + node.getClass());
+        }
+
+        void printLiteral(Literal literal) {
+            out.print("<");
+            out.print(dfLiteral);
+
+            if ( Util.isLangString(literal) ) {
+                String lang = literal.getLanguage();
+                out.print(" xml:lang=\"");
+                out.print(literal.getLanguage());
+                out.print("\"");
+            } else if ( !Util.isSimpleString(literal) ) {
+                // Datatype
+                // (RDF 1.1) not xsd:string nor rdf:langString.
+                // (RDF 1.0) any datatype.
+                String datatype = literal.getDatatypeURI();
+                out.print(" ");
+                out.print(dfAttrDatatype);
+                out.print("=\"");
+                out.print(datatype);
+                out.print("\"");
+            }
+
+            out.print(">");
+            out.print(xml_escape(literal.getLexicalForm()));
+            out.print("</");
+            out.print(dfLiteral);
+            out.println(">");
+        }
+
+        void printResource(Resource r) {
+            if ( r.isAnon() ) {
+                String label = bNodeMap.get(null, r.asNode());
+                // Comes with leading "_:"
+                label = label.substring(2);
+                out.print("<");
+                out.print(dfBNode);
+                out.print(">");
+                out.print(xml_escape(label));
+                out.print("</");
+                out.print(dfBNode);
+                out.println(">");
+            } else {
+                out.print("<");
+                out.print(dfURI);
+                out.print(">");
+                out.print(xml_escape(r.getURI()));
+                out.print("</");
+                out.print(dfURI);
+                out.println(">");
+            }
+        }
+
+        private static String xml_escape(String string) {
+            final StringBuilder sb = new StringBuilder(string);
+
+            int offset = 0;
+            String replacement;
+            char found;
+            for (int i = 0; i < string.length(); i++) {
+                found = string.charAt(i);
+                
+                switch (found) {
+                    case '&' : replacement = "&amp;"; break;
+                    case '<' : replacement = "&lt;"; break;
+                    case '>' : replacement = "&gt;"; break;
+                    case '\r': replacement = "&#x0D;"; break;
+                    case '\n': replacement = "&#x0A;"; break;
+                    default  : replacement = null;
+                }
+                
+                if (replacement != null) {
+                    sb.replace(offset + i, offset + i + 1, replacement);
+                    offset += replacement.length() - 1; // account for added chars
+                }
+            }
+            
+            return sb.toString();
+        }
+
+        /** @return Returns the stylesheetURL. */
+        public String getStylesheetURL()
+        { return stylesheetURL ; }
+
+        /** @param stylesheetURL The stylesheetURL to set. */
+        public void setStylesheetURL(String stylesheetURL)
+        { this.stylesheetURL = stylesheetURL ; }
+
+        /** @return Returns the xmlInst. */
+        public boolean getXmlInst()
+        { return xmlInst ; }
+
+        /** @param xmlInst The xmlInst to set. */
+        public void setXmlInst(boolean xmlInst)
+        { this.xmlInst = xmlInst ; }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsMgrX.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsMgrX.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsMgrX.java
new file mode 100644
index 0000000..80ee9b0
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsMgrX.java
@@ -0,0 +1,69 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.OutputStream;
+
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.SPARQLResult;
+
+public class ResultsMgrX {
+    // For org.apache.jena.riotResultSetMgr
+    public static ResultSet readResults(String url) {
+        ResultSet rs = read(url).getResultSet();
+        if ( rs == null )
+            throw new ResultSetException("Not a result set"); 
+        return rs;
+    }
+
+    public static boolean readBoolean(String url) {
+        Boolean b = read(url).getBooleanResult();
+        if ( b == null )
+            throw new ResultSetException("Not a boolean result"); 
+        return b;
+    }
+    
+    private static SPARQLResult read(String url) {
+        return null;
+//        ResultsReader.create()
+//            //.forceLang(lang)
+//            //.context(context)
+//            .build()
+//            .read(url);
+    }
+    
+    public static void write(OutputStream output, ResultSet resultSet) {
+        ResultsWriter.create()
+            .build()
+            .write(output, resultSet);
+    }
+
+    public static void write(OutputStream output, Boolean booleanResult) {
+    }
+
+    public static void write(String filename, ResultSet resultSet) {
+        ResultsWriter.create()
+            .build()
+            .write(filename, resultSet);
+    }
+
+    public static void write(String filename, Boolean booleanResult) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsReader.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsReader.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsReader.java
new file mode 100644
index 0000000..ce76d8c
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsReader.java
@@ -0,0 +1,151 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.InputStream;
+
+import org.apache.jena.atlas.web.ContentType;
+import org.apache.jena.atlas.web.TypedInputStream;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.riot.*;
+import org.apache.jena.riot.resultset.ResultSetReader;
+import org.apache.jena.riot.resultset.ResultSetReaderFactory;
+import org.apache.jena.riot.resultset.ResultSetReaderRegistry;
+import org.apache.jena.riot.system.stream.StreamManager;
+import org.apache.jena.sparql.resultset.SPARQLResult;
+import org.apache.jena.sparql.util.Context;
+
+public class ResultsReader {
+    
+    /** Create a {@code ResultsReader.Builder}. */
+    public static Builder create() { return new Builder() ; }
+    
+    public static class Builder {
+        private Lang hintLang = null; 
+        private Lang forceLang = null; 
+        private Context context = null;
+
+        /** Provide a {@link Lang} for the parser.
+         * The declared MIME type takes precedence, 
+         * the file extension does not.
+         */
+        public Builder lang(Lang hintLang) {
+            this.hintLang = hintLang;
+            return this;
+        }
+
+        /** Provide a {@link Lang} for the parser.
+         * This setting overrides any declared MIME type or file extension.  
+         */
+        public Builder forceLang(Lang forceLang) {
+            this.forceLang = forceLang;
+            return this;
+        }
+
+        /** Set the {@link Context}. This defaults to the global settings of {@code ARQ.getContext()}. */
+        public Builder context(Context context) {
+            if ( context != null )
+                context = context.copy();
+            this.context = context;
+            return this;
+        }
+        
+        /** Build a {@code ResultsReader} */
+        public ResultsReader build() {
+            return new ResultsReader(hintLang, forceLang, context); 
+        }
+        
+        /** Short form equivalent to {@code .build().read(url)} */
+        public ResultSet read(String url) {
+          return build().read(url); 
+        }
+        
+        /** Short form equivalent to {@code .build().read(InputStreams)} */
+        public ResultSet read(InputStream input) {
+          return build().read(input); 
+        }
+    }
+    
+    private final Lang hintLang;
+    private final Lang forceLang; 
+    private final Context context;
+    
+    private ResultsReader(Lang hintLang, Lang forceLang, Context context) {
+        super();
+        this.hintLang = hintLang;
+        this.forceLang = forceLang;
+        this.context = context;
+    }
+
+    private Lang determinLang(TypedInputStream in, String url) {
+        if ( in == null )
+            throw new RiotNotFoundException(url);
+        Lang lang = forceLang;
+        if ( lang == null ) {
+            ContentType ct = WebContent.determineCT(in.getContentType(), hintLang, url);
+            lang = RDFLanguages.contentTypeToLang(ct);
+        }
+        if ( lang == null )
+            throw new RiotException("Can't indentify the result set syntax from "+url); 
+        return lang;
+    }
+    
+    public ResultSet read(String url) {
+        // Remap?
+        TypedInputStream in = StreamManager.get(context).open(url);
+        Lang lang = determinLang(in, url);
+        return readResultSet(in.getInputStream(), lang);
+    }
+    
+    public ResultSet read(InputStream input) {
+        Lang lang = forceLang!=null ? forceLang : hintLang;
+        if ( lang == null )
+            throw new RiotException("Need a syntax to read a result set from an InputStream");
+        return readResultSet(input, lang);
+    }
+    
+    public SPARQLResult readAny(String url) {
+        TypedInputStream in = StreamManager.get(context).open(url);
+        Lang lang = determinLang(in, url);
+        return readAny(in.getInputStream(), lang);
+    }
+
+    public SPARQLResult readAny(InputStream input) {
+        Lang lang = forceLang!=null ? forceLang : hintLang;
+        if ( lang == null )
+            throw new RiotException("Need a syntax to read a result set from an InputStream");
+        return readAny(input, lang);
+    }
+
+    private ResultSet readResultSet(InputStream input, Lang lang) {
+        return readAny(input, lang).getResultSet();
+    }
+    
+    private SPARQLResult readAny(InputStream input, Lang lang) {
+        if ( ! ResultSetReaderRegistry.isRegistered(lang) )
+            throw new RiotException("Not registered as a SPARQL result set input syntax: "+lang);
+        
+        ResultSetReaderFactory factory = ResultSetReaderRegistry.getFactory(lang);
+        if ( factory == null )
+            throw new RiotException("No ResultSetReaderFactory for "+lang);
+        ResultSetReader reader = factory.create(lang);
+        SPARQLResult rs = reader.readAny(input, context);
+        return rs;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java
new file mode 100644
index 0000000..b6dde3a
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java
@@ -0,0 +1,473 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.jena.atlas.lib.Closeable;
+import org.apache.jena.atlas.logging.Log;
+import org.apache.jena.datatypes.RDFDatatype;
+import org.apache.jena.datatypes.TypeMapper;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.riot.lang.LabelToNode;
+import org.apache.jena.riot.system.SyntaxLabels;
+import org.apache.jena.sparql.ARQConstants;
+import org.apache.jena.sparql.core.ResultBinding;
+import org.apache.jena.sparql.core.Var;
+import org.apache.jena.sparql.engine.binding.Binding;
+import org.apache.jena.sparql.engine.binding.BindingFactory;
+import org.apache.jena.sparql.engine.binding.BindingMap;
+import org.apache.jena.sparql.graph.GraphFactory;
+import org.apache.jena.sparql.resultset.ResultSetException;
+import org.apache.jena.sparql.resultset.SPARQLResult;
+import org.apache.jena.sparql.util.Context;
+
+/** Public only for use by XMLOuptu (legacy) */
+public class ResultsStAX implements ResultSet, Closeable {
+    public static SPARQLResult read(InputStream in, Model model, Context context) {
+        XMLInputFactory xf = XMLInputFactory.newInstance() ;
+        try {
+            XMLStreamReader xReader = xf.createXMLStreamReader(in) ;
+            return worker(xReader, model, context);
+        } catch (XMLStreamException e) {
+            throw new ResultSetException("Can't initialize StAX parsing engine", e) ;
+        } catch (Exception ex) {
+            throw new ResultSetException("Failed when initializing the StAX parsing engine", ex) ;
+        }
+    }
+
+    public static SPARQLResult read(Reader in, Model model, Context context) {
+        XMLInputFactory xf = XMLInputFactory.newInstance() ;
+        try {
+            XMLStreamReader xReader = xf.createXMLStreamReader(in) ;
+            return worker(xReader, model, context) ;
+        } catch (XMLStreamException e) {
+            throw new ResultSetException("Can't initialize StAX parsing engine", e) ;
+        } catch (Exception ex) {
+            throw new ResultSetException("Failed when initializing the StAX parsing engine", ex) ;
+        }
+    }
+
+    private static SPARQLResult worker(XMLStreamReader xReader, Model model, Context context) {
+        if ( model == null )
+            model = GraphFactory.makeJenaDefaultModel() ;
+        ResultsStAX rss = new ResultsStAX(xReader, model, context) ;
+        return rss.read();
+    }
+    
+    // ResultSet variables
+    private QuerySolution   current          = null;
+    private XMLStreamReader parser           = null;
+    private List<String>    variables        = new ArrayList<>();
+    private Binding         binding          = null;                                                                  // Current
+    private boolean         inputGraphLabels = ARQ.isTrue(ARQ.inputGraphBNodeLabels);
+
+    private final LabelToNode  bNodes;
+
+    private boolean         isResultSet      = false;
+
+    // Result set
+    private boolean         ordered          = false;
+    private boolean         distinct         = false;
+    private boolean         finished         = false;
+    private Model           model            = null;
+    private int             row              = 0;
+
+    private boolean         askResult        = false;
+
+    private ResultsStAX(XMLStreamReader reader, Model model, Context context) {
+        
+        
+        
+        parser = reader ;
+        this.model = model ;
+        boolean inputGraphBNodeLabels = (context != null) && context.isTrue(ARQ.inputGraphBNodeLabels);
+        this.bNodes = inputGraphBNodeLabels
+            ? SyntaxLabels.createLabelToNodeAsGiven()
+            : SyntaxLabels.createLabelToNode();
+        init() ;
+    }
+
+    private SPARQLResult read() {
+        if ( isResultSet )
+            return new SPARQLResult(this);
+        else
+            return new SPARQLResult(askResult);
+    }
+    
+    private void init() {
+        try {
+            // Because all the tags are different, we could use one big
+            // switch statement!
+            skipTo(XMLResults.dfHead) ;
+            processHead() ;
+            skipTo(new String[]{XMLResults.dfResults, XMLResults.dfBoolean}, new String[]{XMLResults.dfResults}) ;
+            // Next should be a <result>, <boolean> element or </results>
+
+            // Need to decide what sort of thing we are reading.
+
+            String tag = parser.getLocalName() ;
+            if ( tag.equals(XMLResults.dfResults) ) {
+                isResultSet = true ;
+                processResults() ;
+            }
+            if ( tag.equals(XMLResults.dfBoolean) ) {
+                isResultSet = false ;
+                processBoolean() ;
+            }
+
+        } catch (XMLStreamException ex) {
+            Log.warn(this, "XMLStreamException: " + ex.getMessage(), ex) ;
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        if ( !isResultSet )
+            throw new ResultSetException("Not an XML result set") ;
+
+        if ( finished )
+            return false ;
+
+        try {
+            if ( binding == null )
+                binding = getOneSolution() ;
+        } catch (XMLStreamException ex) {
+            staxError("XMLStreamException: " + ex.getMessage(), ex) ;
+        }
+        boolean b = (binding != null) ;
+        if ( !b )
+            close() ;
+        return b ;
+    }
+
+    @Override
+    public QuerySolution next() {
+        return nextSolution() ;
+    }
+
+    @Override
+    public Binding nextBinding() {
+        if ( finished )
+            throw new NoSuchElementException("End of XML Results") ;
+        if ( !hasNext() )
+            throw new NoSuchElementException("End of XML Results") ;
+        Binding r = binding ;
+        row++ ;
+        binding = null ;
+        return r ;
+    }
+
+    @Override
+    public QuerySolution nextSolution() {
+        Binding r = nextBinding() ;
+        ResultBinding currentEnv = new ResultBinding(model, r) ;
+        return currentEnv ;
+    }
+
+    @Override
+    public int getRowNumber() {
+        return row ;
+    }
+
+    @Override
+    public List<String> getResultVars() {
+        return variables ;
+    }
+
+    public boolean isOrdered() {
+        return ordered ;
+    }
+
+    public boolean isDistinct() {
+        return distinct ;
+    }
+
+    // No model - it was from a stream
+    @Override
+    public Model getResourceModel() {
+        return null ;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException(ResultsStAX.class.getName()) ;
+    }
+
+    @Override
+    public void close() {
+        if ( finished )
+            return ;
+        finished = true ;
+        try { parser.close() ; } catch (XMLStreamException ex) {}
+    }
+
+    // -------- Boolean stuff
+
+    private void processBoolean() throws XMLStreamException {
+        try {
+            // At start of <boolean>
+            String s = parser.getElementText() ;
+            if ( s.equalsIgnoreCase("true") ) {
+                askResult = true ;
+                return ;
+            }
+            if ( s.equalsIgnoreCase("false") ) {
+                askResult = false ;
+                return ;
+            }
+            throw new ResultSetException("Unknown boolean value: " + s) ;
+        } finally {
+            close() ;
+        }
+    }
+
+    // --------
+
+    private void skipTo(String tag1) throws XMLStreamException {
+        skipTo(new String[]{tag1}, null) ;
+    }
+
+    private void skipTo(String[] startElementNames, String[] stopElementNames) throws XMLStreamException {
+        boolean found = false ;
+        loop : while (parser.hasNext()) {
+            int event = parser.next() ;
+            switch (event) {
+                case XMLStreamConstants.END_DOCUMENT :
+                    break loop ;
+                case XMLStreamConstants.END_ELEMENT :
+                    if ( stopElementNames == null )
+                        break ;
+
+                    String endTag = parser.getLocalName() ;
+                    if ( endTag != null && containsName(stopElementNames, endTag) )
+                        return ;
+                    break ;
+                case XMLStreamConstants.START_ELEMENT :
+                    if ( startElementNames == null )
+                        break ;
+                    QName qname = parser.getName() ;
+                    if ( !qname.getNamespaceURI().equals(XMLResults.baseNamespace) )
+                        staxError("skipToHead: Unexpected tag: " + qname) ;
+                    if ( containsName(startElementNames, qname.getLocalPart()) )
+                        return ;
+                    break ;
+                default :
+                    // Skip stuff
+            }
+        }
+
+        if ( !found ) {
+            String s1 = "" ;
+            if ( startElementNames != null )
+                s1 = String.join(", ", startElementNames) ;
+
+            String s2 = "" ;
+            if ( stopElementNames != null )
+                s2 = String.join(", ", stopElementNames) ;
+            Log.warn(this, "Failed to find start and stop of specified elements: " + s1 + " :: " + s2) ;
+        }
+    }
+
+    private boolean containsName(String[] elementNames, String eName) {
+        for ( String s : elementNames )
+        {
+            if ( s.equals( eName ) )
+            {
+                return true;
+            }
+        }
+        return false ;
+    }
+
+    private void processHead() throws XMLStreamException {
+        // Should be at the start of head
+
+        loop : while (parser.hasNext()) {
+            int event = parser.next() ;
+            String tag = null ;
+
+            switch (event) {
+                case XMLStreamConstants.END_DOCUMENT :
+                    break loop ;
+                case XMLStreamConstants.END_ELEMENT :
+                    tag = parser.getLocalName() ;
+                    if ( isTag(tag, XMLResults.dfHead) )
+                        break loop ;
+                    break ;
+                case XMLStreamConstants.START_ELEMENT :
+                    tag = parser.getLocalName() ;
+                    if ( isTag(tag, XMLResults.dfHead) )
+                        break ; // This switch statement
+                    if ( isTag(tag, XMLResults.dfVariable) ) {
+                        String varname = parser.getAttributeValue(null, XMLResults.dfAttrVarName) ;
+                        variables.add(varname) ;
+                        break ;
+                    }
+                    if ( isTag(tag, XMLResults.dfLink) )
+                        break ;
+
+                    staxError("Unknown XML element: " + tag) ;
+                    break ;
+                default :
+            }
+        }
+    }
+
+    // -------- Result Set
+
+    private void processResults() {
+        return ;
+    }
+
+    
+    static final String XML_NS = ARQConstants.XML_NS ;
+    
+    private Binding getOneSolution() throws XMLStreamException {
+        if ( finished )
+            return null ;
+        // At the start of <result>
+        BindingMap binding = BindingFactory.create() ;
+        String varName = null ;
+        while (parser.hasNext()) {
+            int event = parser.next() ;
+            String tag = null ;
+
+            switch (event) {
+                case XMLStreamConstants.END_DOCUMENT :
+                    staxError("End of document while processing solution") ;
+                    return null ;
+                case XMLStreamConstants.END_ELEMENT :
+                    tag = parser.getLocalName() ;
+                    if ( isTag(tag, XMLResults.dfSolution) )
+                        return binding ;
+                    if ( isTag(tag, XMLResults.dfResults) )
+                        // Hit the end of solutions.
+                        return null ;
+                    break ;
+                case XMLStreamConstants.START_ELEMENT :
+                    tag = parser.getLocalName() ;
+                    if ( isTag(tag, XMLResults.dfSolution) ) {
+                        binding = BindingFactory.create() ;
+                        break ;
+                    }
+                    if ( isTag(tag, XMLResults.dfBinding) ) {
+                        varName = parser.getAttributeValue(null, XMLResults.dfAttrVarName) ;
+                        break ;
+                    }
+                    // URI, literal, bNode, unbound.
+                    if ( isTag(tag, XMLResults.dfBNode) ) {
+                        String label = parser.getElementText() ;
+                        Node node = null ;
+                        // if ( inputGraphLabels.getValue() )
+                        if ( inputGraphLabels )
+                            node = NodeFactory.createBlankNode(label) ;
+                        else
+                            node = bNodes.get(null, label);
+                        addBinding(binding, Var.alloc(varName), node) ;
+                        break ;
+                    }
+
+                    if ( isTag(tag, XMLResults.dfLiteral) ) {
+                        String datatype = parser.getAttributeValue(null, XMLResults.dfAttrDatatype) ;
+
+                        // String langTag = parser.getAttributeValue(null,
+                        // "lang") ;
+
+                        // Woodstox needs XML_NS despite the javadoc of StAX
+                        // "If the namespaceURI is null the namespace is not checked for equality"
+                        // StAX(.codehaus.org) copes both ways round
+                        String langTag = parser.getAttributeValue(XML_NS, "lang") ;
+
+                        // Works for XML literals (returning them as a
+                        // string)
+                        String text = parser.getElementText() ;
+
+                        RDFDatatype dType = null ;
+                        if ( datatype != null )
+                            dType = TypeMapper.getInstance().getSafeTypeByName(datatype) ;
+
+                        Node n = NodeFactory.createLiteral(text, langTag, dType) ;
+                        if ( varName == null )
+                            throw new ResultSetException("No name for variable") ;
+                        addBinding(binding, Var.alloc(varName), n) ;
+                        break ;
+                    }
+
+                    if ( isTag(tag, XMLResults.dfUnbound) ) {
+                        break ;
+                    }
+                    if ( isTag(tag, XMLResults.dfURI) ) {
+                        String uri = parser.getElementText() ;
+                        Node node = NodeFactory.createURI(uri) ;
+                        addBinding(binding, Var.alloc(varName), node) ;
+                        break ;
+                    }
+                    break ;
+                default :
+            }
+        }
+        staxError("getOneSolution: Hit end unexpectedly") ;
+        return null ;
+    }
+    
+    static protected void addBinding(BindingMap binding, Var var, Node value) {
+        Node n = binding.get(var);
+        if ( n != null ) {
+            // Same - silently skip.
+            if ( n.equals(value) )
+                return;
+            Log.warn(ResultsStAX.class,
+                     String.format("Multiple occurences of a binding for variable '%s' with different values - ignored", var.getName()));
+            return;
+        }
+        binding.add(var, value);
+    }
+
+    private boolean isTag(String localName, String expectedName) {
+        if ( !parser.getNamespaceURI().equals(XMLResults.baseNamespace) )
+            return false ;
+        return localName.equals(expectedName) ;
+    }
+
+    private void staxError(String msg) {
+        Log.warn(this, "StAX error: " + msg) ;
+        throw new ResultSetException(msg) ;
+    }
+
+    private void staxError(String msg, Throwable th) {
+        Log.warn(this, "StAX error: " + msg, th) ;
+        throw new ResultSetException(msg, th) ;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsWriter.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsWriter.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsWriter.java
new file mode 100644
index 0000000..d1c4c81
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsWriter.java
@@ -0,0 +1,113 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import java.io.OutputStream;
+
+import org.apache.jena.atlas.lib.NotImplemented;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RiotException;
+import org.apache.jena.riot.resultset.ResultSetWriter;
+import org.apache.jena.riot.resultset.ResultSetWriterFactory;
+import org.apache.jena.riot.resultset.ResultSetWriterRegistry;
+import org.apache.jena.sparql.util.Context;
+
+public class ResultsWriter {
+    
+    /** Create a {@code ResultsWriter.Builder}. */
+    public static Builder create() { return new Builder() ; }
+    
+    public static class Builder {
+        private Lang lang = null; 
+        private Context context = null;
+
+        /** Provide a {@link Lang} for the writer.*/
+        public Builder lang(Lang lang) {
+            this.lang = lang;
+            return this;
+        }
+
+        /** Set the {@link Context}. This defaults to the global settings of {@code ARQ.getContext()}. */
+        public Builder context(Context context) {
+            if ( context != null )
+                context = context.copy();
+            this.context = context;
+            return this;
+        }
+        
+        /** Build a {@code ResultWriter} */
+        public ResultsWriter build() {
+            return new ResultsWriter(lang, context); 
+        }
+
+        /** Short form equivalent to {@code build().write(url, ResultSet)} */ 
+        public void write(String url, ResultSet resultSet) {
+            build().write(url, resultSet);
+        }
+        
+        /** Short form equivalent to {@code build().write(OutputStream, ResultSet)} */ 
+        public void write(OutputStream output, ResultSet resultSet) {
+            build().write(output, resultSet);
+        }
+    }
+    
+    private final Lang lang;
+    private final Context context;
+    
+    private ResultsWriter(Lang lang, Context context) {
+        super();
+        this.lang = lang;
+        this.context = context;
+    }
+
+    public void write(String url, ResultSet resultSet) {
+        throw new NotImplemented();
+    }
+    
+    public void write(OutputStream output, ResultSet resultSet) {
+        write(output, resultSet, null, lang);
+    }
+    
+    public void write(String url, boolean booleanResult) {
+        throw new NotImplemented();
+    }
+    
+    public void write(OutputStream output, boolean booleanResult) {
+        write(output, null, booleanResult, lang);
+    }
+    
+    private void write(OutputStream output, ResultSet resultSet, Boolean result, Lang lang) {
+        if ( resultSet == null && result == null )
+            throw new RiotException("No result set and no boolean result");
+        if ( resultSet != null && result != null )
+            throw new RiotException("Both result set and boolean result supplied");
+        if ( ! ResultSetWriterRegistry.isRegistered(lang) )
+            throw new RiotException("Not registered as a SPARQL result set output syntax: "+lang);
+        
+        ResultSetWriterFactory factory = ResultSetWriterRegistry.getFactory(lang);
+        if ( factory == null )
+            throw new RiotException("No ResultSetReaderFactory for "+lang);
+        ResultSetWriter writer = factory.create(lang);
+        if ( resultSet != null )
+            writer.write(output, resultSet, context);
+        else
+            writer.write(output, result, context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java
new file mode 100644
index 0000000..ae0c423
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java
@@ -0,0 +1,50 @@
+/*
+ * 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
+ *
+ *     http://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.
+ */
+
+package org.apache.jena.riot.resultset.rw;
+
+import org.apache.jena.sparql.ARQConstants ;
+
+
+public interface XMLResults
+{
+    public static final int INDENT = 2 ;
+
+    public static final String baseNamespace   = ARQConstants.srxPrefix ;
+    public static final String xsBaseURI       = ARQConstants.XML_SCHEMA_NS ;
+    
+    public static final String dfAttrVarName   = "name" ;
+    public static final String dfAttrDatatype  = "datatype" ;
+    
+    public static final String dfNamespace  = baseNamespace ;
+    public static final String dfRootTag    = "sparql" ;
+    public static final String dfHead       = "head" ;
+    public static final String dfVariable   = "variable" ;
+    public static final String dfLink       = "link" ;
+    public static final String dfResults    = "results" ;
+    public static final String dfSolution   = "result" ;
+    public static final String dfBinding    = "binding" ;
+    
+    public static final String dfBNode      = "bnode" ;
+    public static final String dfURI        = "uri" ;
+    public static final String dfLiteral    = "literal" ;
+    
+    public static final String dfUnbound    = "unbound" ;
+
+    public static final String dfBoolean    = "boolean" ;
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/riot/system/stream/StreamManager.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/stream/StreamManager.java b/jena-arq/src/main/java/org/apache/jena/riot/system/stream/StreamManager.java
index d8ba825..6ba919f 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/stream/StreamManager.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/stream/StreamManager.java
@@ -86,7 +86,7 @@ public class StreamManager {
 
     /**
      * Return the {@code StreamManager} in a context, or the global one if the context is
-     * null or does not contain an entry for a {@code StreamManager}.
+     * null or does not contain a valid entry for a {@code StreamManager}.
      * <p>
      * The {@code StreamManager} is keyed in the context by
      * {@link SysRIOT#sysStreamManager}.
@@ -95,7 +95,8 @@ public class StreamManager {
         if ( context == null )
             return get();
         try {
-            return (StreamManager)context.get(SysRIOT.sysStreamManager, context);
+            if ( context.isDefined(SysRIOT.sysStreamManager))
+                return (StreamManager)context.get(SysRIOT.sysStreamManager);
         }
         catch (ClassCastException ex) {
             log.warn("Context symbol '" + SysRIOT.sysStreamManager + "' is not a " + Lib.classShortName(StreamManager.class));


Mime
View raw message