001package org.dllearner.reasoning;
002
003import org.apache.jena.query.ResultSet;
004import org.dllearner.core.ComponentAnn;
005import org.dllearner.kb.SparqlEndpointKS;
006import org.jetbrains.annotations.NotNull;
007import org.semanticweb.owlapi.model.OWLClassExpression;
008import org.semanticweb.owlapi.model.OWLIndividual;
009import org.semanticweb.owlapi.model.OWLObjectProperty;
010
011import java.util.Collection;
012import java.util.SortedSet;
013import java.util.TreeSet;
014import java.util.concurrent.TimeUnit;
015import java.util.regex.Matcher;
016import java.util.stream.Collectors;
017
018/**
019 * Specialised SPARQL Reasoner for specific SPARQL dialects
020 */
021@ComponentAnn(name = "SPARQL Reasoner (Quad)", shortName = "spr.quad", version = 0.1)
022public class SPARQLReasonerQuad extends SPARQLReasoner {
023        protected String buildSubsumptionHierarchyQuery() {
024                return "SELECT * WHERE {"
025                                + " ?sub a <http://www.w3.org/2002/07/owl#Class> . "
026                                + " OPTIONAL { "
027                                // for ontoquad
028                                + "{ ?sub <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?sup . FILTER(?sub != ?sup) . } "
029                                + " UNION { ?sub <http://www.w3.org/2002/07/owl#equivalentClass> ?sup . FILTER(?sub != ?sup) . } "
030                                + " . "
031                                + " } "
032                                + "}";
033        }
034
035        @Override
036        protected String buildIndividualsQueryValues(OWLClassExpression description, Collection<OWLIndividual> indValues, boolean isCountQuery) {
037                String query;
038                String tp = converter.convert("?ind", description);
039
040                // for ontoquad
041
042                if (isCountQuery) {
043                        query = "SELECT (COUNT(?ind) as ?cnt) WHERE { \n"
044                        + "SELECT DISTINCT ?ind WHERE { \n";
045                } else {
046                        query = "SELECT DISTINCT ?ind WHERE { \n";
047                }
048
049                query += tp + "\n}";
050                if (isCountQuery)
051                        query += "\n}";
052                query += "\n " + "VALUES (?ind) { \n";
053
054                for (OWLIndividual x:indValues) {
055                        query += "(<" + x.toStringID() + ">) ";
056                }
057
058                query += "\n}";
059
060                return query;
061        }
062
063        @NotNull
064        @Override
065        protected String buildMeaningfulClassesQuery(OWLClassExpression index, SortedSet<OWLClassExpression> targetClasses) {
066                String query = "SELECT DISTINCT ?concept WHERE {";
067                query += converter.convert("?ind", index);
068                query += "?ind a ?concept . ";
069                query += "}";
070                query += "VALUES ?concept {"
071                                + targetClasses.stream().map(ce -> "<" + ce.asOWLClass().toStringID() + ">").collect(Collectors.joining(" "))
072                                + "}";
073                return query;
074        }
075
076        @Override
077        public SortedSet<OWLClassExpression> getMeaningfulClasses(OWLClassExpression index, SortedSet<OWLClassExpression> targetClasses) {
078                if (targetClasses.isEmpty())
079                        return new TreeSet<>();
080                return super.getMeaningfulClasses(index, targetClasses);
081        }
082
083        @Override
084        protected String buildApplicablePropertiesValuesQuery(OWLClassExpression domain, Collection<? extends OWLObjectProperty> objectProperties) {
085                String domQuery = converter.convert("?dom", domain);
086                String props = objectProperties.stream().map(op -> "<" + op.toStringID() + ">").collect(Collectors.joining(" "));
087//              String prop1 = converter.convert("?p", objectProperties.iterator().next());
088
089                String query = "SELECT DISTINCT ?p WHERE { " +
090                                "" + domQuery + " ?dom ?p ?o . \n" +
091                                "" + " }" +
092                                "" + " VALUES ?p { \n" + props + " }";
093                return query;
094        }
095
096
097
098        private String getFromStatement() {
099                return getSources().stream()
100                                .filter(SparqlEndpointKS.class::isInstance)
101                                .map(SparqlEndpointKS.class::cast)
102                                .filter(SparqlEndpointKS::isRemote)
103                                .map(ks -> ks.getDefaultGraphURIs().stream().map(uri -> "FROM <" + uri + ">").collect(Collectors.joining(" "))
104                                                + ks.getNamedGraphURIs().stream().map(uri -> "FROM NAMED <" + uri + ">").collect(Collectors.joining(" ")))
105                                .collect(Collectors.joining(" "));
106        }
107
108        @Override
109        protected ResultSet executeSelectQuery(String queryString, long timeout, TimeUnit timeoutUnits) {
110                String q2 = queryString.replaceFirst(
111                                "(^|\\s+)SELECT(\\s+.*?\\s+)WHERE(\\s+)",
112                                "$1" + "SELECT" + "$2" + " " + Matcher.quoteReplacement(getFromStatement()) + " "
113                                + "WHERE" + "$3"
114                );
115                return super.executeSelectQuery(q2, timeout, timeoutUnits);
116        }
117
118        @Override
119        protected boolean executeAskQuery(String queryString) {
120                String q2 = queryString.replaceFirst(
121                                "(^|\\s+)ASK(\\s+)",
122                                "$1" + "ASK " + Matcher.quoteReplacement(getFromStatement()) + " $2"
123                );
124                return super.executeAskQuery(q2);
125        }
126}