| package org.purl.wf4ever.robundle.manifest; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.UUID; |
| |
| import org.apache.jena.riot.RDFDataMgr; |
| import org.apache.jena.riot.RiotException; |
| |
| import com.github.jsonldjava.jena.JenaJSONLD; |
| import com.hp.hpl.jena.ontology.DatatypeProperty; |
| import com.hp.hpl.jena.ontology.Individual; |
| import com.hp.hpl.jena.ontology.ObjectProperty; |
| import com.hp.hpl.jena.ontology.OntClass; |
| import com.hp.hpl.jena.ontology.OntModel; |
| import com.hp.hpl.jena.ontology.OntResource; |
| import com.hp.hpl.jena.rdf.model.Model; |
| import com.hp.hpl.jena.rdf.model.ModelFactory; |
| import com.hp.hpl.jena.rdf.model.RDFNode; |
| import com.hp.hpl.jena.rdf.model.Resource; |
| import com.hp.hpl.jena.util.iterator.ExtendedIterator; |
| |
| public class RDFToManifest { |
| private static final URI ROOT = URI.create("/"); |
| private static final String PROV = "http://www.w3.org/ns/prov#"; |
| private static final String PROV_O = "http://www.w3.org/ns/prov-o#"; |
| private static final String FOAF_0_1 = "http://xmlns.com/foaf/0.1/"; |
| private static final String PAV = "http://purl.org/pav/"; |
| |
| private static final String RO = "http://purl.org/wf4ever/ro#"; |
| private static final String ORE = "http://www.openarchives.org/ore/terms/"; |
| private static final String FOAF_RDF = "/ontologies/foaf.rdf"; |
| private static final String PAV_RDF = "/ontologies/pav.rdf"; |
| private static final String PROV_O_RDF = "/ontologies/prov-o.rdf"; |
| private static final String PROV_AQ_RDF = "/ontologies/prov-aq.rdf"; |
| private OntModel ore; |
| private ObjectProperty aggregates; |
| private ObjectProperty proxyFor; |
| private ObjectProperty proxyIn; |
| |
| private OntClass aggregation; |
| private OntModel foaf; |
| private DatatypeProperty foafName; |
| private OntModel pav; |
| private ObjectProperty createdBy; |
| private OntModel prov; |
| private OntModel provaq; |
| private ObjectProperty hasProvenance; |
| |
| public RDFToManifest() { |
| loadOntologies(); |
| } |
| |
| protected void loadOntologies() { |
| loadORE(); |
| loadFOAF(); |
| loadPROVO(); |
| loadPAV(); |
| loadPROVAQ(); |
| } |
| |
| protected OntModel loadOntologyFromClasspath(String classPathUri, String uri) { |
| OntModel ontModel = ModelFactory.createOntologyModel(); |
| |
| // Load from classpath |
| InputStream inStream = getClass().getResourceAsStream(classPathUri); |
| if (inStream == null) { |
| throw new IllegalArgumentException("Can't load " + classPathUri); |
| } |
| // Ontology ontology = ontModel.createOntology(uri); |
| ontModel.read(inStream, uri); |
| return ontModel; |
| } |
| |
| |
| |
| |
| protected static Model jsonLdAsJenaModel(InputStream jsonIn, URI base) throws IOException, |
| RiotException { |
| JenaJSONLD.init(); |
| Model model = ModelFactory.createDefaultModel(); |
| RDFDataMgr.read(model, jsonIn, base.toASCIIString(), JenaJSONLD.JSONLD); |
| return model; |
| |
| // |
| // Object input = JSONUtils.fromInputStream(jsonIn); |
| // JSONLDTripleCallback callback = new JenaTripleCallback(); |
| // Model model = (Model)JSONLD.toRDF(input, callback, new Options(base.toASCIIString())); |
| // return model; |
| } |
| |
| private void checkNotNull(Object... possiblyNulls) { |
| int i=0; |
| for (Object check : possiblyNulls) { |
| if (check == null) { |
| throw new IllegalStateException("Could not load item #" + i); |
| } |
| i++; |
| } |
| |
| } |
| |
| |
| protected OntModel getOntModel() { |
| OntModel ontModel = ModelFactory.createOntologyModel(); |
| ontModel.setNsPrefix("foaf", FOAF_0_1); |
| ontModel.setNsPrefix("prov", PROV); |
| ontModel.setNsPrefix("ore", ORE); |
| ontModel.setNsPrefix("pav", PAV); |
| // ontModel.getDocumentManager().loadImports(foaf.getOntModel()); |
| return ontModel; |
| } |
| // |
| protected synchronized void loadFOAF() { |
| if (foaf != null) { |
| return; |
| } |
| |
| OntModel ontModel = loadOntologyFromClasspath(FOAF_RDF, FOAF_0_1); |
| |
| // properties from foaf |
| foafName = ontModel.getDatatypeProperty(FOAF_0_1 + "name"); |
| checkNotNull(foafName); |
| |
| foaf = ontModel; |
| } |
| |
| |
| protected synchronized void loadPAV() { |
| if (pav != null) { |
| return; |
| } |
| |
| OntModel ontModel = loadOntologyFromClasspath(PAV_RDF, PAV); |
| |
| // properties from foaf |
| createdBy = ontModel.getObjectProperty(PAV + "createdBy"); |
| checkNotNull(createdBy); |
| |
| pav = ontModel; |
| } |
| |
| protected synchronized void loadPROVO() { |
| if (prov != null) { |
| return; |
| } |
| OntModel ontModel = loadOntologyFromClasspath(PROV_O_RDF, PROV_O); |
| |
| checkNotNull(ontModel); |
| |
| prov = ontModel; |
| } |
| |
| |
| protected synchronized void loadPROVAQ() { |
| if (provaq != null) { |
| return; |
| } |
| OntModel ontModel = loadOntologyFromClasspath(PROV_AQ_RDF, PAV); |
| |
| // properties from foaf |
| hasProvenance = ontModel.getObjectProperty(PROV + "has_provenance"); |
| checkNotNull(hasProvenance); |
| |
| provaq = ontModel; |
| } |
| |
| |
| protected synchronized void loadORE() { |
| if (ore != null) { |
| return; |
| } |
| OntModel ontModel = loadOntologyFromClasspath("/ontologies/ore-owl.owl", "http://purl.org/wf4ever/ore-owl"); |
| aggregation = ontModel.getOntClass(ORE + "Aggregation"); |
| |
| aggregates = ontModel.getObjectProperty(ORE + "aggregates"); |
| proxyFor = ontModel.getObjectProperty(ORE + "proxyFor"); |
| proxyIn = ontModel.getObjectProperty(ORE + "proxyIn"); |
| |
| checkNotNull(aggregation, aggregates, proxyFor, proxyIn); |
| |
| |
| ore = ontModel; |
| } |
| |
| public static <T> ClosableIterable<T> iterate(ExtendedIterator<T> iterator) { |
| return new ClosableIterable<T>(iterator); |
| } |
| |
| public static class ClosableIterable<T> implements AutoCloseable, Iterable<T> { |
| |
| private ExtendedIterator<T> iterator; |
| |
| public ClosableIterable(ExtendedIterator<T> iterator) { |
| this.iterator = iterator; |
| } |
| |
| @Override |
| public void close() { |
| iterator.close(); |
| } |
| |
| @Override |
| public ExtendedIterator<T> iterator() { |
| return iterator; |
| } |
| } |
| |
| public void readTo(InputStream resourceAsStream, Manifest manifest) throws IOException, RiotException { |
| OntModel model = new RDFToManifest().getOntModel(); |
| URI base; |
| try { |
| base = makeBaseURI(); |
| } catch (URISyntaxException e) { |
| throw new IllegalStateException("Can't make base URI of form app://{uuid}/", e); |
| } |
| try (InputStream jsonIn = getClass().getResourceAsStream("/manifest.json")) { |
| model.add(jsonLdAsJenaModel(jsonIn, base)); |
| } |
| |
| Individual ro = findRO(model, base); |
| for (Individual in : listObjectProperties(ro, aggregates)) { |
| String uriStr = in.getURI(); |
| PathMetadata meta = new PathMetadata(); |
| if (uriStr != null) { |
| meta.setUri(relativizeFromBase(uriStr, base)); |
| } |
| Resource proxy = in.getPropertyResourceValue(proxyFor); |
| if (proxy != null && proxy.getURI() != null) { |
| meta.setProxy(relativizeFromBase(proxy.getURI(), base)); |
| } |
| |
| List<Agent> creators = new ArrayList<>(); |
| for (Individual agent : listObjectProperties(in, createdBy)) { |
| Agent a = new Agent(); |
| if (agent.getURI() != null) { |
| a.setUri(relativizeFromBase(agent.getURI(), base)); |
| |
| RDFNode name = agent.getPropertyValue(foafName); |
| if (name != null && name.isLiteral()) { |
| a.setName(name.asLiteral().getLexicalForm()); |
| } |
| } |
| creators.add(a); |
| } |
| if (! creators.isEmpty()) { |
| manifest.setCreatedBy(creators); |
| } |
| |
| manifest.getAggregates().add(meta); |
| } |
| |
| |
| |
| // model.write(System.out, "TURTLE"); |
| |
| } |
| |
| private URI relativizeFromBase(String uriStr, URI base) { |
| return ROOT.resolve(base.relativize(URI.create(uriStr))); |
| } |
| |
| protected static URI makeBaseURI() throws URISyntaxException { |
| return new URI("app", UUID.randomUUID().toString(), "/", (String)null); |
| } |
| |
| |
| |
| |
| private Set<Individual> listObjectProperties(Individual in, |
| ObjectProperty prop) { |
| LinkedHashSet<Individual> results = new LinkedHashSet<>(); |
| try (ClosableIterable<RDFNode> props = iterate(in.listPropertyValues(prop))) { |
| for (RDFNode node : props) { |
| if (! node.isResource() || ! node.canAs(Individual.class)) { |
| continue; |
| } |
| results.add(node.as(Individual.class)); |
| } |
| } |
| return results; |
| } |
| |
| private Individual findRO(OntModel model, URI base) { |
| try (ClosableIterable<? extends OntResource> instances = iterate(aggregation.listInstances())) { |
| for (OntResource o : instances) { |
| System.out.println("Woo " + o); |
| return o.asIndividual(); |
| } |
| } |
| // Fallback - resolve as "/" |
| // TODO: Ensure it's an Aggregation? |
| return model.getIndividual(base.toString()); |
| } |
| |
| } |