package at.ac.univie.mminf.qskos4j.issues.skosintegrity;
import at.ac.univie.mminf.qskos4j.issues.Issue;
import at.ac.univie.mminf.qskos4j.result.CollectionResult;
import at.ac.univie.mminf.qskos4j.util.TupleQueryResultUtil;
import at.ac.univie.mminf.qskos4j.util.vocab.SkosOntology;
import at.ac.univie.mminf.qskos4j.util.vocab.SparqlPrefix;
import org.openrdf.OpenRDFException;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.query.*;
import org.openrdf.repository.RepositoryConnection;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* Finds resources not defined in the SKOS ontology (
* <a href="https://github.com/cmader/qSKOS/wiki/Quality-Issues#wiki-Undefined_SKOS_Resources">Undefined SKOS Resources</a>
* ).
*/
public class UndefinedSkosResources extends Issue<CollectionResult<URI>> {
private Map<URI, Collection<URI>> deprecatedProperties, illegalTerms;
public UndefinedSkosResources() {
super("usr",
"Undefined SKOS Resources",
"Finds 'invented' new terms within the SKOS namespace or deprecated properties",
IssueType.ANALYTICAL,
new URIImpl("https://github.com/cmader/qSKOS/wiki/Quality-Issues#undefined-skos-resources")
);
}
@Override
protected CollectionResult<URI> invoke() throws OpenRDFException {
findDeprecatedProperties();
findIllegalTerms();
return new CollectionResult<>(collectUndefinedResources());
}
private void findDeprecatedProperties() throws OpenRDFException
{
TupleQuery query = repCon.prepareTupleQuery(QueryLanguage.SPARQL, createDeprecatedPropertiesQuery());
generateDeprecatedPropertiesMap(query.evaluate());
}
private String createDeprecatedPropertiesQuery() {
return SparqlPrefix.SKOS +
"SELECT DISTINCT ?iri ?deprProp "+
"WHERE {{?iri ?deprProp ?o .} UNION "+
"{?q ?deprProp ?iri .} "+
"FILTER isIRI(?iri) "+
"FILTER (?deprProp IN (" +
"skos:symbol,"+
"skos:prefSymbol,"+
"skos:altSymbol,"+
"skos:CollectableProperty,"+
"skos:subject,"+
"skos:isSubjectOf,"+
"skos:primarySubject,"+
"skos:isPrimarySubjectOf,"+
"skos:subjectIndicator))}";
}
private void generateDeprecatedPropertiesMap(TupleQueryResult result)
throws QueryEvaluationException
{
deprecatedProperties = new HashMap<>();
while (result.hasNext()) {
BindingSet queryResult = result.next();
URI resource = (URI) queryResult.getValue("iri");
URI deprProperty = (URI) queryResult.getValue("deprProp");
Collection<URI> resources = deprecatedProperties.get(deprProperty);
if (resources == null) {
resources = new HashSet<>();
deprecatedProperties.put(deprProperty, resources);
}
resources.add(resource);
}
}
private void findIllegalTerms() throws OpenRDFException
{
TupleQuery query = repCon.prepareTupleQuery(QueryLanguage.SPARQL, createIllegalTermsQuery());
generateIllegalTermsMap(query.evaluate());
}
private String createIllegalTermsQuery() throws OpenRDFException {
return SparqlPrefix.SKOS+
"SELECT DISTINCT ?illTerm ?s ?o "+
"WHERE {" +
"{?illTerm ?p ?o . } UNION "+
"{?s ?illTerm ?o . } UNION "+
"{?s ?p ?illTerm . } "+
"FILTER isIRI(?illTerm) "+
"FILTER STRSTARTS(str(?illTerm), \"" +SparqlPrefix.SKOS.getNameSpace()+ "\") "+
createSkosSubjectsFilter()+
"} ";
}
private String createSkosSubjectsFilter() throws OpenRDFException {
RepositoryConnection skosRepoConn = SkosOntology.getInstance().getRepository().getConnection();
try {
TupleQuery skosSubjectsQuery = skosRepoConn.prepareTupleQuery(QueryLanguage.SPARQL, createSkosSubjectsQuery());
return TupleQueryResultUtil.getFilterForBindingName(skosSubjectsQuery.evaluate(), "illTerm", true);
}
finally {
skosRepoConn.close();
}
}
private String createSkosSubjectsQuery() {
return "SELECT ?illTerm WHERE {" +
"?illTerm ?p ?o . " +
"FILTER isIRI(?illTerm)"+
"}";
}
private void generateIllegalTermsMap(TupleQueryResult result)
throws QueryEvaluationException
{
illegalTerms = new HashMap<>();
while (result.hasNext()) {
BindingSet queryResult = result.next();
URI illegalTerm = (URI) queryResult.getValue("illTerm");
URI subject = (URI) queryResult.getValue("s");
Value object = queryResult.getValue("o");
if (!illegalTerm.getLocalName().isEmpty()) {
addTermToMap(illegalTerm, subject, object);
}
}
}
private void addTermToMap(URI term, URI subject, Value object) {
Collection<URI> resources = illegalTerms.get(term);
if (resources == null) {
resources = new HashSet<>();
illegalTerms.put(term, resources);
}
if (subject != null) {
resources.add(subject);
}
else if (object != null && object instanceof URI) {
resources.add((URI) object);
}
}
private Collection<URI> collectUndefinedResources() {
Collection<URI> undefRes = new HashSet<>();
undefRes.addAll(deprecatedProperties.keySet());
undefRes.addAll(illegalTerms.keySet());
return undefRes;
}
}