You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by wi...@apache.org on 2013/03/12 10:10:57 UTC
[2/2] git commit: MARMOTTA-136: provided an alternative
implementation of a sparql html results writer based on freemarker
Updated Branches:
refs/heads/master 5a72f9c5b -> 4c77a2aee
MARMOTTA-136: provided an alternative implementation of a sparql html results writer based on freemarker
Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/4c77a2ae
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/4c77a2ae
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/4c77a2ae
Branch: refs/heads/master
Commit: 4c77a2aeebc4bd99b577714678000cfc47418bb6
Parents: b298d03
Author: Sergio Fernández <wi...@apache.org>
Authored: Tue Mar 12 10:10:09 2013 +0100
Committer: Sergio Fernández <wi...@apache.org>
Committed: Tue Mar 12 10:10:09 2013 +0100
----------------------------------------------------------------------
.../sparqlhtml/SPARQLResultsHTMLWriter.java | 168 +++-----
.../sparqlhtml/SPARQLResultsHTMLWriterXSL.java | 143 +++++++
.../src/main/resources/templates/rdfhtml.ftl | 328 +++++++++++++++
.../main/resources/templates/sparql_select_end.ftl | 25 ++
.../resources/templates/sparql_select_result.ftl | 26 ++
.../resources/templates/sparql_select_start.ftl | 37 ++
6 files changed, 626 insertions(+), 101 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4c77a2ae/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriter.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriter.java b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriter.java
index aead7dd..c701b24 100644
--- a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriter.java
+++ b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriter.java
@@ -17,126 +17,92 @@
*/
package org.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml;
-import org.apache.marmotta.platform.core.api.config.ConfigurationService;
-import org.apache.marmotta.platform.core.util.CDIContext;
-import org.jdom2.Document;
-import org.jdom2.output.Format;
-import org.jdom2.output.XMLOutputter;
-import org.jdom2.transform.JDOMResult;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.marmotta.platform.core.services.templating.TemplatingHelper;
import org.openrdf.query.BindingSet;
import org.openrdf.query.TupleQueryResultHandlerException;
import org.openrdf.query.resultio.TupleQueryResultFormat;
import org.openrdf.query.resultio.TupleQueryResultWriter;
-import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.xml.transform.Source;
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.stream.StreamSource;
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.Charset;
-import java.util.List;
-
/**
- * Add file description here!
- * <p/>
- * User: sschaffe
+ * SPARQL results to HTML writer usong Freemarker
+ *
+ * @author Sergio Fernández
*/
public class SPARQLResultsHTMLWriter implements TupleQueryResultWriter {
- private static final Logger log = LoggerFactory.getLogger(SPARQLResultsHTMLWriter.class);
-
- private OutputStream out;
- private ByteArrayOutputStream xmlOut;
-
- private SPARQLResultsXMLWriter xmlWriter;
+ private static final Logger log = LoggerFactory.getLogger(SPARQLResultsHTMLWriter.class);
+
+ private static final String START_TEMPLATE = "sparql_select_start.ftl";
- private Templates stylesheet;
+ private static final String RESULT_TEMPLATE = "sparql_select_result.ftl";
+ private static final String END_TEMPLATE = "sparql_select_end.ftl";
+
+ private OutputStream out;
+
+ private List<String> vars;
+
public SPARQLResultsHTMLWriter(OutputStream out) {
this.out = out;
- this.xmlOut = new ByteArrayOutputStream();
- this.xmlWriter = new SPARQLResultsXMLWriter(xmlOut);
- Source s_stylesheet = new StreamSource(SPARQLResultsHTMLWriter.class.getResourceAsStream("style.xsl"));
- try {
- stylesheet = TransformerFactory.newInstance().newTemplates(s_stylesheet);
- } catch (TransformerConfigurationException e) {
- log.error("could not compile stylesheet for rendering SPARQL results; result display not available!");
- }
}
- /**
- * Gets the query result format that this writer uses.
- */
- @Override
- public TupleQueryResultFormat getTupleQueryResultFormat() {
- return new TupleQueryResultFormat("SPARQL/HTML","text/html", Charset.forName("UTF-8"), "html");
- }
+ @Override
+ public TupleQueryResultFormat getTupleQueryResultFormat() {
+ return new TupleQueryResultFormat("SPARQL/HTML", "text/html", Charset.forName("UTF-8"), "html");
+ }
- /**
- * Indicates the start of a sequence of Solutions. The supplied bindingNames
- * are an indication of the values that are in the Solutions. For example, a
- * SeRQL query like <tt>select X, Y from {X} P {Y} </tt> will have binding
- * names <tt>X</tt> and <tt>Y</tt>.
- *
- * @param bindingNames An ordered set of binding names.
- */
- @Override
- public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
- xmlWriter.startQueryResult(bindingNames);
- }
-
- /**
- * Indicates the end of a sequence of solutions.
- */
- @Override
- public void endQueryResult() throws TupleQueryResultHandlerException {
- xmlWriter.endQueryResult();
-
- // get server uri
- String server_uri = CDIContext.getInstance(ConfigurationService.class).getServerUri();
-
- byte[] queryResult = xmlOut.toByteArray();
-
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
+ @Override
+ public void startQueryResult(List<String> vars) throws TupleQueryResultHandlerException {
+ Map<String, Object> data = new HashMap<String, Object>();
+ data.put("vars", vars);
+ this.vars = vars;
try {
- Source input = new StreamSource(new ByteArrayInputStream(queryResult));
-
- Transformer transformer = stylesheet.newTransformer();
- transformer.setParameter("serverurl", server_uri);
-
- JDOMResult result = new JDOMResult();
- transformer.transform(input, result);
- Document output = result.getDocument();
-
- XMLOutputter printer = new XMLOutputter(Format.getPrettyFormat());
- printer.output(output, writer);
- writer.flush();
-
- } catch (Exception ex) {
- throw new TupleQueryResultHandlerException("error while transforming XML results to HTML", ex);
- } finally {
- try {
- writer.close();
- } catch (IOException e) {}
+ TemplatingHelper.processTemplate(SPARQLResultsHTMLWriter.class, START_TEMPLATE, data, new OutputStreamWriter(out));
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ throw new TupleQueryResultHandlerException(e);
}
+ }
+
+ @Override
+ public void handleSolution(BindingSet binding) throws TupleQueryResultHandlerException {
+ Map<String, Object> data = new HashMap<String, Object>();
+ data.put("vars", vars);
+ Map<String, String> result = new HashMap<String, String>();
+ for (String var: vars) {
+ if (binding.hasBinding(var)) {
+ result.put(var, binding.getBinding(var).getValue().stringValue());
+ } else {
+ result.put(var, "");
+ }
+ }
+ data.put("result", result);
+ try {
+ TemplatingHelper.processTemplate(SPARQLResultsHTMLWriter.class, RESULT_TEMPLATE, data, new OutputStreamWriter(out));
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ throw new TupleQueryResultHandlerException(e);
+ }
+ }
+
+ @Override
+ public void endQueryResult() throws TupleQueryResultHandlerException {
+ Map<String, Object> data = new HashMap<String, Object>();
+ try {
+ TemplatingHelper.processTemplate(SPARQLResultsHTMLWriter.class, END_TEMPLATE, data, new OutputStreamWriter(out));
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ throw new TupleQueryResultHandlerException(e);
+ }
+ }
- }
-
- /**
- * Handles a solution.
- */
- @Override
- public void handleSolution(BindingSet bindingSet) throws TupleQueryResultHandlerException {
- xmlWriter.handleSolution(bindingSet);
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4c77a2ae/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriterXSL.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriterXSL.java b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriterXSL.java
new file mode 100644
index 0000000..56fbe11
--- /dev/null
+++ b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparqlio/sparqlhtml/SPARQLResultsHTMLWriterXSL.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml;
+
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.util.CDIContext;
+import org.jdom2.Document;
+import org.jdom2.output.Format;
+import org.jdom2.output.XMLOutputter;
+import org.jdom2.transform.JDOMResult;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.TupleQueryResultHandlerException;
+import org.openrdf.query.resultio.TupleQueryResultFormat;
+import org.openrdf.query.resultio.TupleQueryResultWriter;
+import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * ASPARQL Results to HTMl writer using XSL
+ *
+ * @author sschaffe
+ */
+@Deprecated
+public class SPARQLResultsHTMLWriterXSL implements TupleQueryResultWriter {
+
+ private static final Logger log = LoggerFactory.getLogger(SPARQLResultsHTMLWriterXSL.class);
+
+ private OutputStream out;
+ private ByteArrayOutputStream xmlOut;
+
+ private SPARQLResultsXMLWriter xmlWriter;
+
+ private Templates stylesheet;
+
+ public SPARQLResultsHTMLWriterXSL(OutputStream out) {
+ this.out = out;
+ this.xmlOut = new ByteArrayOutputStream();
+ this.xmlWriter = new SPARQLResultsXMLWriter(xmlOut);
+ Source s_stylesheet = new StreamSource(SPARQLResultsHTMLWriterXSL.class.getResourceAsStream("style.xsl"));
+ try {
+ stylesheet = TransformerFactory.newInstance().newTemplates(s_stylesheet);
+ } catch (TransformerConfigurationException e) {
+ log.error("could not compile stylesheet for rendering SPARQL results; result display not available!");
+ }
+ }
+
+ /**
+ * Gets the query result format that this writer uses.
+ */
+ @Override
+ public TupleQueryResultFormat getTupleQueryResultFormat() {
+ return new TupleQueryResultFormat("SPARQL/HTML","text/html", Charset.forName("UTF-8"), "html");
+ }
+
+ /**
+ * Indicates the start of a sequence of Solutions. The supplied bindingNames
+ * are an indication of the values that are in the Solutions. For example, a
+ * SeRQL query like <tt>select X, Y from {X} P {Y} </tt> will have binding
+ * names <tt>X</tt> and <tt>Y</tt>.
+ *
+ * @param bindingNames An ordered set of binding names.
+ */
+ @Override
+ public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
+ xmlWriter.startQueryResult(bindingNames);
+ }
+
+ /**
+ * Indicates the end of a sequence of solutions.
+ */
+ @Override
+ public void endQueryResult() throws TupleQueryResultHandlerException {
+ xmlWriter.endQueryResult();
+
+ // get server uri
+ String server_uri = CDIContext.getInstance(ConfigurationService.class).getServerUri();
+
+ byte[] queryResult = xmlOut.toByteArray();
+
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
+ try {
+ Source input = new StreamSource(new ByteArrayInputStream(queryResult));
+
+ Transformer transformer = stylesheet.newTransformer();
+ transformer.setParameter("serverurl", server_uri);
+
+ JDOMResult result = new JDOMResult();
+ transformer.transform(input, result);
+ Document output = result.getDocument();
+
+ XMLOutputter printer = new XMLOutputter(Format.getPrettyFormat());
+ printer.output(output, writer);
+ writer.flush();
+
+ } catch (Exception ex) {
+ throw new TupleQueryResultHandlerException("error while transforming XML results to HTML", ex);
+ } finally {
+ try {
+ writer.close();
+ } catch (IOException e) {}
+ }
+
+ }
+
+ /**
+ * Handles a solution.
+ */
+ @Override
+ public void handleSolution(BindingSet bindingSet) throws TupleQueryResultHandlerException {
+ xmlWriter.handleSolution(bindingSet);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4c77a2ae/platform/marmotta-sparql/src/main/resources/templates/rdfhtml.ftl
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/src/main/resources/templates/rdfhtml.ftl b/platform/marmotta-sparql/src/main/resources/templates/rdfhtml.ftl
new file mode 100644
index 0000000..782d724
--- /dev/null
+++ b/platform/marmotta-sparql/src/main/resources/templates/rdfhtml.ftl
@@ -0,0 +1,328 @@
+<#--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<!DOCTYPE html>
+<html lang="en" prefix="${prefixMappings}" xmlns="http://www.w3.org/1999/html">
+
+<head>
+ <title>Resource/s in HTML</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <script type="text/javascript" src="${baseUri}core/public/js/lib/jquery-1.7.2.js"></script>
+ <link href="${baseUri}core/public/style/style.css" rel="stylesheet" type="text/css" />
+ <link href="${baseUri}core/public/style/scheme/blue.css" title="blue" rel="stylesheet" type="text/css" />
+ <link href="${baseUri}core/public/style/scheme/dark.css" title="dark" rel="alternate stylesheet" type="text/css" />
+ <link href="${baseUri}core/public/style/rdfhtml.css" rel="stylesheet" type="text/css" />
+
+ <script>
+ $(document).ready(function(){
+ $(".submenu li").click(function(event){
+ event.preventDefault();
+ if(!$(this).hasClass("active")) {
+ $(".submenu").children().removeClass("active");
+ $(this).addClass("active");
+ var tabid = $(this).children(":first").attr("href").substring(1);
+ $("#content").children().hide();
+ $("#"+tabid).show();
+ }
+ })
+
+ $("a.ldcache").each(function(index) {
+ $(this).click(function() {
+ window.location.href = "${baseUri}resource?uri=" + encodeURIComponent($(this).attr("href"));
+ return false;
+ });
+ });
+
+ function loader(uri, type, target) {
+
+ var table = $("#"+target);
+
+ function linkify(text) {
+ var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
+ return text.replace(exp,"<a href='$1' class='ldcache'>$1</a>");
+ }
+ function zebra(index) {
+ return ( index % 2 ? "even": "odd" );
+ }
+ function createRow(data, cssClass) {
+ return $("<tr>", {})
+ .append($("<td>", {html: linkify(data.s)}))
+ .append($("<td>", {html: linkify(data.p)}))
+ .append($("<td>", {html: linkify(data.o)}))
+ .append($("<td>", {html: linkify(data.c)}))
+ .addClass(cssClass);
+ }
+ return {
+ resource: uri,
+ target: table,
+ offset: 0,
+ limit: 10,
+ fetch: function() {
+ var self = this;
+ $.getJSON("${baseUri}inspect/" + type, {uri: self.resource, start: self.offset, limit: self.limit}, function(data) {
+ if(data.length == 0) {
+ console.log(table);
+ table.replaceWith("<p class='no_triples'>No triples to display</p>");
+ }
+ for( var i in data) {
+ var t = data[i];
+ table.append(createRow(t, zebra(i)));
+ }
+ });
+ },
+ next: function(step) {
+ step = step || this.limit;
+ this.offset += step;
+ this.fetch();
+ },
+ prev: function(step) {
+ step = step || this.limit
+ this.offset = Math.max(this.offset - step, 0);
+ this.fetch();
+ },
+ more: function() {
+ this.limit += 5;
+ this.fetch();
+ },
+ less: function() {
+ this.limit = Math.max(this.limit - 5, 5);
+ this.fetch();
+ },
+ first: function() {
+ this.offset = 0;
+ this.fetch();
+ }
+ };
+ }
+
+ <#if resources?size = 1>
+ var subjLoader = new loader("${resources[0].uri}", "subject", "inspect_subject");
+ subjLoader.fetch();
+ $("#s0").click(function() {subjLoader.first();});
+ $("#s1").click(function() {subjLoader.prev();});
+ $("#s2").click(function() {subjLoader.next();});
+ $("#s3").click(function() {subjLoader.more();});
+ $("#s4").click(function() {subjLoader.less();});
+
+ var propLoader = new loader("${resources[0].uri}", "predicate", "inspect_property");
+ propLoader.fetch();
+
+ var objLoader = new loader("${resources[0].uri}", "object", "inspect_object");
+ objLoader.fetch();
+ </#if>
+
+ })
+ </script>
+</head>
+
+<body>
+<#function zebra index>
+ <#if (index % 2) == 0>
+ <#return "odd" />
+ <#else>
+ <#return "even" />
+ </#if>
+</#function>
+
+<#function cacheClass object>
+ <#if object.cache?has_content>
+ <#return "ldcache" />
+ <#else>
+ <#return "" />
+ </#if>
+</#function>
+
+<#function rdfaAttributes object>
+ <#return "${rdfaDatatype(object)} ${rdfaLanguage(object)}" />
+</#function>
+
+<#function rdfaDatatype object>
+ <#if object.datatype?has_content>
+ <#return "datatype=\"${object.datatype}\"" />
+ <#else>
+ <#return "" />
+ </#if>
+</#function>
+
+<#function rdfaLanguage object>
+ <#if object.lang?has_content>
+ <#return "lang=\"${object.lang}\"" />
+ <#else>
+ <#return "" />
+ </#if>
+</#function>
+
+<div id="wrapper">
+ <div id="header">
+ <a id="logo" href="${SERVER_URL}">
+ <img src="${SERVER_URL}${LOGO}">
+ </a>
+ <h1>RDF/HTML</h1>
+ <#if resources?size = 1>
+ <div id="top_serialisation_links">
+ <a href="${baseUri}resource?uri=${resources[0].encoded_uri}&format=application/rdf%2Bxml">RDF/XML</a> |
+ <a href="${baseUri}resource?uri=${resources[0].encoded_uri}&format=text/rdf%2Bn3">N3</a> |
+ <a href="${baseUri}resource?uri=${resources[0].encoded_uri}&format=text/turtle">Turtle</a> |
+ <a href="${baseUri}resource?uri=${resources[0].encoded_uri}&format=application/rdf%2Bjson">RDF/JSON</a> |
+ <a href="${baseUri}resource?uri=${resources[0].encoded_uri}&format=application/ld%2Bjson">JSON-LD</a>
+ </div>
+ <div class="clean"></div>
+ </#if>
+ </div>
+ <div class="clear"></div>
+ <div id="left">
+ <ul id="menu">
+ <li class="menu_item">
+ <div class="menu_heading">Views</div>
+ <ul class="submenu">
+ <li class="active"><a href="#tab-raw-triples">Triples</a></li>
+ <#if resources?size = 1>
+ <li><a href="#tab-inspection">Inspector</a></li>
+ </#if>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <div id="center">
+ <div id="content">
+ <div id="tab-raw-triples">
+
+ <h1>Triples</h1>
+ <#if resources?has_content>
+ <#list resources as resource>
+ <h2><a href="${resource.uri}" class="ldcache">${resource.uri}</a>
+ <#if timemaplink??>
+ <a style="float:right" id="timemap_link" href="${baseUri}${timemaplink}${resource.uri}">
+ <img style="width: 24px" title="browser versions" alt="memento" src="${baseUri}core/public/img/icon/memento_logo_128.png">
+ </a>
+ </#if>
+ </h2>
+ <table class="simple_table">
+ <tr class="trClassHeader">
+ <th>property</th>
+ <th>has value</th>
+ <th>context</th>
+ <th id="info">info</th>
+ </tr>
+ <#list resource.triples as triple>
+ <tr class="${zebra(triple_index)}">
+ <td><a href="${triple.predicate.uri}" class="ldcache">${triple.predicate.curie}</a></td>
+ <td about="${resource.uri}">
+ <#if triple.object.uri?has_content>
+ <a rel="${triple.predicate.curie}" href="${triple.object.uri}" class="${cacheClass(triple.object)}">${triple.object.curie}</a>
+ <#else>
+ <span property="${triple.predicate.curie}" ${rdfaAttributes(triple.object)}>${triple.object.value}</span>
+ </#if>
+ </td>
+ <td><a href="${triple.context.uri}">${triple.context.curie}</a></td>
+ <td>${triple.info}</td>
+ </tr>
+ </#list>
+ </table>
+ <#if resources?size != 1>
+ <p id="rawrdf">
+ Get this resource in raw RDF:
+ <a href="${baseUri}resource?uri=${resource.encoded_uri}&format=application/rdf%2Bxml">RDF/XML</a>,
+ <a href="${baseUri}resource?uri=${resource.encoded_uri}&format=text/rdf%2Bn3">N3</a>,
+ <a href="${baseUri}resource?uri=${resource.encoded_uri}&format=text/turtle">Turtle</a>,
+ <a href="${baseUri}resource?uri=${resource.encoded_uri}&format=application/rdf%2Bjson">RDF/JSON</a>,
+ <a href="${baseUri}resource?uri=${resource.encoded_uri}&format=application/ld%2Bjson">JSON-LD</a>
+ </p>
+ </#if>
+ </#list>
+ <#else>
+ <p>
+ No local triples to display!
+ </p>
+ </#if>
+
+ </div>
+
+ <#if resources?size = 1>
+ <div id="tab-inspection" style="display: none">
+ <h1>Inspection of <a href="${resources[0].uri}" class="ldcache">${resources[0].uri}</a></h1>
+ <div class="introspectionDetails">
+ <h2>Resource as Subject</h2>
+ <div id="table_buttons">
+ <button id="s0">|<</button>
+ <button id="s1"><</button>
+ <button id="s2">></button>
+ <button id="s3">+</button>
+ <button id="s4">-</button>
+ </div>
+ <table id="inspect_subject" class="simple_table">
+ <tr class="trClassHeader">
+ <th>Subject</th>
+ <th>Property</th>
+ <th>Object</th>
+ <th>Context</th>
+ </tr>
+ </table>
+ </div>
+ <div class="introspectionDetails">
+ <h2>Resource as Property</h2>
+ <table id="inspect_property" class="simple_table">
+ <tr class="trClassHeader">
+ <th>Subject</th>
+ <th>Property</th>
+ <th>Object</th>
+ <th>Context</th>
+ </tr>
+ </table>
+ </div>
+ <div class="introspectionDetails">
+ <h2>Resource as Object</h2>
+ <table id="inspect_object" class="simple_table">
+ <tr class="trClassHeader">
+ <th>Subject</th>
+ <th>Property</th>
+ <th>Object</th>
+ <th>Context</th>
+ </tr>
+ </table>
+ </div>
+ <!--
+ <div class="introspectionDetails">
+ <h4><a href="${resources[0].uri}" class="ldcache">${resources[0].uri}</a> as Context</h4>
+ <table id="inspect_context">
+ <tr class="trClassHeader">
+ <th>Subject</th>
+ <th>Property</th>
+ <th>Object</th>
+ <th>Context<th>
+ </tr>
+ </table>
+ </div>
+ -->
+ </div>
+ </#if>
+ </div>
+ </div>
+ <div class="clear"></div>
+ <div id="footer">
+ <div id="footer_line">
+ <span>
+ ${FOOTER}
+ </span>
+ </div>
+ </div>
+</div>
+</body>
+
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4c77a2ae/platform/marmotta-sparql/src/main/resources/templates/sparql_select_end.ftl
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/src/main/resources/templates/sparql_select_end.ftl b/platform/marmotta-sparql/src/main/resources/templates/sparql_select_end.ftl
new file mode 100644
index 0000000..bf00846
--- /dev/null
+++ b/platform/marmotta-sparql/src/main/resources/templates/sparql_select_end.ftl
@@ -0,0 +1,25 @@
+<#--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+
+ </tbody>
+ </table>
+ </body>
+
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4c77a2ae/platform/marmotta-sparql/src/main/resources/templates/sparql_select_result.ftl
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/src/main/resources/templates/sparql_select_result.ftl b/platform/marmotta-sparql/src/main/resources/templates/sparql_select_result.ftl
new file mode 100644
index 0000000..61af0a0
--- /dev/null
+++ b/platform/marmotta-sparql/src/main/resources/templates/sparql_select_result.ftl
@@ -0,0 +1,26 @@
+<#--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+
+ <tr>
+ <#list vars as var>
+ <td headers="${var}">${result[var]}</td>
+ </#list>
+ </tr>
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4c77a2ae/platform/marmotta-sparql/src/main/resources/templates/sparql_select_start.ftl
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/src/main/resources/templates/sparql_select_start.ftl b/platform/marmotta-sparql/src/main/resources/templates/sparql_select_start.ftl
new file mode 100644
index 0000000..8fff3c0
--- /dev/null
+++ b/platform/marmotta-sparql/src/main/resources/templates/sparql_select_start.ftl
@@ -0,0 +1,37 @@
+<#--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<!DOCTYPE html>
+<html lang="en" xmlns="http://www.w3.org/1999/html">
+
+ <head>
+ <title>SPARQL Results as HTML</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ </head>
+
+ <body>
+ <table border="1">
+ <thead>
+ <tr>
+ <#list vars as var>
+ <th scope="col" id="${var}">?${var}</th>
+ </#list>
+ </tr>
+ </thead>
+ <tbody>