package at.ac.univie.mminf.qskos4j.issues.skosintegrity; import at.ac.univie.mminf.qskos4j.issues.HierarchyGraphBuilder; import at.ac.univie.mminf.qskos4j.issues.Issue; import at.ac.univie.mminf.qskos4j.progress.MonitoredIterator; import at.ac.univie.mminf.qskos4j.result.CollectionResult; import at.ac.univie.mminf.qskos4j.util.Tuple; import at.ac.univie.mminf.qskos4j.util.TupleQueryResultUtil; import at.ac.univie.mminf.qskos4j.util.graph.NamedEdge; import at.ac.univie.mminf.qskos4j.util.vocab.SparqlPrefix; import org.jgrapht.Graph; import org.jgrapht.alg.DijkstraShortestPath; import org.openrdf.OpenRDFException; import org.openrdf.model.Resource; import org.openrdf.model.impl.URIImpl; import org.openrdf.query.QueryLanguage; import org.openrdf.query.TupleQueryResult; import org.openrdf.repository.RepositoryConnection; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; /** * Finds <a href="https://github.com/cmader/qSKOS/wiki/Quality-Issues#wiki-Relation_Clashes">Associative vs. Hierarchical Relation Clashes</a>. */ public class RelationClashes extends Issue<CollectionResult<Tuple<Resource>>> { private HierarchyGraphBuilder hierarchyGraphBuilder; public RelationClashes(HierarchyGraphBuilder hierarchyGraphBuilder) { super("rc", "Relation Clashes", "Covers condition S27 from the SKOS reference document (Associative vs. Hierarchical Relation Clashes)", IssueType.ANALYTICAL, new URIImpl("https://github.com/cmader/qSKOS/wiki/Quality-Issues#relation-clashes") ); this.hierarchyGraphBuilder = hierarchyGraphBuilder; } @Override protected CollectionResult<Tuple<Resource>> invoke() throws OpenRDFException { Graph<Resource, NamedEdge> hierarchyGraph = hierarchyGraphBuilder.createGraph(); Collection<Tuple<Resource>> clashes = new HashSet<Tuple<Resource>>(); Iterator<Tuple<Resource>> it = new MonitoredIterator<Tuple<Resource>>( findRelatedConcepts(), progressMonitor); while (it.hasNext()) { Tuple<Resource> conceptPair = it.next(); try { if (pathExists(hierarchyGraph, conceptPair)) { clashes.add(conceptPair); } } catch (IllegalArgumentException e) { // one of the concepts not in graph, no clash possible } } return new CollectionResult<Tuple<Resource>>(clashes); } private Collection<Tuple<Resource>> findRelatedConcepts() throws OpenRDFException { TupleQueryResult result = repCon.prepareTupleQuery(QueryLanguage.SPARQL, createRelatedConceptsQuery()).evaluate(); return TupleQueryResultUtil.createCollectionOfResourcePairs(result, "concept1", "concept2"); } private String createRelatedConceptsQuery() { return SparqlPrefix.SKOS + "SELECT DISTINCT ?concept1 ?concept2 WHERE {" + "?concept1 skos:related|skos:relatedMatch ?concept2 ." + "}"; } private boolean pathExists(Graph<Resource, NamedEdge> hierarchyGraph, Tuple<Resource> conceptPair) { if (new DijkstraShortestPath<Resource, NamedEdge>( hierarchyGraph, conceptPair.getFirst(), conceptPair.getSecond()).getPathEdgeList() == null) { return new DijkstraShortestPath<Resource, NamedEdge>( hierarchyGraph, conceptPair.getSecond(), conceptPair.getFirst()).getPathEdgeList() != null; } return true; } @Override public void setRepositoryConnection(RepositoryConnection repCon) { hierarchyGraphBuilder.setRepositoryConnection(repCon); super.setRepositoryConnection(repCon); } }