From d6094eeb5010cedc74502c70951c43475961e6ec Mon Sep 17 00:00:00 2001 From: j2blake Date: Fri, 4 Oct 2013 15:37:17 -0400 Subject: [PATCH] VIVO-295 Added a metadata section to LOD results. Includes date and rights, among other things. While we're at it, support LOD requests with /n123/n123.jsonld --- .../individual/IndividualRdfAssembler.java | 78 +++++++++++++++++++ .../individual/IndividualRequestAnalyzer.java | 9 ++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java index 50d4d40c2..90e79cde7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java @@ -2,6 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.individual; +import java.util.Date; import java.util.HashSet; import java.util.Set; @@ -11,10 +12,13 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.NodeIterator; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.Statement; @@ -33,6 +37,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RdfResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; @@ -71,6 +76,17 @@ public class IndividualRdfAssembler { private static final String RICH_EXPORT_ROOT = "/WEB-INF/rich-export/"; private static final String INCLUDE_ALL = "all"; + private static final String NS_DC = "http://purl.org/dc/elements/1.1/"; + private static final String URI_RIGHTS = NS_DC + "rights"; + private static final String URI_DATE = NS_DC + "date"; + private static final String URI_PUBLISHER = NS_DC + "publisher"; + + private static final String NS_FOAF = "http://xmlns.com/foaf/0.1/"; + private static final String URI_DOCUMENT = NS_FOAF + "Document"; + + private static final String URI_LABEL = VitroVocabulary.RDFS + "label"; + private static final String URI_TYPE = VitroVocabulary.RDF_TYPE; + private final VitroRequest vreq; private final ServletContext ctx; private final String individualUri; @@ -118,6 +134,7 @@ public class IndividualRdfAssembler { o.add(getStatementsAboutEntity()); o.add(getLabelsAndTypesOfRelatedObjects()); filterByPolicy(o); + addDocumentMetadata(o); return o; } @@ -268,4 +285,65 @@ public class IndividualRdfAssembler { return richExportModel; } + /** + * Add info about the RDF itself. + * + * It will look something like this: + * + *
+	 * 
+	 *     rdfs:label "RDF description of Baker, Able - http://vivo.cornell.edu/individual/n6628" ;
+	 *     rdf:type foaf:Document ;
+	 *     dc:publisher  ;
+	 *     dc:date "2007-07-13"^^xsd:date ;
+	 *     dc:rights  .
+	 * 
+ */ + private void addDocumentMetadata(OntModel o) { + String baseUrl = figureBaseUrl(); + String documentUri = createDocumentUri(); + String label = createDocumentLabel(o); + Literal dateLiteral = createDateLiteral(o); + + Resource md = o.getResource(documentUri); + + o.add(md, o.getProperty(URI_LABEL), label); + o.add(md, o.getProperty(URI_TYPE), o.getResource(URI_DOCUMENT)); + o.add(md, o.getProperty(URI_PUBLISHER), o.getResource(baseUrl)); + o.add(md, o.getProperty(URI_DATE), dateLiteral); + o.add(md, o.getProperty(URI_RIGHTS), + o.getResource(baseUrl + "/termsOfUse")); + } + + private String figureBaseUrl() { + int cutHere = individualUri.indexOf("/individual"); + return (cutHere > 0) ? individualUri.substring(0, cutHere) + : individualUri; + } + + private String createDocumentUri() { + return vreq.getRequestURL().toString(); + } + + private String createDocumentLabel(OntModel o) { + String label = null; + NodeIterator nodes = o.listObjectsOfProperty( + o.getResource(individualUri), o.getProperty(URI_LABEL)); + while (nodes.hasNext()) { + RDFNode n = nodes.nextNode(); + if (n.isLiteral()) { + label = n.asLiteral().getString(); + } + } + if (label == null) { + return "RDF description of " + individualUri; + } else { + return "RDF description of " + label + " - " + individualUri; + } + } + + private Literal createDateLiteral(OntModel o) { + return o.createTypedLiteral(new Date(), XSDDatatype.XSDdate); + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRequestAnalyzer.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRequestAnalyzer.java index c0e8561d9..24c69d358 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRequestAnalyzer.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRequestAnalyzer.java @@ -28,7 +28,7 @@ public class IndividualRequestAnalyzer { .getLog(IndividualRequestAnalyzer.class); - private static Pattern RDF_REQUEST = Pattern.compile("^/individual/([^/]+)/\\1\\.(rdf|n3|ttl)$"); + private static Pattern RDF_REQUEST = Pattern.compile("^/individual/([^/]+)/\\1\\.(rdf|n3|ttl|jsonld)$"); private static Pattern HTML_REQUEST = Pattern.compile("^/display/([^/]+)$"); private static Pattern LINKED_DATA_URL = Pattern.compile("^/individual/([^/]+)$"); @@ -145,7 +145,7 @@ public class IndividualRequestAnalyzer { IndividualController.ACCEPTED_CONTENT_TYPES); if (RDFXML_MIMETYPE.equals(ctStr) || N3_MIMETYPE.equals(ctStr) - || TTL_MIMETYPE.equals(ctStr)) { + || TTL_MIMETYPE.equals(ctStr) || JSON_MIMETYPE.equals(ctStr)) { return new ContentType(ctStr); } } catch (Throwable th) { @@ -167,6 +167,7 @@ public class IndividualRequestAnalyzer { * /individual/localname/localname.rdf * /individual/localname/localname.n3 * /individual/localname/localname.ttl + * /individual/localname/localname.jsonld * * * @return null on failure. @@ -257,6 +258,7 @@ public class IndividualRequestAnalyzer { * http://vivo.cornell.edu/individual/n23/n23.rdf * http://vivo.cornell.edu/individual/n23/n23.n3 * http://vivo.cornell.edu/individual/n23/n23.ttl + * http://vivo.cornell.edu/individual/n23/n23.jsonld */ Matcher rdfMatch = RDF_REQUEST.matcher(url); if (rdfMatch.matches() && rdfMatch.groupCount() == 2) { @@ -270,6 +272,9 @@ public class IndividualRequestAnalyzer { if ("ttl".equals(rdfType)) { return ContentType.TURTLE; } + if ("jsonld".equals(rdfType)) { + return ContentType.JSON; + } } return null;