diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Main.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Main.java index f84bdfcd6d28fa221ef14b83ced3e75d2dc0c9b8..82790004902de0b78363874ef480c2dd357cd0c4 100644 --- a/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Main.java +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Main.java @@ -13,6 +13,7 @@ public class Main { public static void main(String[] args) { get("/", Routes.index, new FreeMarkerEngine()); get("/statistics", Routes.statistics, new FreeMarkerEngine()); + get("/queries", Routes.queries, new FreeMarkerEngine()); internalServerError(Errors.internalServerError); notFound(Errors.notFound); diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Routes.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Routes.java index 1776d2b9d2ddcbac7c0564f9cbea0bd9063636d8..626c014f86e50b8fd97c138eb3a0cee3c6512f49 100644 --- a/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Routes.java +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/html/Routes.java @@ -2,9 +2,12 @@ package info.mathhub.uloapi.html; import info.mathhub.uloapi.query.Query; import info.mathhub.uloapi.query.Statistics; +import info.mathhub.uloapi.query.Timer; +import org.eclipse.rdf4j.model.Statement; import spark.*; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -28,4 +31,18 @@ public class Routes { return new ModelAndView(model, "statistics.flt"); }; + + public static final TemplateViewRoute queries = (Request request, Response response) -> { + final Query query = Query.getSingleton(); + + final Timer inductiveStatementsTimer = new Timer(); + final List<Statement> inductiveStatements = query.getInductiveStatements(); + final long inductiveStatementsDuration = inductiveStatementsTimer.elapsedMs(); + + final Map<String, Object> model = new HashMap<>(); + model.put("inductive_statements", inductiveStatements); + model.put("inductive_statements_duration", inductiveStatementsDuration); + + return new ModelAndView(model, "queries.flt"); + }; } diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Query.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Query.java index 8369c91dfa3b5d90f6a430dce769895c9db8d121..7467424c5afcfcbd0edff05dd9fc88fb27a2b01e 100644 --- a/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Query.java +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Query.java @@ -1,20 +1,39 @@ package info.mathhub.uloapi.query; import info.mathhub.uloapi.config.Config; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.repository.RepositoryResult; import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +/** + * Class {@link Query} wraps various common queries to an RDF4j endpoint. Objects of type {@link Query} + * are safe for concurrent used by multiple threads. + */ public class Query { private final String serverUrl; private final String repository; private static Query singleton; + /** + * Create a new object for the given endpoint. + * + * @param serverUrl URL of the RDF4J endpoint. Usually some kind of HTTP(S) URI. + * @param repository Name of the repository to connect to. + */ public Query(String serverUrl, String repository) { this.serverUrl = serverUrl; this.repository = repository; } + /** + * Get {@link Query} instance that is configured to connect to the endpoint defined + * in {@code uloapi.properties}. + */ public static synchronized Query getSingleton() { if (Query.singleton == null) { Query.singleton = new Query(Config.serverUrl(), Config.repository()); @@ -23,6 +42,9 @@ public class Query { return Query.singleton; } + /** + * Return {@link Statistics} that contain some meta data about the connected repository. + */ public Statistics getStatistics() { final GraphDB.Operation<Statistics> operation = (manager, repository, connection) -> { final Statistics statistics = new Statistics(); @@ -43,4 +65,28 @@ public class Query { return GraphDB.execute(this.serverUrl, this.repository, operation); } + + /** + * Return a list of triplets that define some kind of {@link ULO#INDUCTIVE_ON} relationship. + * + * @return The triplets. Limited to a small number, the actual number of matching triplets in the + * underlying RDF4j repository might be way bigger. + */ + public List<Statement> getInductiveStatements() { + final GraphDB.Operation<List<Statement>> operation = (manager, repository, connection) -> { + final RepositoryResult<Statement> result = connection.getStatements(null, ULO.INDUCTIVE_ON, null); + final Iterator<Statement> iterator = result.iterator(); + + final List<Statement> statements = new ArrayList<>(); + + for (int i = 0; i < 16 && iterator.hasNext(); i++) { + final Statement statement = iterator.next(); + statements.add(statement); + } + + return statements; + }; + + return GraphDB.execute(this.serverUrl, this.repository, operation); + } } diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Timer.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Timer.java new file mode 100644 index 0000000000000000000000000000000000000000..11bd881eafc858808bd0e1410b50ac0b29b905e5 --- /dev/null +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/Timer.java @@ -0,0 +1,23 @@ +package info.mathhub.uloapi.query; + +/** + * Class for timing execution of methods. Create a new {@link Timer} object, + * run some operation and then get the elapsed time with {@link Timer#elapsedMs}. + */ +public class Timer { + private final long startMs; + + public Timer() { + this.startMs = System.currentTimeMillis(); + } + + /** + * Return elapsed time since this object has been created. + * + * @return Elapsed time since object creation in milliseconds. + */ + public long elapsedMs() { + final long stopMs = System.currentTimeMillis(); + return stopMs - this.startMs; + } +} diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/ULO.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/ULO.java index 75884ec67a4c2fde35507a0636bcd0f5d61c1e54..fc1b050404cae20ad6b7c11bb234a5a3971be08b 100644 --- a/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/ULO.java +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/query/ULO.java @@ -5,7 +5,6 @@ import org.eclipse.rdf4j.model.Namespace; import org.eclipse.rdf4j.model.ValueFactory; import org.eclipse.rdf4j.model.impl.SimpleNamespace; import org.eclipse.rdf4j.model.impl.SimpleValueFactory; -import org.eclipse.rdf4j.model.vocabulary.FOAF; /** * Constants for use with ULO, the Upper Library Ontology [1]. diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Errors.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Errors.java index b5142d5b0429c287ef4d997b51ab03a362deb785..07dd798c555ad6691b21d3663529f34915c40b2c 100644 --- a/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Errors.java +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Errors.java @@ -4,7 +4,6 @@ import com.google.gson.Gson; import org.eclipse.jetty.http.HttpStatus; import spark.Request; import spark.Response; -import spark.ResponseTransformer; import spark.Route; public class Errors { diff --git a/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Routes.java b/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Routes.java index d563690a489f55464333dc31d1237627a0fd142b..c59693189e313061c64f83d6533dc5d3a4932d3d 100644 --- a/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Routes.java +++ b/experimental/uloapi/src/main/java/info/mathhub/uloapi/rest/Routes.java @@ -1,7 +1,6 @@ package info.mathhub.uloapi.rest; import info.mathhub.uloapi.query.Query; -import org.eclipse.jetty.http.HttpStatus; import spark.*; import java.util.HashMap; diff --git a/experimental/uloapi/src/main/resources/spark/template/freemarker/base.flt b/experimental/uloapi/src/main/resources/spark/template/freemarker/base.flt index a0d1317491b573468964f577969c6b2fe067f9aa..19d8bea991f0235fdac3662046c92da83d6317dd 100644 --- a/experimental/uloapi/src/main/resources/spark/template/freemarker/base.flt +++ b/experimental/uloapi/src/main/resources/spark/template/freemarker/base.flt @@ -14,6 +14,7 @@ <title><@page_title/></title> <style> * { + background-color: white; font-family: "Open Sans", Helvetica, Arial; font-size: 12pt; } @@ -36,6 +37,14 @@ display: inline-block; font-weight: bold; } + + h2 { + font-size: 14pt; + } + + table { + text-align: left; + } </style> </head> <body> diff --git a/experimental/uloapi/src/main/resources/spark/template/freemarker/queries.flt b/experimental/uloapi/src/main/resources/spark/template/freemarker/queries.flt new file mode 100644 index 0000000000000000000000000000000000000000..82c6db0819190591fe0956ff4affbff80bfe05c1 --- /dev/null +++ b/experimental/uloapi/src/main/resources/spark/template/freemarker/queries.flt @@ -0,0 +1,36 @@ +<#include "base.flt"> + +<#macro page_title> + Statistics +</#macro> + +<#macro page_main> + <h2>Queries</h2> + + <p> + This page contains various example queries. They were executed using RDF4j which you + can think of as SPARQL for JVM languages. + </p> + + <h3>Inductive Queries</h3> + + <p> + Show some tuples where <em>x</em> is inductive on <em>y</em>. + Query took ${inductive_statements_duration} ms. + </p> + + <table> + <tr> + <th>Subject <em>x</em></th> + <th>Object <em>y</em></th> + </tr> + <#list inductive_statements as statement> + <tr> + <td>${statement.subject}</td> + <td>${statement.object}</td> + </tr> + </#list> + </table> +</#macro> + +<@display_page/>