/*
* Copyright 2008 Fedora Commons, Inc.
*
* Licensed 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.mulgara.protocol;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Map;
import org.mulgara.query.Answer;
import org.mulgara.query.TuplesException;
/**
* Represents a data object as JSON.
*
* @created Jul 8, 2008
* @author Paula Gearon
* @copyright © 2008 <a href="http://www.fedora-commons.org/">Fedora Commons</a>
*/
public class StreamedSparqlJSONObject implements StreamedAnswer {
/** The encoded data. */
final Object objectData;
/** The writer used for creating the XML. */
protected OutputStreamWriter s = null;
/** The byte output stream used for creating the XML. */
protected OutputStream output = null;
/**
* Creates an XML object encoding.
* @param objectData The data to encode.
* @param output Where to send the output.
*/
public StreamedSparqlJSONObject(Object objectData, OutputStream output) {
this.objectData = objectData;
this.output = output;
}
/**
* Put the parts of the document together, and close the stream.
* @see org.mulgara.protocol.StreamedXMLAnswer#emit()
*/
public void emit() throws IOException {
s = new OutputStreamWriter(output);
s.append("{ \"data\": ");
s.append(jsonEscape(objectData));
s.append(" }");
s.flush();
}
/**
* Create a JSON string for a single Map object.
* @param o The object to convert to a JSON string.
* @return The JSON string representing the parameter.
*/
static String jsonHash(Map<?,?> o) {
StringBuilder s = new StringBuilder("{ ");
boolean first = true;
for (Map.Entry<?,?> entry: o.entrySet()) {
if (!first) s.append(", ");
else first = false;
s.append("\"");
s.append(entry.getKey());
s.append("\": ");
s.append(jsonEscape(entry.getValue()));
}
s.append(" }");
return s.toString();
}
/** Trivial escaping. */
static String jsonEscape(Object o) {
if (o instanceof Number) return o.toString();
if (o instanceof Map<?,?>) return jsonHash((Map<?,?>)o);
String data = o.toString();
data = data.replace("\"", "\\\"");
data = data.replace("\\", "\\\\");
data = data.replace("/", "\\/");
data = data.replace("\b", "\\b");
data = data.replace("\f", "\\f");
data = data.replace("\n", "\\n");
data = data.replace("\r", "\\r");
data = data.replace("\t", "\\t");
return "\"" + data + "\"";
}
public void addAnswer(Answer data) throws TuplesException, IOException {
throw new UnsupportedOperationException();
}
public void addDocFooter() throws IOException {
throw new UnsupportedOperationException();
}
public void addDocHeader() throws IOException {
throw new UnsupportedOperationException();
}
public void close() throws IOException {
s.flush();
output.close();
}
/**
* Not to be called for when doing an "emit". Only used when more manual control is needed
* due to streaming multiple answers.
*/
public void initOutput() {
if (s == null) s = new OutputStreamWriter(output);
}
}