package org.linkeddatafragments.model; import com.github.fge.uritemplate.URITemplate; import com.github.fge.uritemplate.URITemplateException; import com.github.fge.uritemplate.vars.VariableMap; import com.github.fge.uritemplate.vars.VariableMapBuilder; import com.google.common.base.Strings; import org.apache.commons.lang3.StringUtils; import org.apache.jena.graph.*; import org.apache.jena.rdf.model.*; import org.apache.jena.sparql.graph.GraphFactory; import org.apache.jena.util.iterator.ExtendedIterator; import java.net.MalformedURLException; import java.net.URLEncoder; import java.util.Iterator; import java.util.function.Predicate; public class LinkedDataFragment { public static final Resource RDF_PREDICATE = ResourceFactory.createResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"); protected ExtendedIterator<Triple> triples; protected final Model tripleModel; protected Long matchCount; protected String url; protected String nextUrl; protected RDFNode fragmentNode; protected RDFNode pattern; protected String subjectVariable; protected String predicateVariable; protected String objectVariable; protected String template; protected URITemplate uriTemplate; protected final Triple tripleMatch; public LinkedDataFragment(Triple m) { this.tripleMatch = m; Graph g = GraphFactory.createJenaDefaultGraph(); g.add(m); this.tripleModel = ModelFactory.createModelForGraph(g); this.matchCount = 1L; this.triples = GraphUtil.findAll(g); //hydraParse(g); } public LinkedDataFragment(Triple m, Long matchCount) { this.tripleMatch = m; Graph g = GraphFactory.createJenaDefaultGraph(); if(matchCount > 0) { g.add(m); } this.tripleModel = ModelFactory.createModelForGraph(g); this.matchCount = matchCount; this.triples = GraphUtil.findAll(g); //hydraParse(g); } public LinkedDataFragment(ExtendedIterator<Triple> triples, Triple m) { this.tripleMatch = m; Long matchCount = 0L; ExtendedIterator<Triple> iteratorTriples = triples; Graph g = GraphFactory.createJenaDefaultGraph(); while (iteratorTriples.hasNext()) { matchCount += 1; g.add(iteratorTriples.next()); } this.tripleModel = ModelFactory.createModelForGraph(g); this.matchCount = matchCount; hydraParse(g); } public LinkedDataFragment(Iterator<Triple> triples, Long matchCount, Triple m) { this.tripleMatch = m; Graph g = GraphFactory.createJenaDefaultGraph(); GraphUtil.add(g, triples); this.tripleModel = ModelFactory.createModelForGraph(g); this.matchCount = matchCount; hydraParse(g); } protected void hydraParse(Graph g) { setUrl(); setNextUrl(); setFragmentUrl(); setPattern(); setTemplate(); setMatchCount(); this.triples = GraphUtil.findAll(g) .filterKeep(triple -> tripleMatch.matches(triple)) .filterDrop(triple -> new Triple(NodeFactory.createURI(url), Node.ANY, Node.ANY).matches(triple)) .filterDrop(triple -> new Triple(pattern.asNode(), Node.ANY, Node.ANY).matches(triple)) .filterDrop(triple -> LinkedDataFragmentsConstants.HYDRA_VARIABLE.matches(triple)) .filterDrop(triple -> LinkedDataFragmentsConstants.HYDRA_PROPERTY.matches(triple)); if(fragmentNode != null) { this.triples = this.triples.filterDrop( triple -> new Triple(fragmentNode.asNode(), Node.ANY, Node.ANY).matches(triple)); } } public ExtendedIterator<Triple> getTriples() { return this.triples; } public Long getMatchCount() { return this.matchCount; } public String getUrl() { return url; } public Triple getTripleMatch() { return this.tripleMatch; } protected void setUrl() { if(Strings.isNullOrEmpty(url)) { ResIterator it = this.tripleModel.listSubjectsWithProperty(LinkedDataFragmentsConstants.RDF_TYPE_RESOURCE, LinkedDataFragmentsConstants.VOID_DATASET_RESOURCE); while (it.hasNext()) { url = it.next().getURI(); //url = fullUrl.substring(0, fullUrl.indexOf('#')); } } } protected void setNextUrl() { if(Strings.isNullOrEmpty(nextUrl)) { NodeIterator it = this.tripleModel.listObjectsOfProperty(LinkedDataFragmentsConstants.HYDRA_NEXTPAGE); while (it.hasNext()) { nextUrl = it.next().asResource().getURI(); } } } protected void setTemplate() { NodeIterator it = this.tripleModel.listObjectsOfProperty(LinkedDataFragmentsConstants.HYDRA_TEMPLATE); while (it.hasNext()) { template = it.next().toString(); } // Throws URITemplateParseException if the template is invalid try{ uriTemplate = new URITemplate(template); } catch (URITemplateException e) { e.printStackTrace(); } } protected void setMatchCount() { NodeIterator it = this.tripleModel.listObjectsOfProperty(LinkedDataFragmentsConstants.HYDRA_TOTALITEMS); while (it.hasNext()) { Literal matchCountLiteral = it.next().asLiteral(); if(StringUtils.isNumeric(matchCountLiteral.getString())) { matchCount = matchCountLiteral.getLong(); } } } protected void setFragmentUrl() { if(fragmentNode == null) { ResIterator it = this.tripleModel.listSubjectsWithProperty(LinkedDataFragmentsConstants.RDF_TYPE_RESOURCE, LinkedDataFragmentsConstants.HYDRA_PAGEDCOLLECTION); while (it.hasNext()) { fragmentNode = it.next(); } } } public Long getTriplesSize() { NodeIterator it = this.tripleModel.listObjectsOfProperty(LinkedDataFragmentsConstants.VOID_TRIPLES); Long triplesNumber = 0L; while(it.hasNext()) { RDFNode number = it.next(); triplesNumber = number.asLiteral().getLong(); } return triplesNumber; } public String getUrlToFragment(Triple m) { NodeIterator it = getNodePatternIterator(); while(it.hasNext()) { RDFNode mapping = it.next(); NodeIterator var = this.tripleModel.listObjectsOfProperty(mapping.asResource(), ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#property")); while(var.hasNext()) { Resource typeOfMapping = var.next().asResource(); if(Strings.isNullOrEmpty(subjectVariable)) { if(typeOfMapping.equals(LinkedDataFragmentsConstants.RDF_SUBJECT)) { NodeIterator label = this.tripleModel.listObjectsOfProperty(mapping.asResource(), ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#variable")); while(label.hasNext()) { String labelString = label.next().asLiteral().getString(); subjectVariable = labelString; } } } if(Strings.isNullOrEmpty(predicateVariable)) { if(typeOfMapping.equals(RDF_PREDICATE)) { NodeIterator label = this.tripleModel.listObjectsOfProperty(mapping.asResource(), ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#variable")); while(label.hasNext()) { String labelString = label.next().asLiteral().getString(); predicateVariable = labelString; } } } if(Strings.isNullOrEmpty(objectVariable)) { if(typeOfMapping.equals(LinkedDataFragmentsConstants.RDF_OBJECT)) { NodeIterator label = this.tripleModel.listObjectsOfProperty(mapping.asResource(), ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#variable")); while(label.hasNext()) { String labelString = label.next().asLiteral().getString(); objectVariable = labelString; } } } } } // Create a variable map, consisting of name/value pairs final VariableMapBuilder builder = VariableMap.newBuilder(); if(m.getMatchSubject() != null && m.getMatchSubject().isConcrete()) { if(m.getMatchSubject().isURI()) { builder.addScalarValue(subjectVariable, m.getMatchSubject().getURI()); } else { builder.addScalarValue(subjectVariable, String.format("\"%s\"@%s", m.getMatchSubject().getLiteralLexicalForm(), m.getMatchSubject().getLiteralLanguage())); } } if(m.getMatchPredicate() != null && m.getMatchPredicate().isConcrete()) { builder.addScalarValue(predicateVariable, m.getMatchPredicate().getURI()); } if(m.getMatchObject() != null && m.getMatchObject().isConcrete()) { if(m.getMatchObject().isURI()) { builder.addScalarValue(objectVariable, m.getMatchObject().getURI()); } else { builder.addScalarValue(objectVariable, String.format("\"%s\"@%s",m.getMatchObject().getLiteralLexicalForm(),m.getMatchObject().getLiteralLanguage())); //builder.addScalarValue(objectVariable, String.format("%s",m.getMatchObject().getLiteral())); } } // Create the variable map final VariableMap vars = builder.freeze(); try { return uriTemplate.toURL(vars).toString(); } catch (Exception e) { e.printStackTrace(); return null; } } protected NodeIterator getNodePatternIterator() { setPattern(); NodeIterator it; if(!(pattern == null)) { it = this.tripleModel.listObjectsOfProperty(pattern.asResource(), ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#mapping")); } else { it = this.tripleModel.listObjectsOfProperty(ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#mapping")); } return it; } protected void setPattern() { NodeIterator it = this.tripleModel.listObjectsOfProperty(ResourceFactory.createResource(url), ResourceFactory.createProperty("http://www.w3.org/ns/hydra/core#search")); while(it.hasNext()) { pattern = it.next(); } } public Graph getGraph() { Graph g = GraphFactory.createJenaDefaultGraph(); GraphUtil.add(g, triples); return g; } public String getNextUrl() { return nextUrl; } public Boolean hasNextUrl() { return !Strings.isNullOrEmpty(nextUrl); } }