http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInput.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInput.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInput.java index 322a568..d2a3ee5 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInput.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInput.java @@ -18,231 +18,40 @@ package org.apache.jena.sparql.resultset; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kBindings; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kBnode; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kBoolean; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kDatatype; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kHead; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kLink; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kLiteral; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kResults; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kType; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kTypedLiteral; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kUri; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kValue; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kVars; -import static org.apache.jena.sparql.resultset.JSONResultsKW.kXmlLang; - 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.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.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.riot.resultset.ResultSetLang; +import org.apache.jena.riot.resultset.rw.ResultsReader; +/** + * @deprecated Use ResultSetMgr.read + */ +@Deprecated public class JSONInput extends SPARQLResult { public static ResultSet fromJSON(InputStream input) { - SPARQLResult r = new JSONInput().process(input, null); - return r.getResultSet(); + return + ResultsReader.create() + .lang(ResultSetLang.SPARQLResultSetJSON) + .read(input); } public static boolean booleanFromJSON(InputStream input) { - SPARQLResult r = new JSONInput().process(input, null); - return r.getBooleanResult(); + return make(input).getBooleanResult(); } public static SPARQLResult make(InputStream input) { - return make(input, null); + return + ResultsReader.create() + .lang(ResultSetLang.SPARQLResultSetJSON) + .build() + .readAny(input); } public static SPARQLResult make(InputStream input, Model model) { - return new JSONInput().process(input, model); - } - - public JSONInput() {} - - public JSONInput(InputStream in) { - this(in, null); + return make(input); } - // See also XMLInputSAX for design structure. - public JSONInput(InputStream in, Model model) { - if ( model == null ) - model = GraphFactory.makeJenaDefaultModel(); - process(in, model); - } - - Boolean booleanResult = null; // Valid if rows is null. - List<Binding> rows = null; - List<Var> vars = null; - - // TODO Streaming version of JSON Result set processing - - private SPARQLResult process(InputStream in, Model model) { - parse(in); - if ( model == null ) - model = GraphFactory.makeJenaDefaultModel(); - if ( rows != null ) { - QueryIterator qIter = new QueryIterPlainWrapper(rows.iterator()); - ResultSet rs = new ResultSetStream(Var.varNames(vars), model, qIter); - super.set(rs); - } else - super.set(booleanResult); - return this; - } - - private void parse(InputStream in) { - JsonObject obj = JSON.parse(in); - - if ( obj.hasKey(kBoolean) ) { - checkContains(obj, true, true, kHead, kBoolean); - booleanResult = obj.get(kBoolean).getAsBoolean().value(); - rows = null; - return; - } - - 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()); - b.add(Var.alloc(vn), n); - } - rows.add(b); - } - } - - private 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; - } - - LabelToNode labelMap = SyntaxLabels.createLabelToNode(); - - private Node parseOneTerm(JsonObject term) { - 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"); - } + private JSONInput() {} }
http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInputIterator.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInputIterator.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInputIterator.java deleted file mode 100644 index c8f89f1..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONInputIterator.java +++ /dev/null @@ -1,657 +0,0 @@ -/** - * 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.sparql.resultset; - -import java.io.InputStream; -import java.util.*; - -import org.apache.jena.atlas.AtlasException; -import org.apache.jena.atlas.io.IO; -import org.apache.jena.atlas.io.IndentedWriter; -import org.apache.jena.atlas.io.PeekReader; -import org.apache.jena.atlas.iterator.PeekIterator; -import org.apache.jena.atlas.json.io.parser.TokenizerJSON; -import org.apache.jena.datatypes.TypeMapper; -import org.apache.jena.graph.Node; -import org.apache.jena.graph.NodeFactory; -import org.apache.jena.query.QueryException; -import org.apache.jena.riot.RiotParseException; -import org.apache.jena.riot.tokens.Token; -import org.apache.jena.riot.tokens.TokenType; -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.engine.iterator.QueryIteratorBase; -import org.apache.jena.sparql.serializer.SerializationContext; - -/** - * Streaming Iterator over SPARQL JSON results, not yet fully implemented (see - * JENA-267) - * <p> - * Creating the Iterator automatically causes it to parse a small chunk of the - * stream to determine the variables in the result set either by reading the - * header or reading some portion of the results if the results appear before - * the header since JSON does not guarantee the order of keys within an object - * </p> - */ -public class JSONInputIterator extends QueryIteratorBase { - - private InputStream input; - - private boolean isBooleanResults = false, - boolResult = false, headerSeen = false; - private Binding binding = null; - private TokenizerJSON tokens; - private PeekIterator<Token> peekIter; - - private Queue<Binding> cache = new LinkedList<>(); - private Set<String> vars = new HashSet<>(); - - /** - * Creates a SPARQL JSON Iterator - * <p> - * Automatically parses some portion of the input to determine the variables - * in use - * </p> - */ - public JSONInputIterator(InputStream input) { - this.input = input; - this.tokens = new TokenizerJSON(PeekReader.makeUTF8(input)); - this.peekIter = new PeekIterator<>(this.tokens); - - // We should always parse the first little bit to see the head stuff or - // to cache a chunk of results and infer the headers - // Primarily we are trying to find out what the variables are - preParse(); - } - - /** - * Returns the variables present in the result sets - */ - public Iterator<String> getVars() { - return vars.iterator(); - } - - /** - * Gets whether the SPARQL JSON represents a boolean result set - */ - public boolean isBooleanResult() { - return isBooleanResults; - } - - /** - * Does the pre-parsing which attempts to read the header of the results - * file and determine variables present - * <p> - * If the header is encountered first then we read this, if the results are - * encountered first we parse the first 100 results and determine the - * variables present from those instead - * </p> - */ - private void preParse() { - // First off the { to start the object - expect("Expected the start of the JSON Results Object", TokenType.LBRACE); - - // Then expect to see a Property Name - // Loop here because we might see some things we can discard first - do { - if ( !isPropertyName() ) { - Token t = nextToken(); - String name = t.getImage(); - checkColon(); - - if ( name.equals("head") ) { - if ( headerSeen ) - exception(t, "Invalid duplicate header property"); - parseHeader(); - // Continue afterwards because we want to be in place to - // start streaming results - } else if ( name.equals("boolean") ) { - parseBoolean(); - // Afterwards we continue because we want to see an empty - // head - } else if ( name.equals("results") ) { - if ( isBooleanResults ) - exception(t, "Encountered results property when boolean property has already been countered"); - - // Scroll to first result - parseToFirstResult(); - - // If we already saw the header then exit at this point - if ( headerSeen ) - return; - - // If not we're going to pre-cache some chunk of results so - // we can infer the variable names - boolean complete = cacheResults(100); - - // If this exhausted the result set then we can continue - // looking for the header - // Otherwise we should exit as we may eventually see the - // header later... - if ( !complete ) { - // TODO Now determine variables present from this - return; - } - } else { - ignoreValue(); - } - checkComma(TokenType.RBRACE); - } else if ( lookingAt(TokenType.RBRACE) ) { - // We hit the end of the result object already - if ( !headerSeen ) - exception(peekToken(), "End of JSON Results Object encountered before a valid header was seen"); - nextToken(); - - // Shouldn't be any further content - if ( !lookingAt(TokenType.EOF) ) - exception(peekToken(), "Unexpected content after end of JSON Results Object"); - - // Can stop our initial buffering at this stage - return; - } else { - exception(peekToken(), "Expected a JSON property name but got %s", peekToken()); - } - } while (true); - } - - private void parseHeader() { - do { - if ( isPropertyName() ) { - Token t = nextToken(); - String name = t.getImage(); - checkColon(); - - if ( name.equals("vars") ) { - parseVars(); - } else if ( name.equals("link") ) { - // Throw away the links - skipLinks(); - } else { - exception(t, "Unexpected property %s encountered in head object", name); - } - checkComma(TokenType.RBRACE); - } else if ( lookingAt(TokenType.RBRACE) ) { - nextToken(); - return; - } else { - exception(peekToken(), "Unexpected Token encountered while parsing head object"); - } - } while (true); - } - - private void parseVars() { - if ( lookingAt(TokenType.LBRACKET) ) { - nextToken(); - vars.clear(); - do { - if ( lookingAt(TokenType.STRING) ) { - Token t = nextToken(); - String var = t.getImage(); - vars.add(var); - checkComma(TokenType.RBRACKET); - } else if ( lookingAt(TokenType.RBRACKET) ) { - nextToken(); - return; - } else { - exception(peekToken(), "Unexpected Token encountered while parsing the variables list in the head object"); - } - } while (true); - } else { - exception(peekToken(), "Unexpected Token ecountered, expected a [ to start the array of variables in the head object"); - } - } - - private void skipLinks() { - if ( lookingAt(TokenType.LBRACKET) ) { - nextToken(); - do { - if ( lookingAt(TokenType.RBRACKET) ) { - // End of links - nextToken(); - return; - } else if ( lookingAt(TokenType.STRING) ) { - // Ignore link and continue - nextToken(); - } else { - exception(peekToken(), "Unexpected Token when a Link URI was expected"); - } - checkComma(TokenType.RBRACKET); - } while (true); - } else { - exception(peekToken(), "Unexpected token when a [ was expected to start the list of URIs for a link property"); - } - } - - private void parseToFirstResult() { - if ( lookingAt(TokenType.LBRACE) ) { - nextToken(); - if ( isPropertyName() ) { - Token t = nextToken(); - String name = t.getImage(); - if ( name.equals("bindings") ) { - checkColon(); - if ( lookingAt(TokenType.LBRACKET) ) { - nextToken(); - } else { - exception(peekToken(), "Unexpected Token encountered, expected a [ for the start of the bindings array"); - } - } else { - exception(t, "Unexpected Token encountered, expected the bindings property"); - } - } else { - exception(peekToken(), "Unexpected Token ecnountered, expected the bindings property"); - } - } else { - exception(peekToken(), "Unexpected Token encountered, expected a { to start the results list object"); - } - } - - private void parseToEnd() { - // TODO Parse through to end of the JSON document consuming the header - // if we haven't seen it already - checkComma(TokenType.RBRACE); - } - - private void ignoreValue() { - if ( isPropertyName() ) { - // Just a string value so can discard and then check for the - // subsequent comma - nextToken(); - checkComma(TokenType.RBRACE); - } else if ( lookingAt(TokenType.DECIMAL) || lookingAt(TokenType.INTEGER) || lookingAt(TokenType.DOUBLE) - || lookingAt(TokenType.KEYWORD) ) { - // Just a numeric/keyword (boolean) value do discard and check for - // subsequent comma - nextToken(); - checkComma(TokenType.RBRACE); - } else if ( lookingAt(TokenType.LBRACE) ) { - // Start of an Object - nextToken(); - - // TODO We should really care about the syntactic validity of - // objects we are ignoring but that seems like a bit too much effort - int openBraces = 1; - while (openBraces >= 1) { - Token next = nextToken(); - if ( next.getType().equals(TokenType.LBRACE) ) { - openBraces++; - } else if ( next.getType().equals(TokenType.RBRACE) ) { - openBraces--; - } - } - checkComma(TokenType.RBRACE); - } else if ( lookingAt(TokenType.LBRACKET) ) { - // Start of an Array - nextToken(); - - // TODO We should really care about the syntactic validity of - // objects we are ignoring but that seems like a bit too much effort - int openBraces = 1; - while (openBraces >= 1) { - Token next = nextToken(); - if ( next.getType().equals(TokenType.LBRACKET) ) { - openBraces++; - } else if ( next.getType().equals(TokenType.RBRACKET) ) { - openBraces--; - } - } - checkComma(TokenType.RBRACE); - } else { - exception(peekToken(), "Unexpected Token"); - } - } - - /** - * Caches the first N results so we can infer variables, indicates whether - * the caching exhausted the result set - * - * @param n - * Number of results to cache - */ - private boolean cacheResults(int n) { - for ( int i = 0 ; i < n ; i++ ) { - if ( parseNextBinding() ) { - this.cache.add(this.binding); - this.binding = null; - } else { - return true; - } - } - return false; - } - - private void parseBoolean() { - isBooleanResults = true; - if ( lookingAt(TokenType.KEYWORD) ) { - Token t = nextToken(); - String keyword = t.getImage(); - if ( keyword.equals("true") ) { - boolResult = true; - } else if ( keyword.equals("false") ) { - boolResult = false; - } else { - exception(t, "Unexpected keyword %s encountered, expected true or false", keyword); - } - } else { - exception(peekToken(), "Unexpected token when a true/false keyword was expected for the value of the boolean property"); - } - } - - @Override - public void output(IndentedWriter out, SerializationContext sCxt) { - // Not needed - only called as part of printing/debugging query plans. - out.println("JSONInputIterator"); - } - - @Override - protected boolean hasNextBinding() { - if ( isBooleanResults ) - return false; - - if ( this.input != null ) { - if ( this.cache.size() > 0 ) { - this.binding = this.cache.remove(); - return true; - } else if ( this.binding == null ) { - return this.parseNextBinding(); - } else { - return true; - } - } else { - return false; - } - } - - private boolean parseNextBinding() { - if ( lookingAt(TokenType.LBRACE) ) { - nextToken(); - BindingMap b = BindingFactory.create(); - do { - if ( isPropertyName() ) { - Token t = nextToken(); - String var = t.getImage(); - checkColon(); - - Node n = parseNode(); - b.add(Var.alloc(var), n); - - checkComma(TokenType.RBRACE); - } else if ( lookingAt(TokenType.RBRACE) ) { - nextToken(); - checkComma(TokenType.RBRACKET); - break; - } else { - exception(peekToken(), "Unexpected Token encountered, expected a property name to indicate the value for a variable"); - } - } while (true); - - this.binding = b; - return true; - } else if ( lookingAt(TokenType.RBRACKET) ) { - // End of Bindings Array - nextToken(); - if ( lookingAt(TokenType.RBRACE) ) { - nextToken(); - parseToEnd(); - } else { - exception(peekToken(), "Unexpected Token encountered, expected a } to end the results object"); - } - } else { - exception(peekToken(), - "Unexpected Token encountered, expected a { for the start of a binding of ] to end the array of bindings"); - } - return false; - } - - private Node parseNode() { - String type, value, lang, datatype; - type = value = lang = datatype = null; - - if ( lookingAt(TokenType.LBRACE) ) { - Token pos = nextToken(); - - // Collect the Properties - do { - if ( isPropertyName() ) { - Token t = nextToken(); - String name = t.getImage(); - checkColon(); - - if ( name.equals("type") ) { - if ( type != null ) - exception(t, "Illegal duplicate type property"); - type = parseNodeInfo("type"); - } else if ( name.equals("value") ) { - if ( value != null ) - exception(t, "Illegal duplicate value property"); - value = parseNodeInfo("value"); - } else if ( name.equals("datatype") ) { - if ( datatype != null ) - exception(t, "Illegal duplicate datatype property"); - datatype = parseNodeInfo("datatype"); - } else if ( name.equals("xml:lang") ) { - if ( lang != null ) - exception(t, "Illegal duplicate xml:lang property"); - lang = parseNodeInfo("xml:lang"); - } else { - exception(t, "Unexpected Property Name '%s', expected one of type, value, datatype or xml:lang", name); - } - } else if ( lookingAt(TokenType.RBRACE) ) { - nextToken(); - break; - } else { - exception(peekToken(), "Unexpected Token, expected a property name as part of a Node object"); - } - } while (true); - - // Error if missing type or value - if ( type == null ) - exception(pos, "Encountered a Node object with no type property"); - if ( value == null ) - exception(pos, "Encountered a Node object with no value property"); - - // Generate a Node based on the properties we saw - if ( type.equals("uri") ) { - return NodeFactory.createURI(value); - } else if ( type.equals("literal") ) { - if ( datatype != null ) { - return NodeFactory.createLiteral(value, TypeMapper.getInstance().getSafeTypeByName(datatype)); - } else if ( lang != null ) { - return NodeFactory.createLiteral(value, lang); - } else { - return NodeFactory.createLiteral(value); - } - } else if ( type.equals("bnode") ) { - return NodeFactory.createBlankNode(value); - } else { - exception(pos, "Encountered a Node object with an invalid type value '%s', expected one of uri, literal or bnode", type); - } - } else { - exception(peekToken(), "Unexpected Token, expected a { for the start of a Node object"); - } - return null; - } - - private String parseNodeInfo(String name) { - if ( lookingAt(TokenType.STRING) ) { - Token t = nextToken(); - String value = t.getImage(); - checkComma(TokenType.RBRACE); - return value; - } else { - exception(peekToken(), "Unexpected Token, expected a string as the value for the %s property", name); - return null; - } - } - - @Override - protected Binding moveToNextBinding() { - if ( !hasNext() ) - throw new NoSuchElementException(); - Binding b = this.binding; - this.binding = null; - return b; - } - - @Override - protected void closeIterator() { - IO.close(input); - input = null; - } - - @Override - protected void requestCancel() { - // Don't need to do anything special to cancel - // Superclass should take care of that and call closeIterator() where we - // do our actual clean up - } - - // JSON Parsing Helpers taken from LangRDFJSON - - private boolean isPropertyName() { - return lookingAt(TokenType.STRING); - } - - private Token checkValidForStringProperty(String property) { - Token t = null; - if ( lookingAt(TokenType.STRING) ) { - t = nextToken(); - } else { - exception(peekToken(), "JSON Values given for property " + property + " must be Strings"); - } - return t; - } - - private void checkColon() { - if ( !lookingAt(TokenType.COLON) ) { - exception(peekToken(), "Expected a : character after a JSON Property Name but got %s", peekToken()); - } - nextToken(); - } - - private void checkComma(TokenType terminator) { - if ( lookingAt(TokenType.COMMA) ) { - nextToken(); - } else if ( lookingAt(terminator) ) { - return; - } else { - exception(peekToken(), "Unexpected Token encountered, expected a , or a %s", terminator); - } - } - - // Streaming Parsing Helper Functions nicked from LangEngine - - // ---- Managing tokens. - - protected final Token peekToken() { - // Avoid repeating. - if ( eof() ) - return tokenEOF; - return peekIter.peek(); - } - - // Set when we get to EOF to record line/col of the EOF. - private Token tokenEOF = null; - - protected final boolean eof() { - if ( tokenEOF != null ) - return true; - - if ( !moreTokens() ) { - tokenEOF = new Token(tokens.getLine(), tokens.getColumn()); - tokenEOF.setType(TokenType.EOF); - return true; - } - return false; - } - - protected final boolean moreTokens() { - return peekIter.hasNext(); - } - - protected final boolean lookingAt(TokenType tokenType) { - if ( eof() ) - return tokenType == TokenType.EOF; - if ( tokenType == TokenType.NODE ) - return peekToken().isNode(); - return peekToken().hasType(tokenType); - } - - // Remember line/col of last token for messages - protected long currLine = -1; - protected long currCol = -1; - - protected final Token nextToken() { - if ( eof() ) - return tokenEOF; - - // Tokenizer errors appear here! - try { - Token t = peekIter.next(); - currLine = t.getLine(); - currCol = t.getColumn(); - return t; - } - catch (RiotParseException ex) { - // Intercept to log it. - raiseException(ex); - throw ex; - } - catch (AtlasException ex) { - // Bad I/O - RiotParseException ex2 = new RiotParseException(ex.getMessage(), -1, -1); - raiseException(ex2); - throw ex2; - } - } - - protected final void expectOrEOF(String msg, TokenType tokenType) { - // DOT or EOF - if ( eof() ) - return; - expect(msg, tokenType); - } - - protected final void expect(String msg, TokenType ttype) { - - if ( !lookingAt(ttype) ) { - Token location = peekToken(); - exception(location, msg); - } - nextToken(); - } - - protected final void exception(Token token, String msg, Object... args) { - if ( token != null ) - exceptionDirect(String.format(msg, args), token.getLine(), token.getColumn()); - else - exceptionDirect(String.format(msg, args), -1, -1); - } - - protected final void exceptionDirect(String msg, long line, long col) { - raiseException(new RiotParseException(msg, line, col)); - } - - protected final void raiseException(RiotParseException ex) { - throw new QueryException("Error passing SPARQL JSON results", ex); - } - -} http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutput.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutput.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutput.java index f894f80..9898d54 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutput.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutput.java @@ -21,22 +21,29 @@ package org.apache.jena.sparql.resultset; import java.io.OutputStream; import org.apache.jena.query.ResultSet; +import org.apache.jena.riot.resultset.ResultSetLang; +import org.apache.jena.riot.resultset.rw.ResultsWriter; +/** + * @deprecated Use ResultSetMgr.write(,,ResultSetLang.SPARQLResultSetJSON) + */ +@Deprecated public class JSONOutput extends OutputBase { public JSONOutput() {} @Override public void format(OutputStream out, ResultSet resultSet) { - // Use direct string output - more control - - JSONOutputResultSet jsonOut = new JSONOutputResultSet(out); - ResultSetApply a = new ResultSetApply(resultSet, jsonOut); - a.apply(); + ResultsWriter.create() + .lang(ResultSetLang.SPARQLResultSetJSON) + .build() + .write(out, resultSet); } @Override public void format(OutputStream out, boolean booleanResult) { - JSONOutputASK jsonOut = new JSONOutputASK(out); - jsonOut.exec(booleanResult); + ResultsWriter.create() + .lang(ResultSetLang.SPARQLResultSetJSON) + .build() + .write(out, booleanResult); } } http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputASK.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputASK.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputASK.java deleted file mode 100644 index 4b030e2..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputASK.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.sparql.resultset; - -import static org.apache.jena.sparql.resultset.JSONResultsKW.*; - -import java.io.OutputStream; - -import org.apache.jena.atlas.io.IO; -import org.apache.jena.atlas.json.io.JSWriter; - -/** JSON Output (ASK format) */ - -public class JSONOutputASK { - private OutputStream outStream; - - public JSONOutputASK(OutputStream outStream) { - this.outStream = outStream; - - } - - public void exec(boolean result) { - 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); - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputResultSet.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputResultSet.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputResultSet.java deleted file mode 100644 index ff86222..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONOutputResultSet.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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.sparql.resultset; - -import static org.apache.jena.sparql.resultset.JSONResultsKW.*; - -import java.io.OutputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -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; - -/** - * A JSON writer for SPARQL Result Sets. Uses Jena Atlas JSON support. - * - * Format: <a href="http://www.w3.org/TR/sparql11-results-json/">SPARQL 1.1 - * Query Results JSON Format</a> - */ - -public class JSONOutputResultSet implements ResultSetProcessor { - static boolean multiLineValues = false; - static boolean multiLineVarNames = false; - - private boolean outputGraphBNodeLabels = false; - private IndentedWriter out; - private int bNodeCounter = 0; - private Map<Resource, String> bNodeMap = new HashMap<>(); - - JSONOutputResultSet(OutputStream outStream) { - this(new IndentedWriter(outStream)); - } - - JSONOutputResultSet(IndentedWriter indentedOut) { - out = indentedOut; - outputGraphBNodeLabels = ARQ.isTrue(ARQ.outputGraphBNodeLabels); - } - - @Override - public void start(ResultSet rs) { - out.println("{"); - out.incIndent(); - doHead(rs); - out.println(quoteName(kResults) + ": {"); - out.incIndent(); - out.println(quoteName(kBindings) + ": ["); - out.incIndent(); - firstSolution = true; - } - - @Override - public void finish(ResultSet rs) { - // Close last binding. - out.println(); - - out.decIndent(); // bindings - out.println("]"); - out.decIndent(); - out.println("}"); // results - out.decIndent(); - out.println("}"); // top level {} - out.flush(); - } - - private void doHead(ResultSet rs) { - out.println(quoteName(kHead) + ": {"); - out.incIndent(); - doLink(rs); - doVars(rs); - out.decIndent(); - out.println("} ,"); - } - - private void doLink(ResultSet rs) { - // ---- link - // out.println("\"link\": []") ; - } - - private void doVars(ResultSet rs) { - // On one line. - out.print(quoteName(kVars) + ": [ "); - if ( multiLineVarNames ) - out.println(); - out.incIndent(); - for ( Iterator<String> iter = rs.getResultVars().iterator() ; iter.hasNext() ; ) { - String varname = iter.next(); - out.print("\"" + varname + "\""); - if ( multiLineVarNames ) - out.println(); - if ( iter.hasNext() ) - out.print(" , "); - } - out.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 ) - out.println(" ,"); - firstSolution = false; - out.println("{"); - out.incIndent(); - firstBindingInSolution = true; - } - - @Override - public void finish(QuerySolution qs) { - out.println(); // Finish last binding - out.decIndent(); - out.print("}"); // NB No newline - } - - @Override - public void binding(String varName, RDFNode value) { - if ( value == null ) - return; - - if ( !firstBindingInSolution ) - out.println(" ,"); - firstBindingInSolution = false; - - // Do not use quoteName - varName may not be JSON-safe as a bare name. - out.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 ) - out.print(" "); - out.print("}"); // NB No newline - } - - // private void printUnbound() - // { - // out.print(quoteName(kType)+ ": "+quote(kUnbound)+" , ") ; - // if ( multiLineValues ) out.println() ; - // out.print(quoteName(kValue)+": null") ; - // if ( multiLineValues ) out.println() ; - // } - - private void printLiteral(Literal literal) { - String datatype = literal.getDatatypeURI(); - String lang = literal.getLanguage(); - - if ( Util.isSimpleString(literal) || Util.isLangString(literal) ) { - out.print(quoteName(kType) + ": " + quote(kLiteral) + " , "); - if ( multiLineValues ) - out.println(); - - if ( lang != null && !lang.equals("") ) { - out.print(quoteName(kXmlLang) + ": " + quote(lang) + " , "); - if ( multiLineValues ) - out.println(); - } - } else { - out.print(quoteName(kType) + ": " + quote(kLiteral) + " , "); - if ( multiLineValues ) - out.println(); - - out.print(quoteName(kDatatype) + ": " + quote(datatype) + " , "); - if ( multiLineValues ) - out.println(); - } - - out.print(quoteName(kValue) + ": " + quote(literal.getLexicalForm())); - if ( multiLineValues ) - out.println(); - } - - private void printResource(Resource resource) { - if ( resource.isAnon() ) { - String label; - if ( outputGraphBNodeLabels ) - label = resource.getId().getLabelString(); - else { - if ( !bNodeMap.containsKey(resource) ) - bNodeMap.put(resource, "b" + (bNodeCounter++)); - label = bNodeMap.get(resource); - } - - out.print(quoteName(kType) + ": " + quote(kBnode) + " , "); - if ( multiLineValues ) - out.println(); - - out.print(quoteName(kValue) + ": " + quote(label)); - - if ( multiLineValues ) - out.println(); - } else { - out.print(quoteName(kType) + ": " + quote(kUri) + " , "); - if ( multiLineValues ) - out.println(); - out.print(quoteName(kValue) + ": " + quote(resource.getURI())); - if ( multiLineValues ) - out.println(); - return; - } - } - - private static String quote(String string) { - 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) { - // Safest to quote anyway. - return quote(string); - - // Assumes only called with safe names - // return string ; - - // Better would be: - // starts a-z, constains a-z,0-9, not a keyword(true, false, null) - // if ( string.contains(something not in a-z0-9) - // and - // //return "\""+string+"\"" ; - // return JSONObject.quote(string) ; - } - -} http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONResultsKW.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONResultsKW.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONResultsKW.java deleted file mode 100644 index 897ca6d..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/JSONResultsKW.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.sparql.resultset; - -//Keywords for JSON: -//Taken from: -//From http://www.w3.org/TR/sparql11-results-json/ (Oct 2011) - -public class JSONResultsKW -{ - public static String kHead = "head" ; - public static String kVars = "vars" ; - public static String kLink = "link" ; - public static String kResults = "results" ; - public static String kBindings = "bindings" ; - public static String kType = "type" ; - public static String kUri = "uri" ; - public static String kValue = "value" ; - public static String kLiteral = "literal" ; - // Legacy. - public static String kTypedLiteral = "typed-literal" ; - public static String kXmlLang = "xml:lang" ; - public static String kDatatype = "datatype" ; - public static String kBnode = "bnode" ; - public static String kBoolean = "boolean" ; -} - http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/SPARQLResult.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/SPARQLResult.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/SPARQLResult.java index fcabe74..77c7ae2 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/SPARQLResult.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/SPARQLResult.java @@ -18,13 +18,9 @@ package org.apache.jena.sparql.resultset; -import org.apache.jena.atlas.logging.Log; -import org.apache.jena.graph.Node; import org.apache.jena.query.Dataset; import org.apache.jena.query.ResultSet; import org.apache.jena.rdf.model.Model; -import org.apache.jena.sparql.core.Var; -import org.apache.jena.sparql.engine.binding.BindingMap; /** * The class "ResultSet" is reserved for the SELECT result format. This class @@ -95,7 +91,7 @@ public class SPARQLResult { return resultSet; } - public boolean getBooleanResult() { + public Boolean getBooleanResult() { if ( !hasBeenSet ) throw new ResultSetException("Not set"); if ( !isBoolean() ) @@ -146,18 +142,4 @@ public class SPARQLResult { booleanResult = r; hasBeenSet = true; } - - 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(SPARQLResult.class, - String.format("Multiple occurences of a binding for variable '%s' with different values - ignored", var.getName())); - return; - } - binding.add(var, value); - } - } http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInput.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInput.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInput.java index 192e4b3..469a466 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInput.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInput.java @@ -20,15 +20,17 @@ package org.apache.jena.sparql.resultset; import java.io.InputStream; import java.io.Reader; +import java.io.StringReader; import org.apache.jena.query.ResultSet; import org.apache.jena.rdf.model.Model; +import org.apache.jena.riot.resultset.rw.ResultsStAX; import org.apache.jena.sparql.SystemARQ; /** * Code that reads an XML Result Set and builds the ARQ structure for the same. */ - +@Deprecated public class XMLInput { public static ResultSet fromXML(InputStream in) { return fromXML(in, null); @@ -71,7 +73,7 @@ public class XMLInput { public static SPARQLResult make(InputStream in, Model model) { if ( SystemARQ.UseSAX ) return new XMLInputSAX(in, model); - return new XMLInputStAX(in, model); + return ResultsStAX.read(in, model, null); } public static SPARQLResult make(Reader in) { @@ -81,7 +83,7 @@ public class XMLInput { public static SPARQLResult make(Reader in, Model model) { if ( SystemARQ.UseSAX ) return new XMLInputSAX(in, model); - return new XMLInputStAX(in, model); + return ResultsStAX.read(in, model, null); } public static SPARQLResult make(String str) { @@ -91,7 +93,7 @@ public class XMLInput { public static SPARQLResult make(String str, Model model) { if ( SystemARQ.UseSAX ) return new XMLInputSAX(str, model); - return new XMLInputStAX(str, model); + return ResultsStAX.read(new StringReader(str), model, null); } } http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputSAX.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputSAX.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputSAX.java index cb3d160..e9952bf 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputSAX.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputSAX.java @@ -30,6 +30,9 @@ import org.apache.jena.datatypes.TypeMapper ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.NodeFactory ; import org.apache.jena.rdf.model.Model ; +import org.apache.jena.riot.lang.LabelToNode; +import org.apache.jena.riot.resultset.rw.XMLResults; +import org.apache.jena.riot.system.SyntaxLabels; import org.apache.jena.sparql.core.Var ; import org.apache.jena.sparql.engine.ResultSetStream ; import org.apache.jena.sparql.engine.binding.Binding ; @@ -38,7 +41,6 @@ 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.util.FmtUtils ; -import org.apache.jena.sparql.util.LabelToNodeMap ; import org.apache.jena.vocabulary.RDF ; import org.xml.sax.* ; import org.xml.sax.helpers.XMLReaderFactory ; @@ -102,7 +104,7 @@ class XMLInputSAX extends SPARQLResult { boolean askResult = false ; int rowCount = 0 ; - LabelToNodeMap bNodes = LabelToNodeMap.createBNodeMap() ; + LabelToNode bNodes = SyntaxLabels.createLabelToNode(); boolean accumulate = false ; StringBuffer buff = new StringBuffer() ; @@ -342,7 +344,7 @@ class XMLInputSAX extends SPARQLResult { private void endElementBNode(String ns, String localName, String name) { endAccumulate() ; String bnodeId = buff.toString() ; - Node node = bNodes.asNode(bnodeId) ; + Node node = bNodes.get(null, bnodeId) ; if ( checkVarName("BNode: " + bnodeId) ) addBinding(binding, Var.alloc(varName), node) ; } @@ -373,5 +375,20 @@ class XMLInputSAX extends SPARQLResult { @Override public void skippedEntity(String name) throws SAXException {} + + 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(SPARQLResult.class, + String.format("Multiple occurences of a binding for variable '%s' with different values - ignored", var.getName())); + return; + } + binding.add(var, value); + } + + } } http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputStAX.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputStAX.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputStAX.java deleted file mode 100644 index 78da74a..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLInputStAX.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * 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.sparql.resultset ; - -import java.io.InputStream ; -import java.io.Reader ; -import java.io.StringReader ; -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.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.util.LabelToNodeMap ; - -/** - * Code that reads an XML Results format and builds the ARQ structure for the - * same. Can read result set and boolean result forms. This is a streaming - * implementation. - */ - -class XMLInputStAX extends SPARQLResult { - private static final String XML_NS = ARQConstants.XML_NS ; - - public static ResultSet fromXML(InputStream in) { - return fromXML(in, null) ; - } - - public static ResultSet fromXML(InputStream in, Model model) { - XMLInputStAX x = new XMLInputStAX(in, model) ; - if ( !x.isResultSet() ) - throw new ResultSetException("Not a result set") ; - return x.getResultSet() ; - } - - public static ResultSet fromXML(String str) { - return fromXML(str, null) ; - - } - - public static ResultSet fromXML(String str, Model model) { - XMLInputStAX x = new XMLInputStAX(str, model) ; - if ( !x.isResultSet() ) - throw new ResultSetException("Not a result set") ; - return x.getResultSet() ; - } - - public static boolean booleanFromXML(InputStream in) { - XMLInputStAX x = new XMLInputStAX(in) ; - return x.getBooleanResult() ; - } - - public static boolean booleanFromXML(String str) { - XMLInputStAX x = new XMLInputStAX(str) ; - return x.getBooleanResult() ; - } - - public XMLInputStAX(InputStream in) { - this(in, null) ; - } - - public XMLInputStAX(InputStream in, Model model) { - XMLInputFactory xf = XMLInputFactory.newInstance() ; - try { - XMLStreamReader xReader = xf.createXMLStreamReader(in) ; - worker(xReader, model) ; - } 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 XMLInputStAX(Reader in, Model model) { - XMLInputFactory xf = XMLInputFactory.newInstance() ; - try { - XMLStreamReader xReader = xf.createXMLStreamReader(in) ; - worker(xReader, model) ; - } 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 XMLInputStAX(String str) { - this(str, null) ; - } - - public XMLInputStAX(String str, Model model) { - XMLInputFactory xf = XMLInputFactory.newInstance() ; - try { - Reader r = new StringReader(str) ; - XMLStreamReader xReader = xf.createXMLStreamReader(r) ; - worker(xReader, model) ; - } 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 void worker(XMLStreamReader xReader, Model model) { - if ( model == null ) - model = GraphFactory.makeJenaDefaultModel() ; - - ResultSetStAX rss = new ResultSetStAX(xReader, model) ; - if ( rss.isResultSet ) - set(rss) ; - else - set(rss.askResult) ; - } - - // private XMLInputStAX() - - // -------- Result Set - - static class ResultSetStAX implements ResultSet, Closeable { - // ResultSet variables - QuerySolution current = null ; - XMLStreamReader parser = null ; - List<String> variables = new ArrayList<>() ; - Binding binding = null ; // Current - // binding - // RefBoolean inputGraphLabels = new - // RefBoolean(ARQ.inputGraphBNodeLabels, false) ; - boolean inputGraphLabels = ARQ.isTrue(ARQ.inputGraphBNodeLabels) ; - - LabelToNodeMap bNodes = LabelToNodeMap.createBNodeMap() ; - - // Type - boolean isResultSet = false ; - - // Result set - boolean ordered = false ; - boolean distinct = false ; - boolean finished = false ; - Model model = null ; - int row = 0 ; - - // boolean - boolean askResult = false ; - - ResultSetStAX(XMLStreamReader reader, Model model) { - parser = reader ; - this.model = model ; - init() ; - } - - 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(XMLInputStAX.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 ; - } - - 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.asNode(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 ; - } - - 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) ; - } - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutput.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutput.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutput.java index a30d5ae..48e85f1 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutput.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutput.java @@ -20,8 +20,12 @@ package org.apache.jena.sparql.resultset; import java.io.OutputStream ; +import org.apache.jena.query.ARQ; import org.apache.jena.query.ResultSet ; - +import org.apache.jena.riot.resultset.ResultSetLang; +import org.apache.jena.riot.resultset.rw.ResultSetWriterXML; +import org.apache.jena.riot.resultset.rw.ResultsWriter; +import org.apache.jena.sparql.util.Context; public class XMLOutput extends OutputBase { @@ -45,11 +49,14 @@ public class XMLOutput extends OutputBase @Override public void format(OutputStream out, ResultSet resultSet) { - XMLOutputResultSet xOut = new XMLOutputResultSet(out); - xOut.setStylesheetURL(stylesheetURL); - xOut.setXmlInst(includeXMLinst); - ResultSetApply a = new ResultSetApply(resultSet, xOut); - a.apply(); + Context cxt = ARQ.getContext().copy(); + if ( stylesheetURL != null ) + cxt.set(ResultSetWriterXML.xmlStylesheet, stylesheetURL); + cxt.set(ResultSetWriterXML.xmlInstruction, includeXMLinst); + ResultsWriter.create() + .context(cxt) + .lang(ResultSetLang.SPARQLResultSetXML) + .write(out, resultSet); } /** @return Returns the includeXMLinst. */ @@ -70,7 +77,14 @@ public class XMLOutput extends OutputBase @Override public void format(OutputStream out, boolean booleanResult) { - XMLOutputASK xOut = new XMLOutputASK(out); - xOut.exec(booleanResult); + Context cxt = ARQ.getContext().copy(); + if ( stylesheetURL != null ) + cxt.set(ResultSetWriterXML.xmlStylesheet, stylesheetURL); + cxt.set(ResultSetWriterXML.xmlInstruction, includeXMLinst); + ResultsWriter.create() + .context(cxt) + .lang(ResultSetLang.SPARQLResultSetXML) + .build() + .write(out, booleanResult); } } http://git-wip-us.apache.org/repos/asf/jena/blob/716b86cf/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutputASK.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutputASK.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutputASK.java deleted file mode 100644 index 66ffe81..0000000 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/XMLOutputASK.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.sparql.resultset; - -import java.io.OutputStream; - -import org.apache.jena.atlas.io.IndentedWriter; - -/** XML Output (ASK format) */ - -public 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(); - } -}
