package eu.fbk.knowledgestore.internal.rdf;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import org.openrdf.model.impl.BooleanLiteralImpl;
import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryResultHandlerException;
import org.openrdf.query.TupleQueryResultHandlerException;
import org.openrdf.query.resultio.BooleanQueryResultFormat;
import org.openrdf.query.resultio.BooleanQueryResultWriter;
import org.openrdf.query.resultio.BooleanQueryResultWriterFactory;
import org.openrdf.query.resultio.QueryResultFormat;
import org.openrdf.query.resultio.QueryResultWriterBase;
import org.openrdf.query.resultio.TupleQueryResultFormat;
import org.openrdf.query.resultio.TupleQueryResultWriter;
import org.openrdf.query.resultio.TupleQueryResultWriterFactory;
public class HtmlSparql implements BooleanQueryResultWriterFactory, TupleQueryResultWriterFactory {
public static final TupleQueryResultFormat TUPLE_FORMAT = new TupleQueryResultFormat(
"HTML/TUPLE", "text/html", Charsets.UTF_8, "html");
public static final BooleanQueryResultFormat BOOLEAN_FORMAT = new BooleanQueryResultFormat(
"HTML/BOOLEAN", "text/html", Charsets.UTF_8, "html");
static {
TupleQueryResultFormat.register(TUPLE_FORMAT);
BooleanQueryResultFormat.register(BOOLEAN_FORMAT);
}
public static void register() {
// calling this method will cause the static initializer to run once
}
@Override
public TupleQueryResultFormat getTupleQueryResultFormat() {
return TUPLE_FORMAT;
}
@Override
public BooleanQueryResultFormat getBooleanQueryResultFormat() {
return BOOLEAN_FORMAT;
}
@Override
public HtmlWriter getWriter(final OutputStream out) {
return new HtmlWriter(new OutputStreamWriter(out, Charsets.UTF_8));
}
private static final class HtmlWriter extends QueryResultWriterBase implements
BooleanQueryResultWriter, TupleQueryResultWriter {
private final Writer writer;
private final Map<String, String> prefixes;
private List<String> variables;
HtmlWriter(final Writer writer) {
this.writer = writer;
this.prefixes = Maps.newHashMap();
this.variables = null;
}
@Override
public QueryResultFormat getQueryResultFormat() {
return TUPLE_FORMAT;
}
@Override
public TupleQueryResultFormat getTupleQueryResultFormat() {
return TUPLE_FORMAT;
}
@Override
public BooleanQueryResultFormat getBooleanQueryResultFormat() {
return BOOLEAN_FORMAT;
}
@Override
public void handleNamespace(final String prefix, final String uri) {
this.prefixes.put(uri, prefix);
}
@Override
public void startDocument() throws QueryResultHandlerException {
try {
this.writer.append("<html>\n<head>\n<meta http-equiv=\"Content-type\" "
+ "content=\"text/html;charset=UTF-8\"/>\n");
} catch (final IOException ex) {
throw new QueryResultHandlerException(ex);
}
}
@Override
public void handleStylesheet(final String stylesheetUrl) {
}
@Override
public void startHeader() {
}
@Override
public void handleLinks(final List<String> linkURLs) throws QueryResultHandlerException {
try {
for (final String linkURL : linkURLs) {
this.writer.append("<link rel=\"nofollow\" href=\"" + linkURL + "\">\n");
}
} catch (final IOException ex) {
throw new QueryResultHandlerException(ex);
}
}
@Override
public void endHeader() {
}
@Override
public void write(final boolean value) {
throw new UnsupportedOperationException();
}
@Override
public void handleBoolean(final boolean value) throws QueryResultHandlerException {
try {
this.writer.append("</head>\n<body>\n"//
+ "<table class=\"sparql\">\n<thead>\n" //
+ "<tr><th>boolean</th></tr>\n" //
+ "</thead>\n<tbody>\n" //
+ "<tr><td>");
RDFUtil.toHtml(value ? BooleanLiteralImpl.TRUE : BooleanLiteralImpl.FALSE,
this.prefixes, this.writer);
this.writer.append("</td></tr>\n" //
+ "</tbody>\n</table>\n" //
+ "</body>\n</html>\n");
this.writer.flush();
} catch (final IOException ex) {
throw new TupleQueryResultHandlerException(ex);
}
}
@Override
public void startQueryResult(final List<String> variables)
throws TupleQueryResultHandlerException {
try {
this.variables = ImmutableList.copyOf(variables);
this.writer.append("</head>\n<body>\n" //
+ "<table class=\"sparql\">\n<thead>\n<tr>");
for (final String variable : variables) {
this.writer.append("<th>").append(variable).append("</th>");
}
this.writer.append("</tr>\n</thead>\n<tbody>\n");
} catch (final IOException ex) {
throw new TupleQueryResultHandlerException(ex);
}
}
@Override
public void handleSolution(final BindingSet bindings)
throws TupleQueryResultHandlerException {
try {
this.writer.append("<tr>");
for (final String variable : this.variables) {
this.writer.append("<td>");
RDFUtil.toHtml(bindings.getValue(variable), this.prefixes, this.writer);
this.writer.append("</td>");
}
this.writer.append("</tr>\n");
} catch (final IOException ex) {
throw new TupleQueryResultHandlerException(ex);
}
}
@Override
public void endQueryResult() throws TupleQueryResultHandlerException {
try {
this.writer.append("</tbody>\n</table>\n" //
+ "</body>\n</html>\n");
this.writer.flush();
} catch (final IOException ex) {
throw new TupleQueryResultHandlerException(ex);
}
}
}
}