From f9d50e38ff6dadc018c405892da22f368da172af Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Tue, 15 Dec 2015 15:28:44 +0100 Subject: [PATCH 1/8] Added default mimeType --- .../servlet/TriplePatternFragmentServlet.java | 13 +++++----- .../linkeddatafragments/util/MIMEParse.java | 26 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java b/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java index 7c598dd..adb25cd 100644 --- a/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java +++ b/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java @@ -27,6 +27,7 @@ import org.linkeddatafragments.datasource.tdb.JenaTDBDataSourceType; import org.linkeddatafragments.exceptions.DataSourceException; import org.linkeddatafragments.exceptions.DataSourceNotFoundException; +import org.linkeddatafragments.exceptions.NoRegisteredMimeTypesException; import org.linkeddatafragments.fragments.LinkedDataFragment; import org.linkeddatafragments.fragments.LinkedDataFragmentRequest; import org.linkeddatafragments.fragments.LinkedDataFragmentRequestBase; @@ -87,10 +88,10 @@ public void init(ServletConfig servletConfig) throws ServletException { } // register content types - mimeTypes.add(Lang.TTL.getHeaderString()); - mimeTypes.add(Lang.JSONLD.getHeaderString()); - mimeTypes.add(Lang.NTRIPLES.getHeaderString()); - mimeTypes.add(Lang.RDFXML.getHeaderString()); + MIMEParse.register(Lang.TTL.getHeaderString()); + MIMEParse.register(Lang.JSONLD.getHeaderString()); + MIMEParse.register(Lang.NTRIPLES.getHeaderString()); + MIMEParse.register(Lang.RDFXML.getHeaderString()); } catch (IOException | DataSourceException e) { throw new ServletException(e); } @@ -152,7 +153,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro output.add( fragment.getControls() ); // do conneg - String bestMatch = MIMEParse.bestMatch(mimeTypes, request.getHeader("Accept")); + String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); Lang contentType = RDFLanguages.contentTypeToLang(bestMatch); // serialize the output @@ -161,7 +162,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro response.setCharacterEncoding("utf-8"); RDFDataMgr.write(response.getOutputStream(), output, contentType); - } catch (IOException e) { + } catch (IOException | NoRegisteredMimeTypesException e) { throw new ServletException(e); } catch (DataSourceNotFoundException ex) { try { diff --git a/src/org/linkeddatafragments/util/MIMEParse.java b/src/org/linkeddatafragments/util/MIMEParse.java index d45d605..4814635 100644 --- a/src/org/linkeddatafragments/util/MIMEParse.java +++ b/src/org/linkeddatafragments/util/MIMEParse.java @@ -1,5 +1,7 @@ package org.linkeddatafragments.util; +import org.linkeddatafragments.exceptions.NoRegisteredMimeTypesException; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -24,10 +26,21 @@ * http://code.google.com/p/mimeparse/ * * Ported by Tom Zellman . + * Extended by Miel Vander Sande * */ public final class MIMEParse { + private final static List mimeTypes = new ArrayList<>(); + + /** + * Register mimeType in collection + * @param mimeType + */ + public static void register(String mimeType) { + mimeTypes.add(mimeType); + } + /** * Parse results container @@ -233,8 +246,11 @@ public static float quality(String mimeType, String ranges) * @param header * @return */ - public static String bestMatch(Collection supported, String header) + public static String bestMatch(List supported, String header) throws NoRegisteredMimeTypesException { + if (supported.isEmpty()) + throw new NoRegisteredMimeTypesException(); + List parseResults = new LinkedList(); List weightedMatches = new LinkedList(); for (String r : StringUtils.split(header, ',')) @@ -251,8 +267,12 @@ public static String bestMatch(Collection supported, String header) FitnessAndQuality lastOne = weightedMatches .get(weightedMatches.size() - 1); - return NumberUtils.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType - : ""; + return NumberUtils.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType : supported.get(0); + } + + public static String bestMatch(String header) throws NoRegisteredMimeTypesException + { + return bestMatch(mimeTypes, header); } // hidden From 19dfaf912abe3b0ed2f00a6c1f66baca68101514 Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Wed, 16 Dec 2015 10:49:44 +0100 Subject: [PATCH 2/8] Added HTML writer with Freemarker --- pom.xml | 7 ++- .../NoRegisteredMimeTypesException.java | 13 +++++ .../servlet/TriplePatternFragmentServlet.java | 35 ++++++++---- .../standalone/JettyServer.java | 13 ++++- .../linkeddatafragments/views/HtmlWriter.java | 56 +++++++++++++++++++ views/base.ftl.html | 40 +++++++++++++ views/index.ftl.html | 13 +++++ 7 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java create mode 100644 src/org/linkeddatafragments/views/HtmlWriter.java create mode 100644 views/base.ftl.html create mode 100644 views/index.ftl.html diff --git a/pom.xml b/pom.xml index bad49c4..235b14f 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ httpclient 4.3.5 - + com.google.code.gson gson 2.5 @@ -73,6 +73,11 @@ jena-tdb 1.1.2 + + org.freemarker + freemarker + 2.3.23 + src diff --git a/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java b/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java new file mode 100644 index 0000000..3d2aaee --- /dev/null +++ b/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java @@ -0,0 +1,13 @@ +package org.linkeddatafragments.exceptions; + +/** + * + * @author mielvandersande + */ +public class NoRegisteredMimeTypesException extends Exception { + + public NoRegisteredMimeTypesException() { + super("List of supported mimeTypes is empty."); + } + +} diff --git a/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java b/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java index adb25cd..8a211ba 100644 --- a/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java +++ b/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java @@ -3,6 +3,9 @@ import com.google.gson.JsonObject; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import freemarker.template.TemplateException; import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -10,6 +13,10 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map.Entry; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.servlet.RequestDispatcher; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -33,6 +40,7 @@ import org.linkeddatafragments.fragments.LinkedDataFragmentRequestBase; import org.linkeddatafragments.fragments.tpf.TriplePatternFragmentRequestImpl; import org.linkeddatafragments.util.MIMEParse; +import org.linkeddatafragments.views.HtmlWriter; /** * Servlet that responds with a Linked Data Fragment. @@ -88,6 +96,7 @@ public void init(ServletConfig servletConfig) throws ServletException { } // register content types + MIMEParse.register("text/html"); MIMEParse.register(Lang.TTL.getHeaderString()); MIMEParse.register(Lang.JSONLD.getHeaderString()); MIMEParse.register(Lang.NTRIPLES.getHeaderString()); @@ -145,24 +154,30 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro final LinkedDataFragmentRequest ldfRequest = new TriplePatternFragmentRequestImpl( request, config ); final IFragmentRequestProcessor processor = dataSource.getRequestProcessor( ldfRequest ); final LinkedDataFragment fragment = processor.createRequestedFragment(); - - final Model output = ModelFactory.createDefaultModel(); - output.setNsPrefixes(config.getPrefixes()); - output.add( fragment.getMetadata() ); - output.add( fragment.getTriples() ); - output.add( fragment.getControls() ); - + // do conneg String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); - Lang contentType = RDFLanguages.contentTypeToLang(bestMatch); // serialize the output response.setHeader("Server", "Linked Data Fragments Server"); response.setContentType(bestMatch); response.setCharacterEncoding("utf-8"); + + if (bestMatch.equals("text/html")) { + new HtmlWriter().write(response.getOutputStream(), dataSources, dataSource, fragment); + return; + } + + final Model output = ModelFactory.createDefaultModel(); + output.setNsPrefixes(config.getPrefixes()); + output.add( fragment.getMetadata() ); + output.add( fragment.getTriples() ); + output.add( fragment.getControls() ); + + Lang contentType = RDFLanguages.contentTypeToLang(bestMatch); + RDFDataMgr.write(response.getOutputStream(), output, contentType); - RDFDataMgr.write(response.getOutputStream(), output, contentType); - } catch (IOException | NoRegisteredMimeTypesException e) { + } catch (IOException | NoRegisteredMimeTypesException | TemplateException e) { throw new ServletException(e); } catch (DataSourceNotFoundException ex) { try { diff --git a/src/org/linkeddatafragments/standalone/JettyServer.java b/src/org/linkeddatafragments/standalone/JettyServer.java index 23ff9c1..3272ded 100644 --- a/src/org/linkeddatafragments/standalone/JettyServer.java +++ b/src/org/linkeddatafragments/standalone/JettyServer.java @@ -5,11 +5,11 @@ import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; - import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; - import org.linkeddatafragments.servlet.TriplePatternFragmentServlet; /** @@ -67,6 +67,15 @@ public static void main(String[] args) throws Exception { ServletHolder tpfServletHolder = new ServletHolder(new TriplePatternFragmentServlet()); tpfServletHolder.setInitParameter(TriplePatternFragmentServlet.CFGFILE, config); handler.addServletWithMapping(tpfServletHolder, "/*"); + + // TODO: create a servlet to serve assets + //String assetsPath = System.getProperty("user.dir") + "/assets"; + //ServletHolder assetsHolder = new ServletHolder(new DefaultServlet()); + //assetsHolder.setInitParameter("resourceBase", assetsPath); + //assetsHolder.setInitParameter("dirAllowed","true"); + //assetsHolder.setInitParameter("pathInfoOnly","true"); + //handler.addServletWithMapping(assetsHolder,"/assets/*"); + // start the server server.start(); diff --git a/src/org/linkeddatafragments/views/HtmlWriter.java b/src/org/linkeddatafragments/views/HtmlWriter.java new file mode 100644 index 0000000..ae4d172 --- /dev/null +++ b/src/org/linkeddatafragments/views/HtmlWriter.java @@ -0,0 +1,56 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package org.linkeddatafragments.views; + +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.LinkedDataFragment; + +/** + * + * @author mielvandersande + */ +public class HtmlWriter { + private final Configuration cfg; + + public HtmlWriter() throws IOException { + cfg = new Configuration(Configuration.VERSION_2_3_22); + cfg.setDirectoryForTemplateLoading(new File(System.getProperty("user.dir") + "/views")); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + } + + public void write(OutputStream outputStream, HashMap dataSources, IDataSource datasource, LinkedDataFragment fragment) throws IOException, TemplateException{ + /* Get the template (uses cache internally) */ + Template temp = cfg.getTemplate("index.ftl.html"); + + Map data = new HashMap(); + data.put("assetsPath", "css/"); + data.put("header", datasource.getTitle()); + data.put("datasources", dataSources); + data.put("content", ""); + + data.put("controls", fragment.getControls()); + data.put("metadata", fragment.getMetadata()); + data.put("triples", fragment.getTriples()); + + + /* Merge data-model with template */ + Writer out = new OutputStreamWriter(outputStream); + temp.process(data, out); + } +} diff --git a/views/base.ftl.html b/views/base.ftl.html new file mode 100644 index 0000000..5e5f37e --- /dev/null +++ b/views/base.ftl.html @@ -0,0 +1,40 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> + + + + + + <#attempt> + ${ title || header } + <#recover> + 'Linked Data Fragments Server' + </#attempt> + + + + + + +
+

+ <#attempt> + ${ header } + <#recover> + 'Linked Data Fragments Server' + +

+ +
+
+ ${ content } +
+ + + \ No newline at end of file diff --git a/views/index.ftl.html b/views/index.ftl.html new file mode 100644 index 0000000..0003a38 --- /dev/null +++ b/views/index.ftl.html @@ -0,0 +1,13 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#include "base.ftl.html"> +
+

Available datasets

+

Browse the following datasets as Triple Pattern Fragments:

+
+ <#list datasources?keys as datasourceName> +
${datasources[datasourceName].getTitle() }
+
${ datasources[datasourceName].getDescription() }
+ +
+

The current dataset index contains metadata about these datasets.

+
From f160c7c14e0056bab91451fdd9ba2511d17685b6 Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Wed, 16 Dec 2015 14:47:18 +0100 Subject: [PATCH 3/8] Started fragment template --- .../servlet/TriplePatternFragmentServlet.java | 6 ------ src/org/linkeddatafragments/views/HtmlWriter.java | 5 ++++- views/base.ftl.html | 10 ++-------- views/index.ftl.html | 4 +++- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java b/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java index 8a211ba..8d3237b 100644 --- a/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java +++ b/src/org/linkeddatafragments/servlet/TriplePatternFragmentServlet.java @@ -3,8 +3,6 @@ import com.google.gson.JsonObject; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.Statement; -import com.hp.hpl.jena.rdf.model.StmtIterator; import freemarker.template.TemplateException; import java.io.File; import java.io.FileReader; @@ -13,10 +11,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map.Entry; -import java.util.function.Consumer; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.servlet.RequestDispatcher; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; diff --git a/src/org/linkeddatafragments/views/HtmlWriter.java b/src/org/linkeddatafragments/views/HtmlWriter.java index ae4d172..9e854c9 100644 --- a/src/org/linkeddatafragments/views/HtmlWriter.java +++ b/src/org/linkeddatafragments/views/HtmlWriter.java @@ -15,6 +15,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.util.Date; import java.util.HashMap; import java.util.Map; import org.linkeddatafragments.datasource.IDataSource; @@ -39,10 +40,12 @@ public void write(OutputStream outputStream, HashMap dataSo Template temp = cfg.getTemplate("index.ftl.html"); Map data = new HashMap(); - data.put("assetsPath", "css/"); + data.put("assetsPath", "assets/"); data.put("header", datasource.getTitle()); data.put("datasources", dataSources); data.put("content", ""); + data.put("date", new Date()); + data.put("controls", fragment.getControls()); data.put("metadata", fragment.getMetadata()); diff --git a/views/base.ftl.html b/views/base.ftl.html index 5e5f37e..59ae42d 100644 --- a/views/base.ftl.html +++ b/views/base.ftl.html @@ -3,13 +3,7 @@ - - <#attempt> - ${ title || header } - <#recover> - 'Linked Data Fragments Server' - </#attempt> - + ${ (title || header)!"Linked Data Fragments Server" } @@ -33,7 +27,7 @@

diff --git a/views/index.ftl.html b/views/index.ftl.html index 0003a38..1cf66d3 100644 --- a/views/index.ftl.html +++ b/views/index.ftl.html @@ -6,8 +6,10 @@

Available datasets

<#list datasources?keys as datasourceName>
${datasources[datasourceName].getTitle() }
-
${ datasources[datasourceName].getDescription() }
+
${ datasources[datasourceName].getDescription()!"" }

The current dataset index contains metadata about these datasets.

+ +<#include "fragment.ftl.html"> \ No newline at end of file From b8ae8a56586567ba219a246346f102c0e5239783 Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Thu, 17 Dec 2015 11:26:26 +0100 Subject: [PATCH 4/8] Added assets to Jetty --- WebContent/WEB-INF/web.xml | 8 +++ .../servlet/LinkedDataFragmentServlet.java | 9 ++-- .../standalone/JettyServer.java | 50 +++++++++++++------ .../linkeddatafragments/views/HtmlWriter.java | 6 ++- views/base.ftl.html | 4 +- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 0f67e0e..4a3f9c1 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -6,8 +6,16 @@ BasicLdfServlet org.linkeddatafragments.servlet.LinkedDataFragmentServlet + + AssetServlet + org.linkeddatafragments.servlet.AssetServlet + BasicLdfServlet /* + + AssetServlet + /AssetServlet + diff --git a/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java b/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java index 04517ea..eaeb4ed 100644 --- a/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java +++ b/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java @@ -155,15 +155,16 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro response.setCharacterEncoding("utf-8"); if (bestMatch.equals("text/html")) { - new HtmlWriter().write(response.getOutputStream(), dataSources, dataSource, fragment); + String datasetUrl = LinkedDataFragmentRequestBase.extractDatasetURL(request, config); + new HtmlWriter().write(response.getOutputStream(), dataSources, dataSource, fragment, datasetUrl); return; } final Model output = ModelFactory.createDefaultModel(); output.setNsPrefixes(config.getPrefixes()); - output.add( fragment.getMetadata() ); - output.add( fragment.getTriples() ); - output.add( fragment.getControls() ); + output.add( fragment.getMetadata().toList() ); + output.add( fragment.getTriples().toList() ); + output.add( fragment.getControls().toList() ); Lang contentType = RDFLanguages.contentTypeToLang(bestMatch); RDFDataMgr.write(response.getOutputStream(), output, contentType); diff --git a/src/org/linkeddatafragments/standalone/JettyServer.java b/src/org/linkeddatafragments/standalone/JettyServer.java index 0fc6a71..b4987eb 100644 --- a/src/org/linkeddatafragments/standalone/JettyServer.java +++ b/src/org/linkeddatafragments/standalone/JettyServer.java @@ -5,9 +5,16 @@ import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; +import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.server.handler.ResourceHandler; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.resource.Resource; import org.linkeddatafragments.servlet.LinkedDataFragmentServlet; /** @@ -58,23 +65,38 @@ public static void main(String[] args) throws Exception { // create a new (Jetty) server, and add a servlet handler Server server = new Server(port); - ServletHandler handler = new ServletHandler(); - server.setHandler(handler); + + // The filesystem paths we will map + String pwdPath = System.getProperty("user.dir"); + String assetsPath = pwdPath + "/assets"; + + // Setup the basic application "context" for this application at "/" + // This is also known as the handler tree (in jetty speak) + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setResourceBase(pwdPath); + context.setContextPath("/"); + server.setHandler(context); + + // add a simple Servlet at "/dynamic/*" + ServletHolder holderDynamic = new ServletHolder("dynamic", LinkedDataFragmentServlet.class); + holderDynamic.setInitParameter(LinkedDataFragmentServlet.CFGFILE, config); + context.addServlet(holderDynamic, "/*"); - // add the TriplePatternFragmentsServlet to the handler - ServletHolder tpfServletHolder = new ServletHolder(new LinkedDataFragmentServlet()); - tpfServletHolder.setInitParameter(LinkedDataFragmentServlet.CFGFILE, config); - handler.addServletWithMapping(tpfServletHolder, "/*"); + // add special pathspec of "/home/" content mapped to the homePath + ServletHolder holderHome = new ServletHolder("static-home", DefaultServlet.class); + holderHome.setInitParameter("resourceBase",assetsPath); + holderHome.setInitParameter("dirAllowed","true"); + holderHome.setInitParameter("pathInfoOnly","true"); + context.addServlet(holderHome,"/assets/*"); + + // Lastly, the default servlet for root content (always needed, to satisfy servlet spec) + // It is important that this is last. + ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class); + holderPwd.setInitParameter("dirAllowed","true"); + context.addServlet(holderPwd,"/"); + - // TODO: create a servlet to serve assets - //String assetsPath = System.getProperty("user.dir") + "/assets"; - //ServletHolder assetsHolder = new ServletHolder(new DefaultServlet()); - //assetsHolder.setInitParameter("resourceBase", assetsPath); - //assetsHolder.setInitParameter("dirAllowed","true"); - //assetsHolder.setInitParameter("pathInfoOnly","true"); - //handler.addServletWithMapping(assetsHolder,"/assets/*"); - // start the server server.start(); System.out.println("Started server, listening at port " + port); diff --git a/src/org/linkeddatafragments/views/HtmlWriter.java b/src/org/linkeddatafragments/views/HtmlWriter.java index 9e854c9..d60fba7 100644 --- a/src/org/linkeddatafragments/views/HtmlWriter.java +++ b/src/org/linkeddatafragments/views/HtmlWriter.java @@ -35,7 +35,7 @@ public HtmlWriter() throws IOException { cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); } - public void write(OutputStream outputStream, HashMap dataSources, IDataSource datasource, LinkedDataFragment fragment) throws IOException, TemplateException{ + public void write(OutputStream outputStream, HashMap dataSources, IDataSource datasource, LinkedDataFragment fragment, String datasetUrl) throws IOException, TemplateException{ /* Get the template (uses cache internally) */ Template temp = cfg.getTemplate("index.ftl.html"); @@ -45,8 +45,10 @@ public void write(OutputStream outputStream, HashMap dataSo data.put("datasources", dataSources); data.put("content", ""); data.put("date", new Date()); - + + data.put("datasourceUrl", datasetUrl); + data.put("datasource", datasource); data.put("controls", fragment.getControls()); data.put("metadata", fragment.getMetadata()); data.put("triples", fragment.getTriples()); diff --git a/views/base.ftl.html b/views/base.ftl.html index 59ae42d..63c0126 100644 --- a/views/base.ftl.html +++ b/views/base.ftl.html @@ -4,7 +4,7 @@ ${ (title || header)!"Linked Data Fragments Server" } - + @@ -18,7 +18,7 @@

From a71446005860abf13c90251abbce935e2873bd2f Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Sat, 26 Dec 2015 16:24:37 +0100 Subject: [PATCH 5/8] Refactored LinkedDataFragmentWriters --- .../datasource/index/IndexDataSource.java | 6 -- .../servlet/LinkedDataFragmentServlet.java | 67 ++++++------- .../linkeddatafragments/views/HtmlWriter.java | 65 ------------- .../views/HtmlWriterImpl.java | 97 +++++++++++++++++++ .../views/LinkedDataFragmentWriter.java | 17 ++++ views/base.ftl.html | 16 ++- views/index.ftl.html | 6 +- 7 files changed, 154 insertions(+), 120 deletions(-) delete mode 100644 src/org/linkeddatafragments/views/HtmlWriter.java create mode 100644 src/org/linkeddatafragments/views/HtmlWriterImpl.java create mode 100644 src/org/linkeddatafragments/views/LinkedDataFragmentWriter.java diff --git a/src/org/linkeddatafragments/datasource/index/IndexDataSource.java b/src/org/linkeddatafragments/datasource/index/IndexDataSource.java index 2ec7a86..70ffb0f 100644 --- a/src/org/linkeddatafragments/datasource/index/IndexDataSource.java +++ b/src/org/linkeddatafragments/datasource/index/IndexDataSource.java @@ -15,12 +15,10 @@ public class IndexDataSource extends DataSource { protected final IndexRequestProcessorForTPFs requestProcessor; - private final HashMap datasources; public IndexDataSource(String baseUrl, HashMap datasources) { super("Index", "List of all datasources"); requestProcessor = new IndexRequestProcessorForTPFs( baseUrl, datasources ); - this.datasources = datasources; } @Override @@ -28,9 +26,5 @@ public IFragmentRequestProcessor getRequestProcessor() { return requestProcessor; } - - public HashMap getDatasources() { - return datasources; - } } diff --git a/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java b/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java index 2476dc9..b24d832 100644 --- a/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java +++ b/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java @@ -1,9 +1,6 @@ package org.linkeddatafragments.servlet; import com.google.gson.JsonObject; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import freemarker.template.TemplateException; import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -17,8 +14,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.jena.riot.Lang; -import org.apache.jena.riot.RDFDataMgr; -import org.apache.jena.riot.RDFLanguages; import org.linkeddatafragments.config.ConfigReader; import org.linkeddatafragments.datasource.DataSourceFactory; import org.linkeddatafragments.datasource.IDataSource; @@ -27,12 +22,12 @@ import org.linkeddatafragments.datasource.tdb.JenaTDBDataSourceType; import org.linkeddatafragments.exceptions.DataSourceException; import org.linkeddatafragments.exceptions.DataSourceNotFoundException; -import org.linkeddatafragments.exceptions.NoRegisteredMimeTypesException; import org.linkeddatafragments.fragments.FragmentRequestParserBase; import org.linkeddatafragments.fragments.LinkedDataFragment; import org.linkeddatafragments.fragments.LinkedDataFragmentRequest; import org.linkeddatafragments.util.MIMEParse; -import org.linkeddatafragments.views.HtmlWriter; +import org.linkeddatafragments.views.LinkedDataFragmentWriter; +import org.linkeddatafragments.views.LinkedDataFragmentWriterFactory; /** * Servlet that responds with a Linked Data Fragment. @@ -142,16 +137,6 @@ private IDataSource getDataSource(HttpServletRequest request) throws DataSourceN @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { - final IDataSource dataSource = getDataSource( request ); - - final LinkedDataFragmentRequest ldfRequest = - dataSource.getRequestParser() - .parseIntoFragmentRequest( request, config ); - - final LinkedDataFragment fragment = - dataSource.getRequestProcessor() - .createRequestedFragment( ldfRequest ); - // do conneg String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); @@ -160,30 +145,36 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro response.setContentType(bestMatch); response.setCharacterEncoding("utf-8"); - if (bestMatch.equals("text/html")) { - new HtmlWriter().write(response.getOutputStream(), dataSource, fragment, ldfRequest); - return; - } - - final Model output = ModelFactory.createDefaultModel(); - output.setNsPrefixes(config.getPrefixes()); - output.add( fragment.getMetadata() ); - output.add( fragment.getTriples() ); - output.add( fragment.getControls() ); + LinkedDataFragmentWriter writer = LinkedDataFragmentWriterFactory.create(config.getPrefixes(), dataSources, bestMatch); - Lang contentType = RDFLanguages.contentTypeToLang(bestMatch); - RDFDataMgr.write(response.getOutputStream(), output, contentType); - - } catch (IOException | NoRegisteredMimeTypesException | TemplateException e) { - throw new ServletException(e); - } catch (DataSourceNotFoundException ex) { try { - response.setStatus(404); - response.getOutputStream().println(ex.getMessage()); - response.getOutputStream().close(); - } catch (IOException ex1) { - throw new ServletException(ex1); + + final IDataSource dataSource = getDataSource( request ); + + final LinkedDataFragmentRequest ldfRequest = + dataSource.getRequestParser() + .parseIntoFragmentRequest( request, config ); + + final LinkedDataFragment fragment = + dataSource.getRequestProcessor() + .createRequestedFragment( ldfRequest ); + + writer.writeFragment(response.getOutputStream(), dataSource, fragment, ldfRequest); + + } catch (DataSourceNotFoundException ex) { + try { + response.setStatus(404); + writer.writeNotFound(response.getOutputStream(), request); + } catch (Exception ex1) { + throw new ServletException(ex1); + } + } catch (Exception e) { + response.setStatus(500); + writer.writeError(response.getOutputStream(), e); } + + } catch (Exception e) { + throw new ServletException(e); } } diff --git a/src/org/linkeddatafragments/views/HtmlWriter.java b/src/org/linkeddatafragments/views/HtmlWriter.java deleted file mode 100644 index f8c162a..0000000 --- a/src/org/linkeddatafragments/views/HtmlWriter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package org.linkeddatafragments.views; - -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import freemarker.template.TemplateExceptionHandler; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.ServletOutputStream; -import org.linkeddatafragments.datasource.IDataSource; -import org.linkeddatafragments.datasource.index.IndexDataSource; -import org.linkeddatafragments.fragments.LinkedDataFragment; -import org.linkeddatafragments.fragments.LinkedDataFragmentRequest; - -/** - * - * @author mielvandersande - */ -public class HtmlWriter { - private final Configuration cfg; - - public HtmlWriter() throws IOException { - cfg = new Configuration(Configuration.VERSION_2_3_22); - cfg.setDirectoryForTemplateLoading(new File(System.getProperty("user.dir") + "/views")); - cfg.setDefaultEncoding("UTF-8"); - cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - } - - public void write(OutputStream outputStream, IDataSource datasource, LinkedDataFragment fragment, LinkedDataFragmentRequest ldfRequest) throws IOException, TemplateException{ - /* Get the template (uses cache internally) */ - Template temp = cfg.getTemplate("index.ftl.html"); - - Map data = new HashMap(); - data.put("assetsPath", "assets/"); - data.put("header", datasource.getTitle()); - if (datasource instanceof IndexDataSource) - data.put("datasources", ((IndexDataSource) datasource).getDatasources()); - data.put("content", ""); - data.put("date", new Date()); - - - data.put("datasourceUrl", ldfRequest.getDatasetURL()); - data.put("datasource", datasource); - data.put("controls", fragment.getControls()); - data.put("metadata", fragment.getMetadata()); - data.put("triples", fragment.getTriples()); - - - /* Merge data-model with template */ - Writer out = new OutputStreamWriter(outputStream); - temp.process(data, out); - } -} diff --git a/src/org/linkeddatafragments/views/HtmlWriterImpl.java b/src/org/linkeddatafragments/views/HtmlWriterImpl.java new file mode 100644 index 0000000..abba13b --- /dev/null +++ b/src/org/linkeddatafragments/views/HtmlWriterImpl.java @@ -0,0 +1,97 @@ +package org.linkeddatafragments.views; + +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.index.IndexDataSource; +import org.linkeddatafragments.fragments.LinkedDataFragment; +import org.linkeddatafragments.fragments.LinkedDataFragmentRequest; +import org.linkeddatafragments.fragments.tpf.TriplePatternFragmentRequest; + +/** + * + * @author mielvandersande + */ +public class HtmlWriterImpl extends LinkedDataFragmentWriterBase implements LinkedDataFragmentWriter { + private final Configuration cfg; + + private final Template indexTemplate; + private final Template datasourceTemplate; + private final Template notfoundTemplate; + private final Template errorTemplate; + + + public HtmlWriterImpl(Map prefixes, HashMap datasources) throws IOException { + super(prefixes, datasources); + + cfg = new Configuration(Configuration.VERSION_2_3_22); + cfg.setDirectoryForTemplateLoading(new File(System.getProperty("user.dir") + "/views")); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + indexTemplate = cfg.getTemplate("index.ftl.html"); + datasourceTemplate = cfg.getTemplate("datasource.ftl.html"); + notfoundTemplate = cfg.getTemplate("notfound.ftl.html"); + errorTemplate = cfg.getTemplate("error.ftl.html"); + } + + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, LinkedDataFragment fragment, LinkedDataFragmentRequest ldfRequest) throws IOException, TemplateException{ + Map data = new HashMap(); + data.put("assetsPath", "assets/"); + data.put("header", datasource.getTitle()); + + data.put("date", new Date()); + + data.put("datasourceUrl", ldfRequest.getDatasetURL()); + data.put("datasource", datasource); + data.put("controls", fragment.getControls()); + data.put("metadata", fragment.getMetadata()); + data.put("triples", fragment.getTriples()); + data.put("datasources", getDatasources()); + + Map query = new HashMap(); + TriplePatternFragmentRequest tpfRequest = (TriplePatternFragmentRequest) ldfRequest; + query.put("subject", tpfRequest.getSubject()); + query.put("predicate", tpfRequest.getPredicate()); + query.put("object", tpfRequest.getObject()); + data.put("query", query); + + /* Get the template (uses cache internally) */ + Template temp = datasource instanceof IndexDataSource ? indexTemplate : datasourceTemplate; + + /* Merge data-model with template */ + Writer out = new OutputStreamWriter(outputStream); + temp.process(data, out); + } + + @Override + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception { + Map data = new HashMap(); + data.put("url", request.getRequestURL().toString()); + data.put("datasources", getDatasources()); + + Writer out = new OutputStreamWriter(outputStream); + notfoundTemplate.process(data, out); + } + + @Override + public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception { + Map data = new HashMap(); + data.put("error", ex); + + Writer out = new OutputStreamWriter(outputStream); + errorTemplate.process(data, out); + } +} diff --git a/src/org/linkeddatafragments/views/LinkedDataFragmentWriter.java b/src/org/linkeddatafragments/views/LinkedDataFragmentWriter.java new file mode 100644 index 0000000..33ccdc2 --- /dev/null +++ b/src/org/linkeddatafragments/views/LinkedDataFragmentWriter.java @@ -0,0 +1,17 @@ +package org.linkeddatafragments.views; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.LinkedDataFragment; +import org.linkeddatafragments.fragments.LinkedDataFragmentRequest; + +/** + * + * @author mielvandersande + */ +public interface LinkedDataFragmentWriter { + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception; + public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception; + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, LinkedDataFragment fragment, LinkedDataFragmentRequest ldfRequest) throws Exception; +} diff --git a/views/base.ftl.html b/views/base.ftl.html index 63c0126..78ef1a5 100644 --- a/views/base.ftl.html +++ b/views/base.ftl.html @@ -1,28 +1,23 @@ <#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#macro display_page> - ${ (title || header)!"Linked Data Fragments Server" } + ${ title!header!"Linked Data Fragments Server" }
-

- <#attempt> - ${ header } - <#recover> - 'Linked Data Fragments Server' - -

+

${header!"Linked Data Fragments Server"}

- ${ content } + <@contents/>

@@ -31,4 +26,5 @@

- \ No newline at end of file + + \ No newline at end of file diff --git a/views/index.ftl.html b/views/index.ftl.html index 61b481f..40027bf 100644 --- a/views/index.ftl.html +++ b/views/index.ftl.html @@ -1,5 +1,6 @@ <#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> <#include "base.ftl.html"> +<#macro contents>

Available datasets

Browse the following datasets as Triple Pattern Fragments:

@@ -14,4 +15,7 @@

Available datasets

The current dataset index contains metadata about these datasets.

-<#include "fragment.ftl.html"> \ No newline at end of file +<#include "fragment.ftl.html"> + + +<@display_page/> \ No newline at end of file From 4d4b8226d13a0fb364f6f3204d2adbe8ec448b77 Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Sat, 26 Dec 2015 16:58:56 +0100 Subject: [PATCH 6/8] Completed draft writers --- .../linkeddatafragments/assets/favicon.ico | Bin 0 -> 318 bytes src/org/linkeddatafragments/assets/logo.svg | 67 +++++ src/org/linkeddatafragments/assets/style.css | 247 ++++++++++++++++++ .../views/HtmlWriterImpl.java | 10 +- .../views/LinkedDataFragmentWriterBase.java | 27 ++ .../LinkedDataFragmentWriterFactory.java | 25 ++ .../views/RdfWriterImpl.java | 53 ++++ views/datasource.ftl.html | 7 + views/error.ftl.html | 11 + views/fragment.ftl.html | 73 ++++++ views/notfound.ftl.html | 16 ++ 11 files changed, 534 insertions(+), 2 deletions(-) create mode 100644 src/org/linkeddatafragments/assets/favicon.ico create mode 100644 src/org/linkeddatafragments/assets/logo.svg create mode 100644 src/org/linkeddatafragments/assets/style.css create mode 100644 src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java create mode 100644 src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java create mode 100644 src/org/linkeddatafragments/views/RdfWriterImpl.java create mode 100644 views/datasource.ftl.html create mode 100644 views/error.ftl.html create mode 100644 views/fragment.ftl.html create mode 100644 views/notfound.ftl.html diff --git a/src/org/linkeddatafragments/assets/favicon.ico b/src/org/linkeddatafragments/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..65418193a24cd6f59b00198636351f7270b6dd41 GIT binary patch literal 318 zcmZQzU<5(|0RbS%!l1#(z#zuJz@P!d0zj+)#2|4HXaJKC0wf0l(z3D)k^bixltlM2 z{Qv(SB1i&h3~db%3#_M#y2to@)=;tsYa9FRIEw?&DS39 literal 0 HcmV?d00001 diff --git a/src/org/linkeddatafragments/assets/logo.svg b/src/org/linkeddatafragments/assets/logo.svg new file mode 100644 index 0000000..dce588f --- /dev/null +++ b/src/org/linkeddatafragments/assets/logo.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/linkeddatafragments/assets/style.css b/src/org/linkeddatafragments/assets/style.css new file mode 100644 index 0000000..4728a61 --- /dev/null +++ b/src/org/linkeddatafragments/assets/style.css @@ -0,0 +1,247 @@ +/*! @license ©2013 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */ + +html, input, th, td { + font-family: "Open Sans", Verdana, Arial, sans-serif; + font-size: 11pt; +} + +html { + background: #f6f6f6; +} + +body { + max-width: 800px; + margin: 0 auto; + line-height: 1.3; + color: #333333; + background-color: white; + padding: 10px 40px; + box-shadow: 2px 2px 15px 0px rgba(50, 50, 50, 0.75); +} + +h1, h2, h3, legend { + margin: .4em 0 .2em; + overflow: hidden; +} +h1 { + margin-right: 180px; +} +h1 a { + color: black; +} +h2 { + color: #be1622; +} +h3 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +p { + margin: 0; +} + +a { + color: #be1622; + text-decoration: none; + border-bottom: none 1px; +} +a:hover { + color: #be1622 !important; + border-bottom-style: solid; +} + +ul { + padding: 0; + margin: 0 0 .5em 1.5em; + list-style: none; +} + +pre { + margin: 0; +} + +form { + margin: 0 0 1.5em; +} + +fieldset { + border: none; + padding: .5em 0 0 20px; +} +fieldset ul { + margin-left: 0; +} +fieldset li { + line-height: 2em; +} + +legend { + font-size: 1.17em; + font-weight: bold; + padding: 0; + margin-left: -20px; +} + +label { + width: 100px; + display: block; + float: left; + clear: both; + font-weight: bold; +} +label:after { + content: ":"; +} + +input { + outline: none; + font-size: .95em; +} +fieldset input { + width: 500px; + color: #be1622; + background-color: transparent; + border: none; + border-bottom: 1px solid #bbbbbb; + cursor: pointer; +} +input[type=submit] { + font-weight: bold; + color: #be1622; + background-color: #f6f6f6; + border-radius: 3px; + padding: 5px 8px; + border: 1px solid #999999; + cursor: pointer; +} +input[type=submit]:hover { + border-color: #666666; +} +input[type=submit]:active { + padding: 6px 7px 4px 9px; +} +.uri { + font-family: "Droid Sans Mono", monospace; +} + +header .logo { + text-align: right; +} +header .logo a { + position: absolute; + top: 20px; + margin-left: -100px; + border-bottom-width: 0px; +} +header .logo img { + width: 160px; +} + +footer { + clear: both; + margin: 1.5em 0 .5em; + font-size: small; +} +footer * { + color: gray; + margin-right: 5px; +} + +.counts { + color: gray; +} +ul.links { + margin: 0; + padding: 0; + display: inline; +} +ul.links li { + display: inline; + padding-left: 20px; + font-weight: bold; +} + +ul.triples { + margin: .3em 0 1em 20px; + font-size: .95em; + line-height: 1.5; + font-family: "Droid Sans Mono", monospace; + overflow-x: hidden; +} +ul.triples li { + text-indent: -20px; + padding-left: 20px; + max-width: 100%; + max-height: 1.5em; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +ul.triples li:hover { + max-height: 100em; + white-space: normal; + transition: max-height .5s ease-in; + transition-delay: .5s; +} +ul.triples li:not(:hover) a { + color: inherit; +} +ul.triples a:nth-child(2) { + margin: 0 1em; +} +abbr { + border: none; +} + +.index { + margin-bottom: 2em; +} +.datasets { + margin: .5em 20px; +} +dt { + font-weight: bold; + display: block; + float: left; + clear: left; +} +dd { + color: gray; + margin: .1em 0 0 12em; + font-size: .95em; +} + +#about { + margin-top: 1.5em; + font-size: .9em; +} + +@media screen and (max-width: 700px) { + html, input, th, td { + font-size: 10pt; + } + body { + padding: 15px; + } + header figure { + display: none; + } + h1, legend { + margin: 0; + } + fieldset, ul.triples { + padding: .5em 0; + margin: 0; + } + fieldset input { + width: 70%; + } + label { + width: 80px; + } + ul.triples li { + margin: 1em 0; + } +} diff --git a/src/org/linkeddatafragments/views/HtmlWriterImpl.java b/src/org/linkeddatafragments/views/HtmlWriterImpl.java index abba13b..07c2397 100644 --- a/src/org/linkeddatafragments/views/HtmlWriterImpl.java +++ b/src/org/linkeddatafragments/views/HtmlWriterImpl.java @@ -49,11 +49,13 @@ public HtmlWriterImpl(Map prefixes, HashMap @Override public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, LinkedDataFragment fragment, LinkedDataFragmentRequest ldfRequest) throws IOException, TemplateException{ Map data = new HashMap(); + + // base.ftl.html data.put("assetsPath", "assets/"); data.put("header", datasource.getTitle()); - data.put("date", new Date()); + // fragment.ftl.html data.put("datasourceUrl", ldfRequest.getDatasetURL()); data.put("datasource", datasource); data.put("controls", fragment.getControls()); @@ -79,8 +81,10 @@ public void writeFragment(ServletOutputStream outputStream, IDataSource datasour @Override public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception { Map data = new HashMap(); - data.put("url", request.getRequestURL().toString()); + data.put("assetsPath", "assets/"); data.put("datasources", getDatasources()); + data.put("date", new Date()); + data.put("url", request.getRequestURL().toString()); Writer out = new OutputStreamWriter(outputStream); notfoundTemplate.process(data, out); @@ -89,6 +93,8 @@ public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest r @Override public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception { Map data = new HashMap(); + data.put("assetsPath", "assets/"); + data.put("date", new Date()); data.put("error", ex); Writer out = new OutputStreamWriter(outputStream); diff --git a/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java new file mode 100644 index 0000000..901103b --- /dev/null +++ b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java @@ -0,0 +1,27 @@ +package org.linkeddatafragments.views; + +import java.util.HashMap; +import java.util.Map; +import org.linkeddatafragments.datasource.IDataSource; + +/** + * + * @author mielvandersande + */ +public abstract class LinkedDataFragmentWriterBase implements LinkedDataFragmentWriter { + private final Map prefixes; + private final HashMap datasources; + + public LinkedDataFragmentWriterBase(Map prefixes, HashMap datasources) { + this.prefixes = prefixes; + this.datasources = datasources; + } + + public Map getPrefixes() { + return prefixes; + } + + public HashMap getDatasources() { + return datasources; + } +} diff --git a/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java new file mode 100644 index 0000000..b4aeebc --- /dev/null +++ b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java @@ -0,0 +1,25 @@ +package org.linkeddatafragments.views; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.linkeddatafragments.datasource.IDataSource; + +/** + * + * @author mielvandersande + */ +public class LinkedDataFragmentWriterFactory { + + private final static String HTML = "text/html"; + + + public static LinkedDataFragmentWriter create(Map prefixes, HashMap datasources, String mimeType) throws IOException { + switch (mimeType) { + case HTML: + return new HtmlWriterImpl(prefixes, datasources); + default: + return new RdfWriterImpl(prefixes, datasources, mimeType); + } + } +} diff --git a/src/org/linkeddatafragments/views/RdfWriterImpl.java b/src/org/linkeddatafragments/views/RdfWriterImpl.java new file mode 100644 index 0000000..4b1a99c --- /dev/null +++ b/src/org/linkeddatafragments/views/RdfWriterImpl.java @@ -0,0 +1,53 @@ +package org.linkeddatafragments.views; + +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFDataMgr; +import org.apache.jena.riot.RDFLanguages; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.LinkedDataFragment; +import org.linkeddatafragments.fragments.LinkedDataFragmentRequest; + +/** + * + * @author mielvandersande + */ +class RdfWriterImpl extends LinkedDataFragmentWriterBase implements LinkedDataFragmentWriter { + + private final Lang contentType; + + public RdfWriterImpl(Map prefixes, HashMap datasources, String mimeType) { + super(prefixes, datasources); + this.contentType = RDFLanguages.contentTypeToLang(mimeType); + } + + @Override + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws IOException { + outputStream.println(request.getRequestURL().toString() + " not found!"); + outputStream.close(); + } + + @Override + public void writeError(ServletOutputStream outputStream, Exception ex) throws IOException { + outputStream.println(ex.getMessage()); + outputStream.close(); + } + + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, LinkedDataFragment fragment, LinkedDataFragmentRequest ldfRequest) throws Exception { + final Model output = ModelFactory.createDefaultModel(); + output.setNsPrefixes(getPrefixes()); + output.add(fragment.getMetadata()); + output.add(fragment.getTriples()); + output.add(fragment.getControls()); + + RDFDataMgr.write(outputStream, output, contentType); + } + +} diff --git a/views/datasource.ftl.html b/views/datasource.ftl.html new file mode 100644 index 0000000..97cd099 --- /dev/null +++ b/views/datasource.ftl.html @@ -0,0 +1,7 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#assign title = datasource.getTitle() + ' | ' + title!""> +<#include "base.ftl.html"> +<#macro contents> +<#include "fragment.ftl.html"> + +<@display_page/> diff --git a/views/error.ftl.html b/views/error.ftl.html new file mode 100644 index 0000000..84ce658 --- /dev/null +++ b/views/error.ftl.html @@ -0,0 +1,11 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#include "base.ftl.html"> +<#macro contents> +

Error executing your request

+

Your request could not be executed due to an internal server error.

+

Please try reloading the page or return to the index page.

+ +

Error details

+

<#if error??>${(error.getMessage())!error!""}

+ +<@display_page/> \ No newline at end of file diff --git a/views/fragment.ftl.html b/views/fragment.ftl.html new file mode 100644 index 0000000..7174554 --- /dev/null +++ b/views/fragment.ftl.html @@ -0,0 +1,73 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#setting url_escaping_charset='UTF-8'> +

+

${datasource.getTitle()?cap_first}

+ +
+
+ Query ${datasource.getTitle()} by triple pattern +
    +<#list ['subject', 'predicate', 'object'] as component> +
  • + + +
  • + +
+
+

+ +

+
+
+ +

Matches in ${datasource.getTitle()} for ${ (query.getPatternString())!"" }

+ +<#assign HYDRA = "http://www.w3.org/ns/hydra/core#"> + +
+ <#list metadata as triple> + <#if triple.getPredicate().getURI() == (HYDRA + "totalItems")> + Total number of triples: ${triple.getObject().getString()} + + +
+ + + +<#list controls as triple> + + \ No newline at end of file diff --git a/views/notfound.ftl.html b/views/notfound.ftl.html new file mode 100644 index 0000000..363b8ab --- /dev/null +++ b/views/notfound.ftl.html @@ -0,0 +1,16 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#include "base.ftl.html"> +<#macro contents> +

Resource not found

+

+ No resource with URL ${ url!"" } was found. +

+ +

Available datasets

+ + +<@display_page/> \ No newline at end of file From 1c62dcd9f30ccdcd62b9b1297da036feed534675 Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Wed, 30 Dec 2015 10:59:54 +0100 Subject: [PATCH 7/8] Added assets folder --- assets/logo.svg | 67 +++++++++++++ assets/style.css | 247 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 assets/logo.svg create mode 100644 assets/style.css diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..dce588f --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..4728a61 --- /dev/null +++ b/assets/style.css @@ -0,0 +1,247 @@ +/*! @license ©2013 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */ + +html, input, th, td { + font-family: "Open Sans", Verdana, Arial, sans-serif; + font-size: 11pt; +} + +html { + background: #f6f6f6; +} + +body { + max-width: 800px; + margin: 0 auto; + line-height: 1.3; + color: #333333; + background-color: white; + padding: 10px 40px; + box-shadow: 2px 2px 15px 0px rgba(50, 50, 50, 0.75); +} + +h1, h2, h3, legend { + margin: .4em 0 .2em; + overflow: hidden; +} +h1 { + margin-right: 180px; +} +h1 a { + color: black; +} +h2 { + color: #be1622; +} +h3 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +p { + margin: 0; +} + +a { + color: #be1622; + text-decoration: none; + border-bottom: none 1px; +} +a:hover { + color: #be1622 !important; + border-bottom-style: solid; +} + +ul { + padding: 0; + margin: 0 0 .5em 1.5em; + list-style: none; +} + +pre { + margin: 0; +} + +form { + margin: 0 0 1.5em; +} + +fieldset { + border: none; + padding: .5em 0 0 20px; +} +fieldset ul { + margin-left: 0; +} +fieldset li { + line-height: 2em; +} + +legend { + font-size: 1.17em; + font-weight: bold; + padding: 0; + margin-left: -20px; +} + +label { + width: 100px; + display: block; + float: left; + clear: both; + font-weight: bold; +} +label:after { + content: ":"; +} + +input { + outline: none; + font-size: .95em; +} +fieldset input { + width: 500px; + color: #be1622; + background-color: transparent; + border: none; + border-bottom: 1px solid #bbbbbb; + cursor: pointer; +} +input[type=submit] { + font-weight: bold; + color: #be1622; + background-color: #f6f6f6; + border-radius: 3px; + padding: 5px 8px; + border: 1px solid #999999; + cursor: pointer; +} +input[type=submit]:hover { + border-color: #666666; +} +input[type=submit]:active { + padding: 6px 7px 4px 9px; +} +.uri { + font-family: "Droid Sans Mono", monospace; +} + +header .logo { + text-align: right; +} +header .logo a { + position: absolute; + top: 20px; + margin-left: -100px; + border-bottom-width: 0px; +} +header .logo img { + width: 160px; +} + +footer { + clear: both; + margin: 1.5em 0 .5em; + font-size: small; +} +footer * { + color: gray; + margin-right: 5px; +} + +.counts { + color: gray; +} +ul.links { + margin: 0; + padding: 0; + display: inline; +} +ul.links li { + display: inline; + padding-left: 20px; + font-weight: bold; +} + +ul.triples { + margin: .3em 0 1em 20px; + font-size: .95em; + line-height: 1.5; + font-family: "Droid Sans Mono", monospace; + overflow-x: hidden; +} +ul.triples li { + text-indent: -20px; + padding-left: 20px; + max-width: 100%; + max-height: 1.5em; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +ul.triples li:hover { + max-height: 100em; + white-space: normal; + transition: max-height .5s ease-in; + transition-delay: .5s; +} +ul.triples li:not(:hover) a { + color: inherit; +} +ul.triples a:nth-child(2) { + margin: 0 1em; +} +abbr { + border: none; +} + +.index { + margin-bottom: 2em; +} +.datasets { + margin: .5em 20px; +} +dt { + font-weight: bold; + display: block; + float: left; + clear: left; +} +dd { + color: gray; + margin: .1em 0 0 12em; + font-size: .95em; +} + +#about { + margin-top: 1.5em; + font-size: .9em; +} + +@media screen and (max-width: 700px) { + html, input, th, td { + font-size: 10pt; + } + body { + padding: 15px; + } + header figure { + display: none; + } + h1, legend { + margin: 0; + } + fieldset, ul.triples { + padding: .5em 0; + margin: 0; + } + fieldset input { + width: 70%; + } + label { + width: 80px; + } + ul.triples li { + margin: 1em 0; + } +} From 2846239b71c51000086671a5e1993d9b6fad8b5c Mon Sep 17 00:00:00 2001 From: Miel Vander Sande Date: Tue, 12 Jan 2016 10:13:09 +0100 Subject: [PATCH 8/8] Added javadoc and cleaning --- .../datasource/DataSourceBase.java | 2 +- .../DataSourceCreationException.java | 2 +- .../exceptions/DataSourceException.java | 2 +- .../DataSourceNotFoundException.java | 2 +- .../NoRegisteredMimeTypesException.java | 2 +- .../UnknownDataSourceTypeException.java | 2 +- .../fragments/ILinkedDataFragment.java | 4 +- .../fragments/LinkedDataFragmentBase.java | 8 +++ .../servlet/LinkedDataFragmentServlet.java | 19 +++++-- .../util/CommonResources.java | 3 ++ ... HtmlTriplePatternFragmentWriterImpl.java} | 53 ++++++++----------- .../views/ILinkedDataFragmentWriter.java | 30 ++++++++++- .../views/LinkedDataFragmentWriterBase.java | 3 +- .../LinkedDataFragmentWriterFactory.java | 17 ++++-- .../views/RdfWriterImpl.java | 5 +- .../TriplePatternFragmentWriterBase.java | 31 +++++++++++ 16 files changed, 135 insertions(+), 50 deletions(-) rename src/org/linkeddatafragments/views/{HtmlWriterImpl.java => HtmlTriplePatternFragmentWriterImpl.java} (75%) create mode 100644 src/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java diff --git a/src/org/linkeddatafragments/datasource/DataSourceBase.java b/src/org/linkeddatafragments/datasource/DataSourceBase.java index 484cbb4..c074dcf 100644 --- a/src/org/linkeddatafragments/datasource/DataSourceBase.java +++ b/src/org/linkeddatafragments/datasource/DataSourceBase.java @@ -2,7 +2,7 @@ /** * - * @author mielvandersande + * @author Miel Vander Sande * @author Bart Hanssens */ public abstract class DataSourceBase implements IDataSource { diff --git a/src/org/linkeddatafragments/exceptions/DataSourceCreationException.java b/src/org/linkeddatafragments/exceptions/DataSourceCreationException.java index 6fd9499..0dcf13f 100644 --- a/src/org/linkeddatafragments/exceptions/DataSourceCreationException.java +++ b/src/org/linkeddatafragments/exceptions/DataSourceCreationException.java @@ -2,7 +2,7 @@ /** * - * @author mielvandersande + * @author Miel Vander Sande */ public class DataSourceCreationException extends DataSourceException { diff --git a/src/org/linkeddatafragments/exceptions/DataSourceException.java b/src/org/linkeddatafragments/exceptions/DataSourceException.java index 10fb1c0..11a8e21 100644 --- a/src/org/linkeddatafragments/exceptions/DataSourceException.java +++ b/src/org/linkeddatafragments/exceptions/DataSourceException.java @@ -4,7 +4,7 @@ /** * - * @author mielvandersande + * @author Miel Vander Sande */ abstract public class DataSourceException extends Exception { diff --git a/src/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java b/src/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java index d002aa6..5a8466d 100644 --- a/src/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java +++ b/src/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java @@ -2,7 +2,7 @@ /** * - * @author mielvandersande + * @author Miel Vander Sande */ public class DataSourceNotFoundException extends DataSourceException { diff --git a/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java b/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java index 3d2aaee..5310b3c 100644 --- a/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java +++ b/src/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java @@ -2,7 +2,7 @@ /** * - * @author mielvandersande + * @author Miel Vander Sande */ public class NoRegisteredMimeTypesException extends Exception { diff --git a/src/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java b/src/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java index 5c7b358..cc1877c 100644 --- a/src/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java +++ b/src/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java @@ -2,7 +2,7 @@ /** * - * @author mielvandersande + * @author Miel Vander Sande */ public class UnknownDataSourceTypeException extends DataSourceCreationException { diff --git a/src/org/linkeddatafragments/fragments/ILinkedDataFragment.java b/src/org/linkeddatafragments/fragments/ILinkedDataFragment.java index 59ad1ea..c999d78 100644 --- a/src/org/linkeddatafragments/fragments/ILinkedDataFragment.java +++ b/src/org/linkeddatafragments/fragments/ILinkedDataFragment.java @@ -1,5 +1,7 @@ package org.linkeddatafragments.fragments; +import java.io.Closeable; + import com.hp.hpl.jena.rdf.model.StmtIterator; /** @@ -7,7 +9,7 @@ * * @author Olaf Hartig */ -public interface ILinkedDataFragment +public interface ILinkedDataFragment extends Closeable { /** * Returns an iterator over the RDF data of this fragment (possibly only diff --git a/src/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java b/src/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java index 6dc89d8..faf1716 100644 --- a/src/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java +++ b/src/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java @@ -35,6 +35,14 @@ protected LinkedDataFragmentBase( final String fragmentURL, this.isLastPage = isLastPage; } + /** + * Does nothing. May be overridden by subclasses that hold some objects + * that need to be closed (such as iterators from the underlying data + * source). + */ + @Override + public void close() {} + @Override public boolean isPageOnly() { return true; diff --git a/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java b/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java index e330cc9..9f4af28 100644 --- a/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java +++ b/src/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java @@ -137,16 +137,18 @@ private IDataSource getDataSource(HttpServletRequest request) throws DataSourceN @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + ILinkedDataFragment fragment = null; try { // do conneg String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); - // serialize the output + // set additional response headers response.setHeader("Server", "Linked Data Fragments Server"); response.setContentType(bestMatch); response.setCharacterEncoding("utf-8"); + // create a writer depending on the best matching mimeType ILinkedDataFragmentWriter writer = LinkedDataFragmentWriterFactory.create(config.getPrefixes(), dataSources, bestMatch); try { @@ -157,8 +159,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro dataSource.getRequestParser() .parseIntoFragmentRequest( request, config ); - final ILinkedDataFragment fragment = - dataSource.getRequestProcessor() + fragment = dataSource.getRequestProcessor() .createRequestedFragment( ldfRequest ); writer.writeFragment(response.getOutputStream(), dataSource, fragment, ldfRequest); @@ -171,7 +172,6 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro throw new ServletException(ex1); } } catch (Exception e) { - e.printStackTrace(); response.setStatus(500); writer.writeError(response.getOutputStream(), e); } @@ -179,6 +179,17 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro } catch (Exception e) { throw new ServletException(e); } + finally { + // close the fragment + if ( fragment != null ) { + try { + fragment.close(); + } + catch ( Exception e ) { + // ignore + } + } + } } } diff --git a/src/org/linkeddatafragments/util/CommonResources.java b/src/org/linkeddatafragments/util/CommonResources.java index 150ca17..7c4a89e 100644 --- a/src/org/linkeddatafragments/util/CommonResources.java +++ b/src/org/linkeddatafragments/util/CommonResources.java @@ -4,6 +4,9 @@ import com.hp.hpl.jena.rdf.model.ResourceFactory; @SuppressWarnings("javadoc") +/** + * All common URIs needed for parsing and serializations + */ public class CommonResources { public final static String RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; public final static Property RDF_TYPE = createProperty(RDF + "type"); diff --git a/src/org/linkeddatafragments/views/HtmlWriterImpl.java b/src/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java similarity index 75% rename from src/org/linkeddatafragments/views/HtmlWriterImpl.java rename to src/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java index e0bcfc3..4c35f65 100644 --- a/src/org/linkeddatafragments/views/HtmlWriterImpl.java +++ b/src/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java @@ -10,7 +10,6 @@ import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; -import java.io.Writer; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -21,13 +20,17 @@ import org.linkeddatafragments.datasource.index.IndexDataSource; import org.linkeddatafragments.fragments.ILinkedDataFragment; import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment; import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; +//TODO: Refactor to a composable & flexible architecture using DataSource types, fragments types and request types + /** + * Serializes an {@link ILinkedDataFragment} to the HTML format * - * @author mielvandersande + * @author Miel Vander Sande */ -public class HtmlWriterImpl extends LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { +public class HtmlTriplePatternFragmentWriterImpl extends TriplePatternFragmentWriterBase implements ILinkedDataFragmentWriter { private final Configuration cfg; private final Template indexTemplate; @@ -39,7 +42,7 @@ public class HtmlWriterImpl extends LinkedDataFragmentWriterBase implements ILin private final String VOID = "http://rdfs.org/ns/void#"; - public HtmlWriterImpl(Map prefixes, HashMap datasources) throws IOException { + public HtmlTriplePatternFragmentWriterImpl(Map prefixes, HashMap datasources) throws IOException { super(prefixes, datasources); cfg = new Configuration(Configuration.VERSION_2_3_22); @@ -52,9 +55,9 @@ public HtmlWriterImpl(Map prefixes, HashMap notfoundTemplate = cfg.getTemplate("notfound.ftl.html"); errorTemplate = cfg.getTemplate("error.ftl.html"); } - + @Override - public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ILinkedDataFragment fragment, ILinkedDataFragmentRequest ldfRequest) throws IOException, TemplateException{ + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ITriplePatternFragment fragment, ITriplePatternFragmentRequest tpfRequest) throws IOException, TemplateException{ Map data = new HashMap(); // base.ftl.html @@ -63,9 +66,10 @@ public void writeFragment(ServletOutputStream outputStream, IDataSource datasour data.put("date", new Date()); // fragment.ftl.html - data.put("datasourceUrl", ldfRequest.getDatasetURL()); + data.put("datasourceUrl", tpfRequest.getDatasetURL()); data.put("datasource", datasource); + // Parse controls to template variables StmtIterator controls = fragment.getControls(); while (controls.hasNext()) { Statement control = controls.next(); @@ -78,41 +82,32 @@ public void writeFragment(ServletOutputStream outputStream, IDataSource datasour } } - StmtIterator metadata = fragment.getMetadata(); - while (metadata.hasNext()) { - Statement item = metadata.next(); - String predicate = item.getPredicate().getURI(); - - if (predicate.equals(HYDRA + "totalItems") || predicate.equals( VOID + "triples")) { - data.put("totalEstimate", item.getObject().asLiteral().getLong()); - break; - } - } + // Add metadata + data.put("totalEstimate", fragment.getTotalSize()); data.put("itemsPerPage", fragment.getMaxPageSize()); + // Add triples and datasources List triples = fragment.getTriples().toList(); data.put("triples", triples); data.put("datasources", getDatasources()); - - Map query = new HashMap(); - ITriplePatternFragmentRequest tpfRequest = (ITriplePatternFragmentRequest) ldfRequest; + // Calculate start and end triple number Long start = ((tpfRequest.getPageNumber() - 1) * fragment.getMaxPageSize()) + 1; data.put("start", start); data.put("end", start + (triples.size() < fragment.getMaxPageSize() ? triples.size() : fragment.getMaxPageSize())); - + // Compose query object + Map query = new HashMap(); query.put("subject", !tpfRequest.getSubject().isVariable() ? tpfRequest.getSubject().asConstantTerm() : ""); query.put("predicate", !tpfRequest.getPredicate().isVariable() ? tpfRequest.getPredicate().asConstantTerm() : ""); query.put("object", !tpfRequest.getObject().isVariable() ? tpfRequest.getObject().asConstantTerm() : ""); data.put("query", query); - /* Get the template (uses cache internally) */ + // Get the template (uses cache internally) Template temp = datasource instanceof IndexDataSource ? indexTemplate : datasourceTemplate; - /* Merge data-model with template */ - Writer out = new OutputStreamWriter(outputStream); - temp.process(data, out); + // Merge data-model with template + temp.process(data, new OutputStreamWriter(outputStream)); } @Override @@ -123,8 +118,7 @@ public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest r data.put("date", new Date()); data.put("url", request.getRequestURL().toString()); - Writer out = new OutputStreamWriter(outputStream); - notfoundTemplate.process(data, out); + notfoundTemplate.process(data, new OutputStreamWriter(outputStream)); } @Override @@ -133,8 +127,7 @@ public void writeError(ServletOutputStream outputStream, Exception ex) throws E data.put("assetsPath", "assets/"); data.put("date", new Date()); data.put("error", ex); - - Writer out = new OutputStreamWriter(outputStream); - errorTemplate.process(data, out); + + errorTemplate.process(data, new OutputStreamWriter(outputStream)); } } diff --git a/src/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java b/src/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java index 5be757c..d6b93e3 100644 --- a/src/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java +++ b/src/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java @@ -7,11 +7,37 @@ import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; /** - * - * @author mielvandersande + * Represents a possible writer to serialize an {@link ILinkedDataFragment} object + * + * @author Miel Vander Sande */ public interface ILinkedDataFragmentWriter { + /** + * Writes a 404 Not Found error + * + * @param outputStream The response stream to write to + * @param request Request that is unable to answer + * @throws Exception Error that occurs while serializing + */ public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception; + + /** + * Writes a 5XX error + * + * @param outputStream The response stream to write to + * @param ex Exception that occurred + * @throws Exception Error that occurs while serializing + */ public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception; + + /** + * Serializes and writes a {@link ILinkedDataFragment} + * + * @param outputStream The response stream to write to + * @param datasource + * @param fragment + * @param ldfRequest Parsed request for fragment + * @throws Exception Error that occurs while serializing + */ public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ILinkedDataFragment fragment, ILinkedDataFragmentRequest ldfRequest) throws Exception; } diff --git a/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java index c3449b5..27eea77 100644 --- a/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java +++ b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java @@ -5,8 +5,9 @@ import org.linkeddatafragments.datasource.IDataSource; /** + * Base class of any implementation of {@link ILinkedDataFragmentWriter}. * - * @author mielvandersande + * @author Miel Vander Sande */ public abstract class LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { private final Map prefixes; diff --git a/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java index 569653c..7619460 100644 --- a/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java +++ b/src/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java @@ -6,18 +6,27 @@ import org.linkeddatafragments.datasource.IDataSource; /** - * - * @author mielvandersande + * A factory for {@link ILinkedDataFragmentWriter}s. + * + * @author Miel Vander Sande */ public class LinkedDataFragmentWriterFactory { private final static String HTML = "text/html"; - + /** + * Creates {@link ILinkedDataFragmentWriter} for a given mimeType + * + * @param prefixes Configured prefixes to be used in serialization + * @param datasources Configured datasources + * @param mimeType mimeType to create writer for + * @return created writer + * @throws IOException + */ public static ILinkedDataFragmentWriter create(Map prefixes, HashMap datasources, String mimeType) throws IOException { switch (mimeType) { case HTML: - return new HtmlWriterImpl(prefixes, datasources); + return new HtmlTriplePatternFragmentWriterImpl(prefixes, datasources); default: return new RdfWriterImpl(prefixes, datasources, mimeType); } diff --git a/src/org/linkeddatafragments/views/RdfWriterImpl.java b/src/org/linkeddatafragments/views/RdfWriterImpl.java index eb183f5..f8ec1e4 100644 --- a/src/org/linkeddatafragments/views/RdfWriterImpl.java +++ b/src/org/linkeddatafragments/views/RdfWriterImpl.java @@ -15,8 +15,9 @@ import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; /** - * - * @author mielvandersande + * Serializes an {@link ILinkedDataFragment} to an RDF format + * + * @author Miel Vander Sande */ class RdfWriterImpl extends LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { diff --git a/src/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java b/src/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java new file mode 100644 index 0000000..97ade31 --- /dev/null +++ b/src/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java @@ -0,0 +1,31 @@ +package org.linkeddatafragments.views; + +import freemarker.template.TemplateException; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.ServletOutputStream; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; + +/** + * Base class of any implementation of {@link ITriplePatternFragmentWriter}. + * + * @author Miel Vander Sande + */ +public abstract class TriplePatternFragmentWriterBase extends LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { + + public TriplePatternFragmentWriterBase(Map prefixes, HashMap datasources) { + super(prefixes, datasources); + } + + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ILinkedDataFragment fragment, ILinkedDataFragmentRequest ldfRequest) throws Exception { + writeFragment(outputStream, datasource, (ITriplePatternFragment) fragment, (ITriplePatternFragmentRequest) ldfRequest); + } + + abstract public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ITriplePatternFragment fragment, ITriplePatternFragmentRequest tpfRequest) throws IOException, TemplateException; +}