/* * 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.query; import java.io.ByteArrayOutputStream ; import java.io.OutputStream ; import java.io.UnsupportedEncodingException ; import java.nio.charset.StandardCharsets ; import java.util.ArrayList ; import java.util.Iterator ; import java.util.List ; import org.apache.jena.atlas.logging.Log ; import org.apache.jena.rdf.model.RDFNode ; import org.apache.jena.riot.ResultSetMgr ; import org.apache.jena.shared.PrefixMapping ; import org.apache.jena.sparql.ARQException ; import org.apache.jena.sparql.ARQNotImplemented ; import org.apache.jena.sparql.core.Prologue ; import org.apache.jena.sparql.core.Var ; import org.apache.jena.sparql.engine.binding.Binding ; import org.apache.jena.sparql.engine.binding.BindingOutputStream ; import org.apache.jena.sparql.engine.binding.BindingUtils ; import org.apache.jena.sparql.resultset.* ; import org.apache.jena.sparql.serializer.SerializationContext ; /** ResultSetFormatter - Convenience ways to call the various output formatters. * in various formats. * @see ResultSetMgr */ public class ResultSetFormatter { // See also ResultSetMgr -- this post-dates this code. // Ideally, the operation here should call ResultSetMgr. private ResultSetFormatter() {} /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param qresults result set */ public static void out(ResultSet qresults) { out(System.out, qresults) ; } /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param out OutputStream * @param qresults result set */ public static void out(OutputStream out, ResultSet qresults) { out(out, qresults, (PrefixMapping)null) ; } /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param qresults result set * @param query May be used to abbreviate URIs */ public static void out(ResultSet qresults, Query query) { out(System.out, qresults, query) ; } /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param qresults result set * @param prologue May be used to abbreviate URIs */ public static void out(ResultSet qresults, Prologue prologue) { out(System.out, qresults, prologue) ; } // /** // * Output a result set in a text format. // * @param out OutputStream // * @param qresults result set // * @param query May be used to abbreviate URIs // */ // public static void out(OutputStream out, ResultSet qresults, Query query) // { out(out, qresults, query.getPrefixMapping()) ; } /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param qresults result set * @param pmap Prefix mapping for abbreviating URIs. */ public static void out(ResultSet qresults, PrefixMapping pmap) { out(System.out, qresults, pmap) ; } /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param out OutputStream * @param qresults result set * @param pmap Prefix mapping for abbreviating URIs. */ public static void out(OutputStream out, ResultSet qresults, PrefixMapping pmap) { TextOutput tFmt = new TextOutput(pmap) ; tFmt.format(out, qresults) ; } /** * Output a result set in a text format. The result set is consumed. * Use @see{ResultSetFactory.makeRewindable(ResultSet)} for a rewindable one. * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * @param out OutputStream * @param qresults result set * @param prologue Prologue, used to abbreviate IRIs */ public static void out(OutputStream out, ResultSet qresults, Prologue prologue) { TextOutput tFmt = new TextOutput(prologue) ; tFmt.format(out, qresults) ; } /** * Output an ASK answer * @param answer The boolean answer */ public static void out(boolean answer) { out(System.out, answer) ; } /** * Output an ASK answer * @param out OutputStream * @param answer The boolean answer */ public static void out(OutputStream out, boolean answer) { TextOutput tFmt = new TextOutput((SerializationContext)null) ; tFmt.format(out, answer) ; } /** Return a string that has the result set serialized as a text table * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * * @param qresults result set * @return string */ public static String asText(ResultSet qresults) { ByteArrayOutputStream arr = new ByteArrayOutputStream() ; out(arr, qresults) ; return new String(arr.toByteArray(), StandardCharsets.UTF_8) ; } /** Return a string that has the result set serialized as a text table * <p> * This caches the entire results in memory in order to determine the appropriate * column widths and therefore may exhaust memory for large results * </p> * * @param qresults result set * @param prologue Prologue, used to abbreviate IRIs * @return string */ public static String asText(ResultSet qresults, Prologue prologue) { ByteArrayOutputStream arr = new ByteArrayOutputStream() ; out(arr, qresults, prologue) ; try { return new String(arr.toByteArray(), "UTF-8") ; } catch (UnsupportedEncodingException e) { Log.warn(ResultSetFormatter.class, "UnsupportedEncodingException") ; return null ; } } // ---------------------------------------------------------------- // Do nothing formatting /** This operation faithfully walks the results but does nothing with them. * @return The count of the number of solutions. */ public static int consume(ResultSet resultSet) { int count = 0 ; for ( ; resultSet.hasNext() ; ) { // Force nodes to be materialized. QuerySolution result = resultSet.nextSolution() ; for ( Iterator<String> iter = result.varNames() ; iter.hasNext() ; ) { String vn = iter.next(); RDFNode n = result.get(vn) ; } count++ ; } return count ; } /** * Turn the result set into a java.util.List * @param resultSet The result set * @return List of QuerySolutions */ static public List<QuerySolution> toList(ResultSet resultSet) { List<QuerySolution> list = new ArrayList<>() ; for ( ; resultSet.hasNext() ; ) { QuerySolution result = resultSet.nextSolution() ; list.add(result) ; } return list ; } // ---------------------------------------------------------------- // As RDF /** Output a ResultSet in some format. * * @param resultSet Result set * @param rFmt A format to encode the result set in */ static public void output(ResultSet resultSet, ResultsFormat rFmt) { output(System.out, resultSet, rFmt) ; } /** Output a ResultSet in some format. * To get detailed control over each format, call the appropropiate operation directly. * * @param outStream Output * @param resultSet Result set * @param rFmt A format to encode the result set in */ static public void output(OutputStream outStream, ResultSet resultSet, ResultsFormat rFmt) { if ( rFmt.equals(ResultsFormat.FMT_RS_XML) ) { outputAsXML(outStream, resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RS_JSON) ) { outputAsJSON(outStream, resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RS_CSV) ) { outputAsCSV(outStream, resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RS_TSV) ) { outputAsTSV(outStream, resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RS_BIO) ) { outputAsBIO(outStream, resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RDF_XML) ) { RDFOutput.outputAsRDF(outStream, "RDF/XML-ABBREV", resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RDF_TTL) ) { RDFOutput.outputAsRDF(outStream, "TTL", resultSet) ; return ; } if ( rFmt.equals(ResultsFormat.FMT_RDF_NT) ) { RDFOutput.outputAsRDF(outStream, "N-TRIPLES", resultSet) ; return ; } throw new ARQException("Unknown ResultSet format: " + rFmt) ; } // ---- XML Output /** Output a result set in the XML format * * @param qresults result set */ static public void outputAsXML(ResultSet qresults) { outputAsXML(System.out, qresults) ; } /** Output a result set in the XML format * * @param outStream output stream * @param qresults result set */ static public void outputAsXML(OutputStream outStream, ResultSet qresults) { outputAsXML(outStream, qresults, (String)null) ; } /** Output a result set in the XML format, inserting a style sheet in the XMl output * * @param qresults result set * @param stylesheet The URL of the stylsheet */ static public void outputAsXML(ResultSet qresults, String stylesheet) { outputAsXML(System.out, qresults, stylesheet) ; } /** Output a result set in the XML format, inserting a style sheet in the XMl output * * @param outStream output stream * @param qresults result set * @param stylesheet The URL of the stylsheet */ static public void outputAsXML(OutputStream outStream, ResultSet qresults, String stylesheet) { XMLOutput xOut = new XMLOutput(stylesheet) ; xOut.format(outStream, qresults) ; } // ---- XML output: ASK /** Output a boolean result in the XML format * * @param booleanResult The boolean result to encode */ public static void outputAsXML(boolean booleanResult) { outputAsXML(System.out, booleanResult) ; } /** Output a boolean result in the XML format * * @param outStream output stream * @param booleanResult The boolean result to encode */ public static void outputAsXML(OutputStream outStream, boolean booleanResult) { outputAsXML(outStream, booleanResult, null) ; } /** Output a boolean result in the XML format * * @param booleanResult * @param stylesheet The URL of the stylesheet */ public static void outputAsXML(boolean booleanResult, String stylesheet) { outputAsXML(System.out, booleanResult, stylesheet) ; } /** Output a boolean result in the XML format * * @param outStream output stream * @param booleanResult * @param stylesheet The URL of the stylesheet */ public static void outputAsXML(OutputStream outStream, boolean booleanResult, String stylesheet) { XMLOutputASK fmt = new XMLOutputASK(outStream, stylesheet) ; fmt.exec(booleanResult) ; } /** Return a string that has the result set serialized as XML (not RDF) * <p> * This builds the string in memory which can lead to memory exhaustion * for large results. It is generally better to use the * {@link #outputAsXML(OutputStream, ResultSet)} overload instead * </p> * * @param qresults result set * @return string */ public static String asXMLString(ResultSet qresults) { return asXMLString(qresults, null) ; } /** Return a string that has the result set serialized as XML (not RDF) * with a style sheet directive inserted into the XML. * <p> * This builds the string in memory which can lead to memory exhaustion * for large results. It is generally better to use the * {@link #outputAsXML(OutputStream, ResultSet, String)} overload instead * </p> * @param qresults result set * @param stylesheet * @return string */ public static String asXMLString(ResultSet qresults, String stylesheet) { XMLOutput xOut = new XMLOutput(stylesheet) ; return xOut.asString(qresults) ; } /** Return a string that has the result set serilized as XML (not RDF) * <p> * This builds the string in memory which can lead to memory exhaustion * for large results. It is generally better to use the * {@link #outputAsXML(OutputStream, boolean)} overload instead * </p> * * @param booleanResult The boolean result to encode * @return string */ public static String asXMLString(boolean booleanResult) { return asXMLString(booleanResult, null) ; } /** Return a string that has the result set serilized as XML (not RDF) * <p> * This builds the string in memory which can lead to memory exhaustion * for large results. It is generally better to use the * {@link #outputAsXML(OutputStream, boolean, String)} overload instead * </p> * * @param booleanResult The boolean result to encode * @param stylesheet * @return string */ public static String asXMLString(boolean booleanResult, String stylesheet) { XMLOutput xOut = new XMLOutput(stylesheet) ; return xOut.asString(booleanResult) ; } // ---- JSON (and YAML) /** Output a result set in the JSON format * Format: <a href="http://www.w3.org/TR/rdf-sparql-json-res/">Serializing SPARQL Query Results in JSON</a> * JSON: <a href="http://json.org">http://json.org/</a> * @param resultSet result set */ static public void outputAsJSON(ResultSet resultSet) { outputAsJSON(System.out, resultSet) ; } /** Output a result set in the JSON format * Format: <a href="http://www.w3.org/TR/rdf-sparql-json-res/">Serializing SPARQL Query Results in JSON</a> * JSON: <a href="http://json.org">http://json.org/</a> * * @param outStream output stream * @param resultSet result set */ static public void outputAsJSON(OutputStream outStream, ResultSet resultSet) { JSONOutput jOut = new JSONOutput() ; jOut.format(outStream, resultSet) ; } /** Output a result set in the JSON format * Format: <a href="http://www.w3.org/TR/rdf-sparql-json-res/">Serializing SPARQL Query Results in JSON</a> * JSON: <a href="http://json.org">http://json.org/</a> * * @param booleanResult The boolean result to encode */ static public void outputAsJSON(boolean booleanResult) { outputAsJSON(System.out, booleanResult ) ; } /** Output a result set in the JSON format * Format: <a href="http://www.w3.org/TR/rdf-sparql-json-res/">Serializing SPARQL Query Results in JSON</a> * JSON: <a href="http://json.org">http://json.org/</a> * * @param outStream output stream * @param booleanResult The boolean result to encode */ static public void outputAsJSON(OutputStream outStream, boolean booleanResult) { JSONOutput jOut = new JSONOutput() ; jOut.format(outStream, booleanResult) ; } // ---- SSE /** Output a boolean result in the SSE format * Format: <a href="http://jena.apache.org/documentation/notes/sse.html">SSE</a> * * @param booleanResult The boolean result to encode */ static public void outputAsSSE(boolean booleanResult) { outputAsSSE(System.out, booleanResult ) ; } /** Output a boolean result in the SSE format * Format: <a href="http://jena.apache.org/documentation/notes/sse.html">SSE</a> * * @param outStream output stream * @param booleanResult The boolean result to encode */ static public void outputAsSSE(OutputStream outStream, boolean booleanResult) { throw new ARQNotImplemented("outputAsSSE") ; } /** Output a result set in the SSE format * Format: <a href="http://jena.apache.org/documentation/notes/sse.html">SSE</a> * @param resultSet result set */ static public void outputAsSSE(ResultSet resultSet) { outputAsSSE(System.out, resultSet) ; } /** Output a result set in the SSE format * Format: <a href="http://jena.apache.org/documentation/notes/sse.html">SSE</a> * @param resultSet result set */ static public void outputAsSSE(ResultSet resultSet, Prologue prologue) { outputAsSSE(System.out, resultSet, prologue) ; } /** Output a result set in the SSE format * Format: <a href="http://jena.apache.org/documentation/notes/sse.html">SSE</a> * @param outStream The output stream * @param resultSet The result set */ static public void outputAsSSE(OutputStream outStream, ResultSet resultSet) { outputAsSSE(outStream, resultSet, null) ; } /** Output a result set in the SSE format * Format: <a href="http://jena.apache.org/documentation/notes/sse.html">SSE</a> * @param outStream output stream * @param resultSet result set * @param prologue */ static public void outputAsSSE(OutputStream outStream, ResultSet resultSet, Prologue prologue) { throw new ARQNotImplemented("outputAsSSE") ; } // ---- CSV /** Output a boolean result in CSV format * * @param booleanResult The boolean result to encode */ static public void outputAsCSV(boolean booleanResult) { outputAsCSV(System.out, booleanResult ) ; } /** Output a boolean result in in CSV format * * @param outStream output stream * @param booleanResult The boolean result to encode */ static public void outputAsCSV(OutputStream outStream, boolean booleanResult) { CSVOutput fmt = new CSVOutput() ; fmt.format(outStream, booleanResult) ; } /** Output a result set in CSV format * @param resultSet result set */ static public void outputAsCSV(ResultSet resultSet) { outputAsCSV(System.out, resultSet) ; } /** Output a result set in CSV format * @param outStream The output stream * @param resultSet The result set */ static public void outputAsCSV(OutputStream outStream, ResultSet resultSet) { CSVOutput fmt = new CSVOutput() ; fmt.format(outStream, resultSet) ; } // ---- TSV /** Output a boolean result in TSV (tab separated values) format * * @param booleanResult The boolean result to encode */ static public void outputAsTSV(boolean booleanResult) { outputAsTSV(System.out, booleanResult ) ; } /** Output a boolean result in in TSV format * * @param outStream output stream * @param booleanResult The boolean result to encode */ static public void outputAsTSV(OutputStream outStream, boolean booleanResult) { TSVOutput fmt = new TSVOutput() ; fmt.format(outStream, booleanResult) ; } /** Output a result set in TSV format * @param resultSet result set */ static public void outputAsTSV(ResultSet resultSet) { outputAsTSV(System.out, resultSet) ; } /** Output a result set in TSV format * @param outStream The output stream * @param resultSet The result set */ static public void outputAsTSV(OutputStream outStream, ResultSet resultSet) { TSVOutput fmt = new TSVOutput() ; fmt.format(outStream, resultSet) ; } /** Output a result set in BIO format * @deprecated Exprimental - may be removed */ @Deprecated public static void outputAsBIO(OutputStream out, ResultSet results) { List<Var> vars = Var.varList(results.getResultVars()) ; BindingOutputStream bout = new BindingOutputStream(out, vars) ; for ( ; results.hasNext() ; ) { Binding b = BindingUtils.asBinding(results.next()) ; bout.write(b) ; } bout.flush() ; } }