// Copyright (c) 2011. This source code is available under the terms of the GNU Lesser General Public License (LGPL) // Author: Mario Volke <[email protected]> // derivo GmbH, James-Franck-Ring, 89081 Ulm package de.derivo.sparqldlapi.impl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import org.jdom.Document; import org.jdom.Element; import org.jdom.Namespace; import de.derivo.sparqldlapi.Query; import de.derivo.sparqldlapi.QueryArgument; import de.derivo.sparqldlapi.QueryBinding; import de.derivo.sparqldlapi.QueryResult; /** * Concrete implementation of the QueryResult interface. * * @author Mario Volke */ public class QueryResultImpl implements QueryResult { private List<QueryBindingImpl> bindings; private boolean ask; private Query query; public QueryResultImpl(Query query) { bindings = new ArrayList<QueryBindingImpl>(); ask = true; this.query = query; } /** * Get the query that belongs to this result. * * @return */ public Query getQuery() { return query; } /** * Add a binding to the result set. * * @param binding */ public void add(QueryBindingImpl binding) { ask = true; bindings.add(binding); } /** * Set whether the query has a solution or not. * * @param s */ public void setAsk(boolean s) { ask = s; } /** * Ask if the query had a solution. * This is the only result you get if the query was of type ASK. * This could also be true if the result set is empty. * * @return True if the query had a solution. */ public boolean ask() { return ask; } /** * An iterator over the result set. * * @return */ public Iterator<QueryBinding> iterator() { List<QueryBinding> iBindings = new ArrayList<QueryBinding>(); for(QueryBindingImpl b : bindings) { iBindings.add(b); } return iBindings.iterator(); } public List<QueryBindingImpl> getBindings() { return bindings; } /** * Get the size of the result set. * * @return The size of the result set. */ public int size() { return bindings.size(); } /** * Returns the QueryBinding at the specified position of the result. * * @param index * @return The QueryBinding at the specified position. */ public QueryBinding get(int index) { return (QueryBinding)bindings.get(index); } /** * Check whether the result set is empty. * * @return True if the result set is empty. */ public boolean isEmpty() { return bindings.isEmpty(); } /** * Output query results as JDOM XML document containing the standard * SPARQL query results XML format (http://www.w3.org/TR/rdf-sparql-XMLres/). * Supports both: Variable binding results and Boolean results. * * @return A JDOM XML document. */ public Document toXML() { Element sparql = new Element("sparql"); sparql.setNamespace(Namespace.getNamespace("http://www.w3.org/2005/sparql-results#")); // generate head Element head = new Element("head"); if(!bindings.isEmpty()) { QueryBinding top = bindings.get(0); for(QueryArgument arg : top.getBoundArgs()) { if(arg.isVar()) { Element var = new Element("variable"); var.setAttribute("name", arg.getValueAsString()); head.addContent(var); } } } sparql.addContent(head); if(query.isAsk()) { Element booleanElement = new Element("boolean"); if(ask) { booleanElement.setText("true"); } else { booleanElement.setText("false"); } sparql.addContent(booleanElement); } else { // otherwise generate results Element results = new Element("results"); for(QueryBinding binding : bindings) { Element result = new Element("result"); for(QueryArgument key : binding.getBoundArgs()) { if(key.isVar()) { Element b = new Element("binding"); b.setAttribute("name", key.getValueAsString()); QueryArgument value = binding.get(key); switch(value.getType()) { case URI: Element uri = new Element("uri"); uri.setText(value.getValueAsIRI().toString()); b.addContent(uri); break; case LITERAL: Element literal = new Element("literal"); literal.setText(value.getValueAsLiteral().getLiteral()); b.addContent(literal); break; case BNODE: Element bnode = new Element("bnode"); bnode.setText(value.getValueAsBNode().getID().toString()); b.addContent(bnode); break; default: } result.addContent(b); } } results.addContent(result); } sparql.addContent(results); } return new Document(sparql); } /** * Output query results in JSON format as standardized in http://www.w3.org/TR/rdf-sparql-json-res/. * Supports both: Variable binding results and Boolean results. * * @return The JSON result as string. */ public String toJSON() { StringBuffer sb = new StringBuffer(); sb.append("{\n"); // generate head sb.append("\t\"head\": {\n"); if(!bindings.isEmpty()) { sb.append("\t\t\"vars\": [\n"); QueryBinding top = bindings.get(0); boolean first = true; for(QueryArgument arg : top.getBoundArgs()) { if(arg.isVar()) { if(first) { first = false; } else { sb.append(",\n"); } sb.append("\t\t\t\""); sb.append(arg.getValueAsString()); sb.append("\""); } } sb.append("\n\t\t]\n"); } sb.append("\t},\n"); if(query.isAsk()) { if(ask) { sb.append("\t\"boolean\": true\n"); } else { sb.append("\t\"boolean\": false\n"); } } else { // otherwise generate results sb.append("\t\"results\": {\n"); sb.append("\t\t\"bindings\": [\n"); boolean firstBinding = true; for(QueryBinding binding : bindings) { if(firstBinding) { firstBinding = false; } else { sb.append(",\n"); } sb.append("\t\t\t{\n"); boolean firstVar = true; for(QueryArgument key : binding.getBoundArgs()) { if(key.isVar()) { if(firstVar) { firstVar = false; } else { sb.append(",\n"); } sb.append("\t\t\t\t\""); sb.append(key.getValueAsString()); sb.append("\": {\n"); QueryArgument value = binding.get(key); switch(value.getType()) { case URI: sb.append("\t\t\t\t\t\"type\": \"uri\",\n"); sb.append("\t\t\t\t\t\"value\": \""); sb.append(value.getValueAsIRI().toString().replaceAll("\"", "\\\\\"")); sb.append("\"\n"); break; case LITERAL: sb.append("\t\t\t\t\t\"type\": \"literal\",\n"); sb.append("\t\t\t\t\t\"value\": \""); sb.append(value.getValueAsLiteral().getLiteral().replaceAll("\"", "\\\\\"")); sb.append("\"\n"); break; case BNODE: sb.append("\t\t\t\t\t\"type\": \"bnode\",\n"); sb.append("\t\t\t\t\t\"value\": \""); sb.append(value.getValueAsBNode().getID().toString().replaceAll("\"", "\\\\\"")); sb.append("\"\n"); break; default: } sb.append("\t\t\t\t}"); } } sb.append("\n\t\t\t}"); } sb.append("\n\t\t]\n\t}\n"); } sb.append("}\n"); return sb.toString(); } /** * Use this method for debugging purposes. * This is no standard format like SPARQL-XML or JSON. * * @return A nicely formatted string containing the results and bindings. */ public String toString() { StringBuffer sb = new StringBuffer(); for(QueryBinding binding : bindings) { Set<QueryArgument> keys = binding.getBoundArgs(); boolean first = true; for(QueryArgument key : keys) { if(first) { first = false; } else { sb.append(','); sb.append(' '); } sb.append(key.toString()); sb.append(' '); sb.append('='); sb.append(' '); sb.append(binding.get(key).toString()); } sb.append('\n'); } return sb.toString(); } }