diff --git a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Main.java b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Main.java index e90ef368092907e86e1b5f5f8c3abfe8568a0a09..0257e6783da17cb285d7663e521ec57f99572b10 100644 --- a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Main.java +++ b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Main.java @@ -18,6 +18,7 @@ public class Main { get("/queries", Routes.queries, new FreeMarkerEngine()); get("/explore", Routes.explore, new FreeMarkerEngine()); get("/explore/contributor/:contributor", Routes.exploreContributor, new FreeMarkerEngine()); + get("/explore/node/:base64uri", Routes.exploreNode, new FreeMarkerEngine()); internalServerError(Errors.internalServerError); notFound(Errors.notFound); diff --git a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/PrintableIRI.java b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/PrintableIRI.java new file mode 100644 index 0000000000000000000000000000000000000000..7ef356c2039ca053544d4b17dcca475ed25f5540 --- /dev/null +++ b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/PrintableIRI.java @@ -0,0 +1,59 @@ +package info.mathhub.uloapi.html; + +import org.eclipse.rdf4j.model.IRI; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Wrapper around {@link IRI} that provides additional + * methods for use in Freemarker templates. + */ +public class PrintableIRI implements IRI { + private final IRI original; + + public PrintableIRI(IRI original) { + this.original = original; + } + + /** + * Convert a list of {@link IRI} to {@link PrintableIRI}. + */ + public static List<PrintableIRI> convert(List<IRI> originals) { + return originals.stream().map(PrintableIRI::new).collect(Collectors.toList()); + } + + @Override + public String toString() { + return this.original.toString(); + } + + @Override + public String getNamespace() { + return this.original.getNamespace(); + } + + @Override + public String getLocalName() { + return this.original.getLocalName(); + } + + @Override + public String stringValue() { + return this.original.stringValue(); + } + + @Override + public boolean equals(Object o) { + return this.original.equals(o); + } + + @Override + public int hashCode() { + return this.original.hashCode(); + } + + public String toBase64() { + return Base64.encode(this.toString()); + } +} diff --git a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Routes.java b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Routes.java index 1ff7c5ad00d645f9fc59e7480921a12bc82ad8a8..9f1d9a6f56036776e9714d089f6b0f84d4c667a1 100644 --- a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Routes.java +++ b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/html/Routes.java @@ -67,7 +67,7 @@ public class Routes { final Query query = Query.getSingleton(); final String contributor = request.params("contributor"); - final List<IRI> contributions = query.getContributions(contributor); + final List<PrintableIRI> contributions = PrintableIRI.convert(query.getContributions(contributor)); final Map<String, Object> model = new HashMap<>(); model.put("contributor", contributor); @@ -76,6 +76,21 @@ public class Routes { return new ModelAndView(withGlobals(model), "explore_contributor.flt"); }; + public static final TemplateViewRoute exploreNode = (Request request, Response response) -> { + final Query query = Query.getSingleton(); + + final String base64uri = request.params("base64uri"); + final String uri = Base64.decode(base64uri); + + final List<PrintableIRI> uses = PrintableIRI.convert(query.getUses(uri)); + + final Map<String, Object> model = new HashMap<>(); + model.put("uri", uri); + model.put("uses", uses); + + return new ModelAndView(withGlobals(model), "explore_node.flt"); + }; + /** * Add some global values we always need to argument {@code model}. * diff --git a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/IRIs.java b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/IRIs.java new file mode 100644 index 0000000000000000000000000000000000000000..8d7f6a69606e23c0cdde060d74fd020771434a9a --- /dev/null +++ b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/IRIs.java @@ -0,0 +1,24 @@ +package info.mathhub.uloapi.query; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +public class IRIs { + private IRIs() {} + + /** + * Create an {@link IRI} from argument {@code value}. + * + * @param value The argument to turn into an {@link IRI}. + * @return An {@link IRI} that contains argument {@code value}. + */ + public static IRI fromString(String value) { + if (value == null) { + throw new NullPointerException("argument value must not be null"); + } + + final ValueFactory valueFactory = SimpleValueFactory.getInstance(); + return valueFactory.createIRI(value); + } +} diff --git a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/Query.java b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/Query.java index 127246c480aa0c9ffad0a8bdea621a343a7bafa2..3b694472af0f8422ae274664e6c569088d3545d9 100644 --- a/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/Query.java +++ b/src/ulo-storage-applications/src/main/java/info/mathhub/uloapi/query/Query.java @@ -167,4 +167,34 @@ public class Query { return GraphDB.execute(this.serverUrl, this.repository, operation); } + + /** + * Return a list of works used by another given node. + * + * @param nodeuri The URI of the node. + */ + public List<IRI> getUses(String nodeuri) { + final GraphDB.Operation<List<IRI>> operation = (manager, repository, connection) -> { + final Set<IRI> uses = new HashSet<>(); + final IRI subject = IRIs.fromString(nodeuri); + + final RepositoryResult<Statement> result = connection.getStatements(subject, ULO.uses, null); + + for (final Statement statement : result) { + final Value object = statement.getObject(); + + if (!(object instanceof IRI)) { + log.warn("found object that is not an IRI"); + continue; + } + + final IRI asIri = (IRI) object; + uses.add(asIri); + } + + return new ArrayList<>(uses); + }; + + return GraphDB.execute(this.serverUrl, this.repository, operation); + } } diff --git a/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_contributor.flt b/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_contributor.flt index 8bb396b12a3507f8a9b4754e5994a559ffa377aa..1c0c2d7d3593c2c09b29e701c24066fbca5d0b7a 100644 --- a/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_contributor.flt +++ b/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_contributor.flt @@ -16,7 +16,9 @@ <ul> <#list contributions as contribution> <li> - <code>${contribution}</code> + <a href="/explore/node/${contribution.toBase64()?url}"> + <code>${contribution}</code> + </a> </li> </#list> </ul> diff --git a/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_node.flt b/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_node.flt new file mode 100644 index 0000000000000000000000000000000000000000..7d2caae0d490b73c03c7f430bfed2e361b1060b3 --- /dev/null +++ b/src/ulo-storage-applications/src/main/resources/spark/template/freemarker/explore_node.flt @@ -0,0 +1,35 @@ +<#ftl output_format="HTML" auto_esc=false> +<#setting url_escaping_charset='UTF-8'> + +<#include "base.flt"> + +<#macro page_title> + Explore Node +</#macro> + +<#macro page_main> + + <h2>Explore Node</h2> + + <h3>URI</h3> + + <ul> + <li> + <code>${uri}</code> + </li> + </ul> + + <h3>Node uses...</h3> + + <ul> + <#list uses as use> + <li> + <a href="/explore/node/${use.toBase64()?url}"> + <code>${use}</code> + </a> + </li> + </#list> + </ul> +</#macro> + +<@display_page/>