All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.rdf.rio.json.SPARQLJSONParserBase Maven / Gradle / Ivy

/* 
 * Licensed to Aduna under one or more contributor license agreements.  
 * See the NOTICE.txt file distributed with this work for additional 
 * information regarding copyright ownership. 
 *
 * Aduna licenses this file to you under the terms of the Aduna BSD 
 * License (the "License"); you may not use this file except in compliance 
 * with the License. See the LICENSE.txt file distributed with this work 
 * for the full License.
 *
 * 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 com.bigdata.rdf.rio.json;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryResultHandlerException;
import org.openrdf.query.impl.MapBindingSet;
import org.openrdf.query.resultio.QueryResultParseException;
import org.openrdf.query.resultio.QueryResultParserBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

/**
 * Abstract base class for SPARQL Results JSON Parsers. Provides a common
 * implementation of both boolean and tuple parsing.
 * 

* Bigdata Changes: *

    *
  • Changed the visibility of the method parseValue() from private to * protected so we could override it.
  • *
  • Pulled some code out of parseQueryResultInternal into its own method so * that we can override it.
  • *
* * @author Peter Ansell * @author Sebastian Schaffert */ public abstract class SPARQLJSONParserBase extends QueryResultParserBase { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final JsonFactory JSON_FACTORY = new JsonFactory(); static { JSON_FACTORY.disable(JsonFactory.Feature.INTERN_FIELD_NAMES); JSON_FACTORY.disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES); JSON_FACTORY.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); } public static final String HEAD = "head"; public static final String LINK = "link"; public static final String VARS = "vars"; public static final String BOOLEAN = "boolean"; public static final String RESULTS = "results"; public static final String BINDINGS = "bindings"; public static final String TYPE = "type"; public static final String VALUE = "value"; public static final String XMLLANG = "xml:lang"; public static final String DATATYPE = "datatype"; public static final String LITERAL = "literal"; public static final String TYPED_LITERAL = "typed-literal"; public static final String BNODE = "bnode"; public static final String URI = "uri"; /** * Backwards compatibility with very early version of original SPARQL spec. */ private static final String DISTINCT = "distinct"; /** * Backwards compatibility with very early version of original SPARQL spec. */ private static final String ORDERED = "ordered"; /** * */ public SPARQLJSONParserBase() { super(); } /** * */ public SPARQLJSONParserBase(ValueFactory valueFactory) { super(valueFactory); } @Override public void parseQueryResult(InputStream in) throws IOException, QueryResultParseException, QueryResultHandlerException { parseQueryResultInternal(in, true, true); } protected boolean parseQueryResultInternal(InputStream in, boolean attemptParseBoolean, boolean attemptParseTuple) throws IOException, QueryResultParseException, QueryResultHandlerException { if (!attemptParseBoolean && !attemptParseTuple) { throw new IllegalArgumentException( "Internal error: Did not specify whether to parse as either boolean and/or tuple"); } JsonParser jp = JSON_FACTORY.createParser(in); boolean result = false; if (jp.nextToken() != JsonToken.START_OBJECT) { throw new QueryResultParseException("Expected SPARQL Results JSON document to start with an Object", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } List varsList = new ArrayList(); boolean varsFound = false; Set bindings = new HashSet(); while (jp.nextToken() != JsonToken.END_OBJECT) { final String baseStr = jp.getCurrentName(); if (baseStr.equals(HEAD)) { if (jp.nextToken() != JsonToken.START_OBJECT) { throw new QueryResultParseException("Did not find object under " + baseStr + " field", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } while (jp.nextToken() != JsonToken.END_OBJECT) { final String headStr = jp.getCurrentName(); if (headStr.equals(VARS)) { if (!attemptParseTuple) { throw new QueryResultParseException( "Found tuple results variables when attempting to parse SPARQL Results JSON to boolean result"); } if (jp.nextToken() != JsonToken.START_ARRAY) { throw new QueryResultParseException("Expected variable labels to be an array", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } while (jp.nextToken() != JsonToken.END_ARRAY) { varsList.add(jp.getText()); } if (this.handler != null) { handler.startQueryResult(varsList); } varsFound = true; // If the bindings were populated before this point push them // out now. if (!bindings.isEmpty() && this.handler != null) { for (BindingSet nextBinding : bindings) { handler.handleSolution(nextBinding); handler.endQueryResult(); } bindings.clear(); } } else if (headStr.equals(LINK)) { List linksList = new ArrayList(); if (jp.nextToken() != JsonToken.START_ARRAY) { throw new QueryResultParseException("Expected links to be an array", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } while (jp.nextToken() != JsonToken.END_ARRAY) { linksList.add(jp.getText()); } if (this.handler != null) { handler.handleLinks(linksList); } } else { throw new QueryResultParseException("Found unexpected object in head field: " + headStr, jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } } } else if (baseStr.equals(RESULTS)) { if (!attemptParseTuple) { throw new QueryResultParseException( "Found tuple results bindings when attempting to parse SPARQL Results JSON to boolean result"); } if (jp.nextToken() != JsonToken.START_OBJECT) { throw new QueryResultParseException("Found unexpected token in results object: " + jp.getCurrentName(), jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } while (jp.nextToken() != JsonToken.END_OBJECT) { if (jp.getCurrentName().equals(BINDINGS)) { if (jp.nextToken() != JsonToken.START_ARRAY) { throw new QueryResultParseException("Found unexpected token in bindings object", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } while (jp.nextToken() != JsonToken.END_ARRAY) { MapBindingSet nextBindingSet = new MapBindingSet(); if (jp.getCurrentToken() != JsonToken.START_OBJECT) { throw new QueryResultParseException("Did not find object in bindings array: " + jp.getCurrentName(), jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } while (jp.nextToken() != JsonToken.END_OBJECT) { if (jp.getCurrentToken() != JsonToken.FIELD_NAME) { throw new QueryResultParseException("Did not find binding name", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } final String bindingStr = jp.getCurrentName(); if (jp.nextToken() != JsonToken.START_OBJECT) { throw new QueryResultParseException("Did not find object for binding value", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start Bigdata Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ final Value value = parseValue(bindingStr, jp); nextBindingSet.addBinding(bindingStr, value); // String lang = null; // String type = null; // String datatype = null; // String value = null; // // while (jp.nextToken() != JsonToken.END_OBJECT) { // // if (jp.getCurrentToken() != JsonToken.FIELD_NAME) { // throw new QueryResultParseException("Did not find value attribute under " // + bindingStr + " field", jp.getCurrentLocation().getLineNr(), // jp.getCurrentLocation().getColumnNr()); // } // String fieldName = jp.getCurrentName(); // // // move to the value token // jp.nextToken(); // // // set the appropriate state variable // if (TYPE.equals(fieldName)) { // type = jp.getText(); // } // else if (XMLLANG.equals(fieldName)) { // lang = jp.getText(); // } // else if (DATATYPE.equals(fieldName)) { // datatype = jp.getText(); // } // else if (VALUE.equals(fieldName)) { // value = jp.getText(); // } // else { // throw new QueryResultParseException("Unexpected field name: " + fieldName, // jp.getCurrentLocation().getLineNr(), // jp.getCurrentLocation().getColumnNr()); // // } // } // // nextBindingSet.addBinding(bindingStr, parseValue(type, value, lang, datatype)); /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Bigdata Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ } // parsing of solution finished, report result return to // bindings state if (!varsFound) { // Buffer the bindings to fit with the // QueryResultHandler contract so that startQueryResults // is // always called before handleSolution bindings.add(nextBindingSet); } else if (handler != null) { handler.handleSolution(nextBindingSet); } } if (handler != null) { handler.endQueryResult(); } } // Backwards compatibility with very old draft of the original // SPARQL spec else if (jp.getCurrentName().equals(DISTINCT) || jp.getCurrentName().equals(ORDERED)) { jp.nextToken(); } else { throw new QueryResultParseException("Found unexpected field in results: " + jp.getCurrentName(), jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } } } else if (baseStr.equals(BOOLEAN)) { if (!attemptParseBoolean) { throw new QueryResultParseException( "Found boolean results when attempting to parse SPARQL Results JSON to tuple results"); } jp.nextToken(); result = Boolean.parseBoolean(jp.getText()); if (handler != null) { handler.handleBoolean(result); } } else { throw new QueryResultParseException("Found unexpected object in top level " + baseStr + " field", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } } return result; } /** * New method added to support Bigdata Sid extension. */ protected Value parseValue(final String bindingStr, final JsonParser jp) throws QueryResultParseException, JsonParseException, IOException { String lang = null; String type = null; String datatype = null; String value = null; while (jp.nextToken() != JsonToken.END_OBJECT) { if (jp.getCurrentToken() != JsonToken.FIELD_NAME) { throw new QueryResultParseException("Did not find value attribute under " + bindingStr + " field", jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } String fieldName = jp.getCurrentName(); // move to the value token jp.nextToken(); // set the appropriate state variable if (TYPE.equals(fieldName)) { type = jp.getText(); } else if (XMLLANG.equals(fieldName)) { lang = jp.getText(); } else if (DATATYPE.equals(fieldName)) { datatype = jp.getText(); } else if (VALUE.equals(fieldName)) { value = jp.getText(); } else { throw new QueryResultParseException("Unexpected field name: " + fieldName, jp.getCurrentLocation().getLineNr(), jp.getCurrentLocation().getColumnNr()); } } return parseValue(type, value, lang, datatype); } /** * Parse a value out of the elements for a binding. * * @param type * {@link #LITERAL}, {@link #TYPED_LITERAL}, {@link #BNODE} or * {@link #URI} * @param value * actual value text * @param language * language tag, if applicable * @param datatype * datatype tag, if applicable * @return the value corresponding to the given parameters */ protected Value parseValue(String type, String value, String language, String datatype) { logger.trace("type: {}", type); logger.trace("value: {}", value); logger.trace("language: {}", language); logger.trace("datatype: {}", datatype); Value result = null; if (type.equals(LITERAL) || type.equals(TYPED_LITERAL)) { if (language != null) { result = valueFactory.createLiteral(value, language); } else if (datatype != null) { result = valueFactory.createLiteral(value, valueFactory.createURI(datatype)); } else { result = valueFactory.createLiteral(value); } } else if (type.equals(BNODE)) { result = valueFactory.createBNode(value); } else if (type.equals(URI)) { result = valueFactory.createURI(value); } logger.debug("result value: {}", result); return result; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy