diff --git a/README.md b/README.md index 5568b81..02d4cb7 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Create an `config.json` configuration file with the data sources (analogous to t If no parameter is set, it looks for a default `config-example.json` in the folder of the deployed WAR file. ## Status -This is software is still under development. It currently supports: +This software is still under development. It currently supports: - HDT & Jena TDB data sources - HTML, Turtle, NTriples, JsonLD, RDF/XML output diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 82d1488..df505e0 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -6,16 +6,8 @@ TpfServlet org.linkeddatafragments.servlet.LinkedDataFragmentServlet - - AssetServlet - org.linkeddatafragments.servlet.AssetServlet - TpfServlet /* - - AssetServlet - /AssetServlet - diff --git a/pom.xml b/pom.xml index 674dc4c..3cb06a7 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.linkeddatafragments ldfserver - 0.2.0 + 0.2.6-wmf-SNAPSHOT war Linked Data Fragments Server http://linkeddatafragments.org @@ -20,7 +20,7 @@ https://github.com/LinkedDataFragments/Server.Java.git https://github.com/LinkedDataFragments/Server.Java.git - v0.1.0 + v0.2.2 https://github.com/LinkedDataFragments/Server.Java @@ -29,8 +29,8 @@ Ruben Verborgh ruben.verborgh@ugent.be http://ruben.verborgh.org - iMinds - http://iminds.be + imec + http://imec.be Europe/Brussels @@ -38,8 +38,8 @@ Miel Vander Sande miel.vandersande@ugent.be http://semweb.mmlab.be - iMinds - http://iminds.be + imec + http://imec.be Europe/Brussels @@ -54,28 +54,29 @@ - 9.3.6.v20151106 + 9.4.12.v20180830 + 3.10.0 org.apache.jena jena-core - 3.0.0 + ${jenaVersion} org.apache.jena jena-arq - 3.0.0 + ${jenaVersion} org.apache.httpcomponents httpclient - 4.3.5 + 4.4 com.google.code.gson gson - 2.5 + 2.7 javax.servlet @@ -101,7 +102,7 @@ org.apache.commons commons-lang3 - 3.3.2 + 3.4 jar @@ -113,20 +114,64 @@ org.apache.jena jena-tdb - 3.0.0 - - - org.rdfhdt - hdt-jena - 2.0 + ${jenaVersion} org.freemarker freemarker - 2.3.23 + 2.3.25-incubating + + + org.slf4j + slf4j-api + 1.7.21 + + + org.slf4j + slf4j-simple + 1.7.10 + + + junit + junit + 4.11 + test + + + junit + junit + 4.12 + test + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.3 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-release-plugin + 2.5 + + false + true + false + release + deploy + + + + maven-compiler-plugin @@ -211,28 +256,17 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 1.6 sign-artifacts - verify + deploy sign - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 - true - - ossrh - https://oss.sonatype.org/ - true - - @@ -241,4 +275,46 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2 + + + + deploy-archiva + + + wikimedia.releases + Wikimedia Release Repository + https://archiva.wikimedia.org/repository/releases/ + + + wikimedia.snapshots + Wikimedia Snapshot Repository + https://archiva.wikimedia.org/repository/snapshots/ + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + true + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + none + + + + + + + + diff --git a/src/main/java/org/linkeddatafragments/datasource/hdt/HdtBasedRequestProcessorForTPFs.java b/src/main/java/org/linkeddatafragments/datasource/hdt/HdtBasedRequestProcessorForTPFs.java deleted file mode 100644 index a011631..0000000 --- a/src/main/java/org/linkeddatafragments/datasource/hdt/HdtBasedRequestProcessorForTPFs.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.linkeddatafragments.datasource.hdt; - -import java.io.IOException; -import org.apache.jena.graph.Triple; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.rdf.model.RDFNode; - -import org.linkeddatafragments.datasource.AbstractRequestProcessorForTriplePatterns; -import org.linkeddatafragments.datasource.IFragmentRequestProcessor; -import org.linkeddatafragments.fragments.ILinkedDataFragment; -import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; -import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; -import org.rdfhdt.hdt.enums.TripleComponentRole; -import org.rdfhdt.hdt.hdt.HDT; -import org.rdfhdt.hdt.hdt.HDTManager; -import org.rdfhdt.hdt.triples.IteratorTripleID; -import org.rdfhdt.hdt.triples.TripleID; -import org.rdfhdt.hdtjena.NodeDictionary; - - - -/** - * Implementation of {@link IFragmentRequestProcessor} that processes - * {@link ITriplePatternFragmentRequest}s over data stored in HDT. - * - * @author Ruben Verborgh - * @author Olaf Hartig - */ -public class HdtBasedRequestProcessorForTPFs - extends AbstractRequestProcessorForTriplePatterns -{ - - /** - * HDT Datasource - */ - protected final HDT datasource; - - /** - * The dictionary - */ - protected final NodeDictionary dictionary; - - /** - * Creates the request processor. - * - * @param hdtFile the HDT datafile - * @throws IOException if the file cannot be loaded - */ - public HdtBasedRequestProcessorForTPFs( String hdtFile ) throws IOException - { - datasource = HDTManager.mapIndexedHDT( hdtFile, null ); // listener=null - dictionary = new NodeDictionary( datasource.getDictionary() ); - } - - /** - * - * @param request - * @return - * @throws IllegalArgumentException - */ - @Override - protected Worker getTPFSpecificWorker( - final ITriplePatternFragmentRequest request ) - throws IllegalArgumentException - { - return new Worker( request ); - } - - /** - * Worker class for HDT - */ - protected class Worker - extends AbstractRequestProcessorForTriplePatterns.Worker - { - - /** - * Create HDT Worker - * - * @param req - */ - public Worker( - final ITriplePatternFragmentRequest req ) - { - super( req ); - } - - /** - * Creates an {@link ILinkedDataFragment} from the HDT - * - * @param subject - * @param predicate - * @param object - * @param offset - * @param limit - * @return - */ - @Override - protected ILinkedDataFragment createFragment( - final ITriplePatternElement subject, - final ITriplePatternElement predicate, - final ITriplePatternElement object, - final long offset, - final long limit ) - { - // FIXME: The following algorithm is incorrect for cases in which - // the requested triple pattern contains a specific variable - // multiple times; - // e.g., (?x foaf:knows ?x ) or (_:bn foaf:knows _:bn) - // see https://github.com/LinkedDataFragments/Server.Java/issues/23 - - // look up the result from the HDT datasource) - int subjectId = subject.isVariable() ? 0 : dictionary.getIntID(subject.asConstantTerm().asNode(), TripleComponentRole.SUBJECT); - int predicateId = predicate.isVariable() ? 0 : dictionary.getIntID(predicate.asConstantTerm().asNode(), TripleComponentRole.PREDICATE); - int objectId = object.isVariable() ? 0 : dictionary.getIntID(object.asConstantTerm().asNode(), TripleComponentRole.OBJECT); - - if (subjectId < 0 || predicateId < 0 || objectId < 0) { - return createEmptyTriplePatternFragment(); - } - - final Model triples = ModelFactory.createDefaultModel(); - IteratorTripleID matches = datasource.getTriples().search(new TripleID(subjectId, predicateId, objectId)); - boolean hasMatches = matches.hasNext(); - - if (hasMatches) { - // try to jump directly to the offset - boolean atOffset; - if (matches.canGoTo()) { - try { - matches.goTo(offset); - atOffset = true; - } // if the offset is outside the bounds, this page has no matches - catch (IndexOutOfBoundsException exception) { - atOffset = false; - } - } // if not possible, advance to the offset iteratively - else { - matches.goToStart(); - for (int i = 0; !(atOffset = i == offset) && matches.hasNext(); i++) { - matches.next(); - } - } - // try to add `limit` triples to the result model - if (atOffset) { - for (int i = 0; i < limit && matches.hasNext(); i++) { - triples.add(triples.asStatement(toTriple(matches.next()))); - } - } - } - - // estimates can be wrong; ensure 0 is returned if there are no results, - // and always more than actual results - final long estimatedTotal = triples.size() > 0 ? - Math.max(offset + triples.size() + 1, matches.estimatedNumResults()) - : hasMatches ? - Math.max(matches.estimatedNumResults(), 1) - : 0; - - // create the fragment - final boolean isLastPage = ( estimatedTotal < offset + limit ); - return createTriplePatternFragment( triples, estimatedTotal, isLastPage ); - } - - } // end of Worker - - /** - * Converts the HDT triple to a Jena Triple. - * - * @param tripleId the HDT triple - * @return the Jena triple - */ - private Triple toTriple(TripleID tripleId) { - return new Triple( - dictionary.getNode(tripleId.getSubject(), TripleComponentRole.SUBJECT), - dictionary.getNode(tripleId.getPredicate(), TripleComponentRole.PREDICATE), - dictionary.getNode(tripleId.getObject(), TripleComponentRole.OBJECT) - ); - } - -} diff --git a/src/main/java/org/linkeddatafragments/datasource/hdt/HdtDataSource.java b/src/main/java/org/linkeddatafragments/datasource/hdt/HdtDataSource.java deleted file mode 100644 index 12753ea..0000000 --- a/src/main/java/org/linkeddatafragments/datasource/hdt/HdtDataSource.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.linkeddatafragments.datasource.hdt; - -import java.io.IOException; - -import org.linkeddatafragments.datasource.DataSourceBase; -import org.linkeddatafragments.datasource.IFragmentRequestProcessor; -import org.linkeddatafragments.fragments.IFragmentRequestParser; -import org.linkeddatafragments.fragments.tpf.TPFRequestParserForJenaBackends; - -/** - * An HDT data source of Basic Linked Data Fragments. - * - * @author Ruben Verborgh - * @author Olaf Hartig - */ -public class HdtDataSource extends DataSourceBase { - - /** - * The request processor - * - */ - protected final HdtBasedRequestProcessorForTPFs requestProcessor; - - /** - * Creates a new HdtDataSource. - * - * @param title title of the datasource - * @param description datasource description - * @param hdtFile the HDT datafile - * @throws IOException if the file cannot be loaded - */ - public HdtDataSource(String title, String description, String hdtFile) throws IOException { - super(title, description); - requestProcessor = new HdtBasedRequestProcessorForTPFs( hdtFile ); - } - - @Override - public IFragmentRequestParser getRequestParser() - { - return TPFRequestParserForJenaBackends.getInstance(); - } - - @Override - public IFragmentRequestProcessor getRequestProcessor() - { - return requestProcessor; - } - -} diff --git a/src/main/java/org/linkeddatafragments/datasource/hdt/HdtDataSourceType.java b/src/main/java/org/linkeddatafragments/datasource/hdt/HdtDataSourceType.java deleted file mode 100644 index 0ae1afa..0000000 --- a/src/main/java/org/linkeddatafragments/datasource/hdt/HdtDataSourceType.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.linkeddatafragments.datasource.hdt; - -import java.io.File; -import java.io.IOException; - -import org.linkeddatafragments.datasource.IDataSource; -import org.linkeddatafragments.datasource.IDataSourceType; -import org.linkeddatafragments.exceptions.DataSourceCreationException; - -import com.google.gson.JsonObject; - -/** - * The type of HDT-backed Triple Pattern Fragment data sources. - * - * @author Olaf Hartig - */ -public class HdtDataSourceType implements IDataSourceType -{ - @Override - public IDataSource createDataSource( final String title, - final String description, - final JsonObject settings ) - throws DataSourceCreationException - { - final String fname = settings.getAsJsonPrimitive("file").getAsString(); - final File file = new File( fname ); - - try { - return new HdtDataSource(title, description, file.getAbsolutePath()); - } catch (IOException ex) { - throw new DataSourceCreationException(ex); - } - } - -} diff --git a/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java b/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java index 263e781..d39e471 100644 --- a/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java +++ b/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java @@ -55,7 +55,7 @@ public IndexRequestProcessorForTPFs( Resource datasourceUrl = new ResourceImpl(baseUrl + "/" + datasourceName); - model.add(datasourceUrl, new PropertyImpl(RDF + "type"), VOID + "Dataset"); + model.add(datasourceUrl, new PropertyImpl(RDF + "type"), new ResourceImpl(VOID + "Dataset")); model.add(datasourceUrl, new PropertyImpl(RDFS + "label"), datasource.getTitle()); model.add(datasourceUrl, new PropertyImpl(DC + "title"), datasource.getTitle()); model.add(datasourceUrl, new PropertyImpl(DC + "description"), datasource.getDescription()); diff --git a/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java b/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java index 33b7a8a..90d987d 100644 --- a/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java +++ b/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java @@ -14,6 +14,7 @@ import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.system.Txn; import org.apache.jena.tdb.TDBFactory; import org.linkeddatafragments.datasource.AbstractRequestProcessorForTriplePatterns; @@ -113,7 +114,7 @@ protected ILinkedDataFragment createFragment( Model triples = ModelFactory.createDefaultModel(); try (QueryExecution qexec = QueryExecutionFactory.create(query, model, map)) { - qexec.execConstruct(triples); + Txn.executeRead(tdb, () -> qexec.execConstruct(triples)); } if (triples.isEmpty()) { @@ -122,16 +123,17 @@ protected ILinkedDataFragment createFragment( // Try to get an estimate long size = triples.size(); - long estimate = -1; - - try (QueryExecution qexec = QueryExecutionFactory.create(countQuery, model, map)) { - ResultSet results = qexec.execSelect(); - if (results.hasNext()) { - QuerySolution soln = results.nextSolution() ; - Literal literal = soln.getLiteral("count"); - estimate = literal.getLong(); + long estimate = Txn.calculateRead(tdb, () -> { + try (QueryExecution qexec = QueryExecutionFactory.create(countQuery, model, map)) { + ResultSet results = qexec.execSelect(); + if (results.hasNext()) { + QuerySolution soln = results.nextSolution(); + Literal literal = soln.getLiteral("count"); + return literal.getLong(); + } + return -1L; } - } + }); /*GraphStatisticsHandler stats = model.getGraph().getStatisticsHandler(); if (stats != null) { diff --git a/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java b/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java index 10797d1..5847d23 100644 --- a/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java +++ b/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -13,8 +14,8 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; + +import org.apache.http.HttpHeaders; import org.apache.jena.riot.Lang; import org.linkeddatafragments.config.ConfigReader; import org.linkeddatafragments.datasource.DataSourceFactory; @@ -46,7 +47,7 @@ public class LinkedDataFragmentServlet extends HttpServlet { /** * */ - public final static String CFGFILE = "configFile"; + public final static String CFGFILE = "configFile"; private ConfigReader config; private final HashMap dataSources = new HashMap<>(); @@ -96,10 +97,10 @@ 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()); MIMEParse.register(Lang.RDFXML.getHeaderString()); + MIMEParse.register(Lang.NTRIPLES.getHeaderString()); + MIMEParse.register(Lang.JSONLD.getHeaderString()); + MIMEParse.register(Lang.TTL.getHeaderString()); } catch (Exception e) { throw new ServletException(e); } @@ -160,13 +161,14 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro ILinkedDataFragment fragment = null; try { // do conneg - String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); + String acceptHeader = request.getHeader(HttpHeaders.ACCEPT); + String bestMatch = MIMEParse.bestMatch(acceptHeader); // set additional response headers - response.setHeader("Server", "Linked Data Fragments Server"); + response.setHeader(HttpHeaders.SERVER, "Linked Data Fragments Server"); response.setContentType(bestMatch); - response.setCharacterEncoding("utf-8"); - + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + // create a writer depending on the best matching mimeType ILinkedDataFragmentWriter writer = LinkedDataFragmentWriterFactory.create(config.getPrefixes(), dataSources, bestMatch); @@ -180,7 +182,6 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro fragment = dataSource.getRequestProcessor() .createRequestedFragment( ldfRequest ); - writer.writeFragment(response.getOutputStream(), dataSource, fragment, ldfRequest); } catch (DataSourceNotFoundException ex) { @@ -191,11 +192,13 @@ 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); } } catch (Exception e) { + e.printStackTrace(); throw new ServletException(e); } finally { diff --git a/src/main/java/org/linkeddatafragments/standalone/JettyServer.java b/src/main/java/org/linkeddatafragments/standalone/JettyServer.java index 8e3a294e..a73fce0 100644 --- a/src/main/java/org/linkeddatafragments/standalone/JettyServer.java +++ b/src/main/java/org/linkeddatafragments/standalone/JettyServer.java @@ -1,20 +1,15 @@ package org.linkeddatafragments.standalone; +import java.net.URL; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; 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; /** @@ -36,7 +31,7 @@ public class JettyServer { private static void printHelp(Options options) { HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(JettyServer.class.getName() + " [config-example.json] []", + formatter.printHelp("java -jar target/ldf-server.jar [config-example.json] []", "Starts a standalone LDF Triple Pattern server. Options:", options, ""); } @@ -52,13 +47,13 @@ public static void main(String[] args) throws Exception { CommandLineParser parser = new DefaultParser(); CommandLine commandLine = parser.parse(options, args); - + String config = null; if (!commandLine.getArgList().isEmpty()) { config = commandLine.getArgs()[0]; } - if (config == null || commandLine.hasOption('h')) { + if (commandLine.hasOption('h')) { printHelp(options); System.exit(-1); } diff --git a/src/main/java/org/linkeddatafragments/util/MIMEParse.java b/src/main/java/org/linkeddatafragments/util/MIMEParse.java index 6b71bb3..86efa0b 100644 --- a/src/main/java/org/linkeddatafragments/util/MIMEParse.java +++ b/src/main/java/org/linkeddatafragments/util/MIMEParse.java @@ -264,8 +264,11 @@ public static String bestMatch(List supported, String header) throws NoR List parseResults = new LinkedList(); List weightedMatches = new LinkedList(); - for (String r : StringUtils.split(header, ',')) - parseResults.add(parseMediaRange(r)); + for (String r : StringUtils.split(header, ',')) { + try { + parseResults.add(parseMediaRange(r)); + } catch (Exception ex) {} // Fail silently on malformed media type and omit from list. + } for (String s : supported) { @@ -274,10 +277,13 @@ public static String bestMatch(List supported, String header) throws NoR fitnessAndQuality.mimeType = s; weightedMatches.add(fitnessAndQuality); } - Collections.sort(weightedMatches); + + + Collections.sort(weightedMatches); FitnessAndQuality lastOne = weightedMatches .get(weightedMatches.size() - 1); + return NumberUtils.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType : supported.get(0); } diff --git a/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java b/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java index 99883c0..90da504 100644 --- a/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java +++ b/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java @@ -5,6 +5,8 @@ import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; + +import org.apache.jena.query.ARQ; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.riot.Lang; @@ -26,6 +28,7 @@ class RdfWriterImpl extends LinkedDataFragmentWriterBase implements ILinkedDataF public RdfWriterImpl(Map prefixes, HashMap datasources, String mimeType) { super(prefixes, datasources); this.contentType = RDFLanguages.contentTypeToLang(mimeType); + ARQ.init(); } @Override @@ -47,7 +50,6 @@ public void writeFragment(ServletOutputStream outputStream, IDataSource datasour output.add(fragment.getMetadata()); output.add(fragment.getTriples()); output.add(fragment.getControls()); - RDFDataMgr.write(outputStream, output, contentType); } diff --git a/src/main/resources/views/base.ftl.html b/src/main/resources/views/base.ftl.html index 78ef1a5..ecaac88 100644 --- a/src/main/resources/views/base.ftl.html +++ b/src/main/resources/views/base.ftl.html @@ -4,9 +4,10 @@ - ${ title!header!"Linked Data Fragments Server" } + ${ title!header!"Linked Data Fragments Server" } + - + @@ -22,9 +23,9 @@

${header!"Linked Data Fragments Server"}

Powered by a Linked Data Fragments Server - ©2013–${date?string.yyyy} Multimedia Lab – iMinds – Ghent University + ©2013–${date?string.yyyy} Ghent University - imec

- \ No newline at end of file + diff --git a/src/main/resources/views/fragment.ftl.html b/src/main/resources/views/fragment.ftl.html index dc8480b..d7b2327 100644 --- a/src/main/resources/views/fragment.ftl.html +++ b/src/main/resources/views/fragment.ftl.html @@ -36,9 +36,9 @@

Matches in ${datasource.getTitle()} for ${ (query.getPat <@pageLinks/> <#else>

- <%= datasource.getTitle() %> contains + ${datasource.getTitle()} contains - no <#if totalEstimate > 0 >more + no <#if (totalEstimate > 0) >more triples that match this pattern.

@@ -52,14 +52,38 @@

Matches in ${datasource.getTitle()} for ${ (query.getPat <#assign object = triple.getObject().asNode().toString()>
  • - ${subject?keep_after_last("/")} + + <#if (subject?last_index_of("#") > -1) > + ${ subject?keep_after_last("#") } + <#elseif (subject?last_index_of("/") > -1)> + ${ subject?keep_after_last("/") } + <#else> + ${ subject } + + - ${predicate?keep_after_last("/")} + + <#if (predicate?last_index_of("#") > -1) > + ${ predicate?keep_after_last("#") } + <#elseif (predicate?last_index_of("/") > -1)> + ${ predicate?keep_after_last("/") } + <#else> + ${ predicate } + + <#if !triple.getObject().isLiteral()> - ${object?keep_after_last("/")} + + <#if (object?last_index_of("#") > -1) > + ${ object?keep_after_last("#") } + <#elseif (object?last_index_of("/") > -1)> + ${ object?keep_after_last("/") } + <#else> + ${ object } + + . <#else> ${object}. @@ -80,4 +104,4 @@

    Matches in ${datasource.getTitle()} for ${ (query.getPat
  • - \ No newline at end of file + diff --git a/src/test/java/org/linkeddatafragments/test/TestSuite.java b/src/test/java/org/linkeddatafragments/test/TestSuite.java index 1accb53..94ca45d 100644 --- a/src/test/java/org/linkeddatafragments/test/TestSuite.java +++ b/src/test/java/org/linkeddatafragments/test/TestSuite.java @@ -3,7 +3,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; -import org.linkeddatafragments.test.datasource.HdtDataSourceTest; import org.linkeddatafragments.test.datasource.JenaTDBDataSourceTest; /** @@ -12,7 +11,6 @@ */ @RunWith(Suite.class) @Suite.SuiteClasses({ - HdtDataSourceTest.class, JenaTDBDataSourceTest.class }) public class TestSuite { diff --git a/src/test/java/org/linkeddatafragments/test/datasource/HdtDataSourceTest.java b/src/test/java/org/linkeddatafragments/test/datasource/HdtDataSourceTest.java deleted file mode 100644 index bd1c52e..0000000 --- a/src/test/java/org/linkeddatafragments/test/datasource/HdtDataSourceTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.linkeddatafragments.test.datasource; - -import com.google.gson.JsonObject; - -import java.io.File; -import org.apache.jena.rdf.model.RDFNode; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.linkeddatafragments.datasource.DataSourceFactory; -import org.linkeddatafragments.datasource.DataSourceTypesRegistry; -import org.linkeddatafragments.datasource.hdt.HdtDataSourceType; -import org.linkeddatafragments.util.TriplePatternElementParser; -import org.linkeddatafragments.util.TriplePatternElementParserForJena; -import org.rdfhdt.hdt.enums.RDFNotation; -import org.rdfhdt.hdt.hdt.HDT; -import org.rdfhdt.hdt.hdt.HDTManager; -import org.rdfhdt.hdt.options.HDTSpecification; - -/** - * - * @author Bart Hanssens - */ -public class HdtDataSourceTest extends DataSourceTest { - - private static File hdtfile; - - /** - * - * @return - */ - @Override - protected TriplePatternElementParser - getTriplePatternElementParser() - { - return TriplePatternElementParserForJena.getInstance(); - } - - /** - * - * @throws Exception - */ - @BeforeClass - public static void setUpClass() throws Exception { - final String typeName = "HdtTestSourceType"; - if ( ! DataSourceTypesRegistry.isRegistered(typeName) ) { - DataSourceTypesRegistry.register( typeName, new HdtDataSourceType() ); - } - - // HDT does not seem to support an InputReader, so write to temp file - File temp = getResourceAsFile(); - - HDT mgr = HDTManager.generateHDT(temp.getAbsolutePath(), - "http://linkeddatafragments.org", - RDFNotation.NTRIPLES, new HDTSpecification(), null); - hdtfile = File.createTempFile("ldf-hdt-test", ".hdt"); - mgr.saveToHDT(hdtfile.getAbsolutePath(), null); - - temp.getAbsoluteFile().delete(); - - // Everything is in place, now create the LDF datasource - JsonObject config = createConfig("hdt test", "hdt test", typeName); - - JsonObject settings = new JsonObject(); - settings.addProperty("file", hdtfile.getAbsolutePath()); - config.add("settings", settings); - - setDatasource(DataSourceFactory.create(config)); - } - - /** - * - * @throws Exception - */ - @AfterClass - public static void tearDownClass() throws Exception { - if (hdtfile != null) { - hdtfile.delete(); - } - } - - /** - * - * @throws Exception - */ - @Before - public void setUp() throws Exception { - - } - - /** - * - * @throws Exception - */ - @After - public void tearDown() throws Exception { - } -} diff --git a/src/test/java/org/linkeddatafragments/test/datasource/IndexRequestProcessorForTPFsTest.java b/src/test/java/org/linkeddatafragments/test/datasource/IndexRequestProcessorForTPFsTest.java new file mode 100644 index 0000000..edc8b5b --- /dev/null +++ b/src/test/java/org/linkeddatafragments/test/datasource/IndexRequestProcessorForTPFsTest.java @@ -0,0 +1,114 @@ +package org.linkeddatafragments.datasource; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.junit.Assert; +import org.junit.Test; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.datasource.index.IndexRequestProcessorForTPFs; +import org.linkeddatafragments.fragments.IFragmentRequestParser; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; +import org.linkeddatafragments.fragments.tpf.TriplePatternElementFactory; +import org.linkeddatafragments.fragments.tpf.TriplePatternFragmentRequestImpl; + +/** + * Test cases for the IndexRequestProcessorForTPFs + * + * @author Lars G. Svensson + */ +public class IndexRequestProcessorForTPFsTest { + + static class TestIndexRequestProcessor extends IndexRequestProcessorForTPFs { + TestIndexRequestProcessor(final String baseUrl, + final HashMap datasources) { + super(baseUrl, datasources); + } + + @Override + protected TestWorker getTPFSpecificWorker( + final ITriplePatternFragmentRequest request) + throws IllegalArgumentException { + return new TestWorker(request); + } + + class TestWorker extends IndexRequestProcessorForTPFs.Worker { + public TestWorker( + final ITriplePatternFragmentRequest req) { + super(req); + } + } + } + + /** + * Check that the type void:Dataset is returned as a URI and not as a + * literal + */ + @Test + public void shouldGiveVoidDatasetAsAURI() { + final IDataSource datasource = new IDataSource() { + @Override + public String getDescription() { + return "This is a dummy datasource"; + }; + + @Override + public IFragmentRequestParser getRequestParser() { + return null; + } + + @Override + public IFragmentRequestProcessor getRequestProcessor() { + return null; + } + + @Override + public String getTitle() { + return "Dummy Dataource"; + } + + @Override + public void close() { + // does nothing + } + }; + final HashMap datasources = new HashMap(); + datasources.put("dummy", datasource); + final String baseUrl = "dummy"; + final TestIndexRequestProcessor processor = new TestIndexRequestProcessor( + baseUrl, datasources); + final TriplePatternElementFactory factory = new TriplePatternElementFactory(); + final ITriplePatternFragmentRequest request = new TriplePatternFragmentRequestImpl( + null, "dummy", false, 1, factory.createUnspecifiedVariable(), + factory.createUnspecifiedVariable(), + factory.createUnspecifiedVariable()); + final TestIndexRequestProcessor.TestWorker worker = processor + .getTPFSpecificWorker(request); + final ILinkedDataFragment fragment = worker.createRequestedFragment(); + final StmtIterator iterator = fragment.getTriples(); + final Collection statements = new ArrayList(); + while (iterator.hasNext()) { + statements.add(iterator.next()); + } + + final Resource subject = ResourceFactory.createResource("dummy/dummy"); + final Property predicate = ResourceFactory + .createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + final Resource object = ResourceFactory + .createResource("http://rdfs.org/ns/void#Dataset"); + final Statement expected = ResourceFactory.createStatement(subject, + predicate, object); + Assert.assertTrue("triple not contained in model", + statements.contains(expected)); + processor.close(); + } +} diff --git a/src/test/java/org/linkeddatafragments/test/datasource/JenaTDBDataSourceTest.java b/src/test/java/org/linkeddatafragments/test/datasource/JenaTDBDataSourceTest.java index 1af273d..9e1fbb3 100644 --- a/src/test/java/org/linkeddatafragments/test/datasource/JenaTDBDataSourceTest.java +++ b/src/test/java/org/linkeddatafragments/test/datasource/JenaTDBDataSourceTest.java @@ -3,6 +3,7 @@ import com.google.gson.JsonObject; import org.apache.jena.query.Dataset; +import org.apache.jena.query.ReadWrite; import org.apache.jena.rdf.model.Model; import org.apache.jena.tdb.TDBFactory; @@ -63,6 +64,7 @@ public static void setUpClass() throws Exception { dataset = TDBFactory.createDataset(jena.getAbsolutePath()); + dataset.begin(ReadWrite.WRITE); Model model = dataset.getDefaultModel(); InputStream in = ClassLoader.getSystemResourceAsStream("demo.nt"); RDFDataMgr.read(model, in, Lang.NTRIPLES);