001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.query.resultio.sparqljson;
007:
008: import java.io.BufferedWriter;
009: import java.io.IOException;
010: import java.io.OutputStream;
011: import java.io.OutputStreamWriter;
012: import java.io.Writer;
013: import java.nio.charset.Charset;
014: import java.util.Iterator;
015: import java.util.List;
016:
017: import info.aduna.io.IndentingWriter;
018: import info.aduna.text.StringUtil;
019:
020: import org.openrdf.model.BNode;
021: import org.openrdf.model.Literal;
022: import org.openrdf.model.URI;
023: import org.openrdf.model.Value;
024: import org.openrdf.query.Binding;
025: import org.openrdf.query.BindingSet;
026: import org.openrdf.query.TupleQueryResultHandlerException;
027: import org.openrdf.query.resultio.TupleQueryResultFormat;
028: import org.openrdf.query.resultio.TupleQueryResultWriter;
029:
030: /**
031: * A TupleQueryResultWriter that writes query results in the <a
032: * href="http://www.w3.org/TR/rdf-sparql-json-res/">SPARQL Query Results JSON
033: * Format</a>.
034: */
035: public class SPARQLResultsJSONWriter implements TupleQueryResultWriter {
036:
037: /*-----------*
038: * Variables *
039: *-----------*/
040:
041: private IndentingWriter writer;
042:
043: private boolean firstTupleWritten;
044:
045: /*--------------*
046: * Constructors *
047: *--------------*/
048:
049: public SPARQLResultsJSONWriter(OutputStream out) {
050: Writer w = new OutputStreamWriter(out, Charset.forName("UTF-8"));
051: w = new BufferedWriter(w, 1024);
052: writer = new IndentingWriter(w);
053: }
054:
055: /*---------*
056: * Methods *
057: *---------*/
058:
059: public final TupleQueryResultFormat getTupleQueryResultFormat() {
060: return TupleQueryResultFormat.JSON;
061: }
062:
063: public void startQueryResult(List<String> columnHeaders)
064: throws TupleQueryResultHandlerException {
065: try {
066: openBraces();
067:
068: // Write header
069: writeKey("head");
070: openBraces();
071: writeKeyValue("vars", columnHeaders);
072: closeBraces();
073:
074: writeComma();
075:
076: // Write results
077: writeKey("results");
078: openBraces();
079:
080: writeKey("bindings");
081: openArray();
082:
083: firstTupleWritten = false;
084: } catch (IOException e) {
085: throw new TupleQueryResultHandlerException(e);
086: }
087: }
088:
089: public void endQueryResult()
090: throws TupleQueryResultHandlerException {
091: try {
092: closeArray(); // bindings array
093: closeBraces(); // results braces
094: closeBraces(); // root braces
095: writer.flush();
096: } catch (IOException e) {
097: throw new TupleQueryResultHandlerException(e);
098: }
099: }
100:
101: public void handleSolution(BindingSet bindingSet)
102: throws TupleQueryResultHandlerException {
103: try {
104: if (firstTupleWritten) {
105: writeComma();
106: } else {
107: firstTupleWritten = true;
108: }
109:
110: openBraces(); // start of new solution
111:
112: Iterator<Binding> bindingIter = bindingSet.iterator();
113: while (bindingIter.hasNext()) {
114: Binding binding = bindingIter.next();
115:
116: writeKeyValue(binding.getName(), binding.getValue());
117:
118: if (bindingIter.hasNext()) {
119: writeComma();
120: }
121: }
122:
123: closeBraces(); // end solution
124:
125: writer.flush();
126: } catch (IOException e) {
127: throw new TupleQueryResultHandlerException(e);
128: }
129: }
130:
131: private void writeKeyValue(String key, String value)
132: throws IOException {
133: writeKey(key);
134: writeString(value);
135: }
136:
137: private void writeKeyValue(String key, Value value)
138: throws IOException, TupleQueryResultHandlerException {
139: writeKey(key);
140: writeValue(value);
141: }
142:
143: private void writeKeyValue(String key, Iterable<String> array)
144: throws IOException {
145: writeKey(key);
146: writeArray(array);
147: }
148:
149: private void writeKey(String key) throws IOException {
150: writeString(key);
151: writer.write(": ");
152: }
153:
154: private void writeValue(Value value) throws IOException,
155: TupleQueryResultHandlerException {
156: writer.write("{ ");
157:
158: if (value instanceof URI) {
159: writeKeyValue("type", "uri");
160: writer.write(", ");
161: writeKeyValue("value", ((URI) value).toString());
162: } else if (value instanceof BNode) {
163: writeKeyValue("type", "bnode");
164: writer.write(", ");
165: writeKeyValue("value", ((BNode) value).getID());
166: } else if (value instanceof Literal) {
167: Literal lit = (Literal) value;
168:
169: if (lit.getDatatype() != null) {
170: writeKeyValue("type", "typed-literal");
171: writer.write(", ");
172: writeKeyValue("datatype", lit.getDatatype().toString());
173: } else {
174: writeKeyValue("type", "literal");
175: if (lit.getLanguage() != null) {
176: writer.write(", ");
177: writeKeyValue("xml:lang", lit.getLanguage());
178: }
179: }
180:
181: writer.write(", ");
182: writeKeyValue("value", lit.getLabel());
183: } else {
184: throw new TupleQueryResultHandlerException(
185: "Unknown Value object type: " + value.getClass());
186: }
187:
188: writer.write(" }");
189: }
190:
191: private void writeString(String value) throws IOException {
192: // Escape special characters
193: value = StringUtil.gsub("\\", "\\\\", value);
194: value = StringUtil.gsub("\"", "\\\"", value);
195: value = StringUtil.gsub("/", "\\/", value);
196: value = StringUtil.gsub("\b", "\\b", value);
197: value = StringUtil.gsub("\f", "\\f", value);
198: value = StringUtil.gsub("\n", "\\n", value);
199: value = StringUtil.gsub("\r", "\\r", value);
200: value = StringUtil.gsub("\t", "\\t", value);
201:
202: writer.write("\"");
203: writer.write(value);
204: writer.write("\"");
205: }
206:
207: private void writeArray(Iterable<String> array) throws IOException {
208: writer.write("[ ");
209:
210: Iterator<String> iter = array.iterator();
211: while (iter.hasNext()) {
212: String value = iter.next();
213:
214: writeString(value);
215:
216: if (iter.hasNext()) {
217: writer.write(", ");
218: }
219: }
220:
221: writer.write(" ]");
222: }
223:
224: private void openArray() throws IOException {
225: writer.write("[");
226: writer.writeEOL();
227: writer.increaseIndentation();
228: }
229:
230: private void closeArray() throws IOException {
231: writer.writeEOL();
232: writer.decreaseIndentation();
233: writer.write("]");
234: }
235:
236: private void openBraces() throws IOException {
237: writer.write("{");
238: writer.writeEOL();
239: writer.increaseIndentation();
240: }
241:
242: private void closeBraces() throws IOException {
243: writer.writeEOL();
244: writer.decreaseIndentation();
245: writer.write("}");
246: }
247:
248: private void writeComma() throws IOException {
249: writer.write(", ");
250: writer.writeEOL();
251: }
252: }
|