001/** 002 * Copyright (C) 2007 - 2016, Jens Lehmann 003 * 004 * This file is part of DL-Learner. 005 * 006 * DL-Learner is free software; you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation; either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * DL-Learner is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.dllearner.reasoning; 020 021import com.clarkparsia.owlapiv3.XSD; 022import com.google.common.base.Joiner; 023import com.google.common.collect.HashMultimap; 024import com.google.common.collect.Multimap; 025import com.google.common.collect.Sets; 026import org.aksw.jena_sparql_api.core.QueryExecutionFactory; 027import org.aksw.jena_sparql_api.delay.core.QueryExecutionFactoryDelay; 028import org.aksw.jena_sparql_api.http.QueryExecutionFactoryHttp; 029import org.aksw.jena_sparql_api.model.QueryExecutionFactoryModel; 030import org.aksw.jena_sparql_api.pagination.core.QueryExecutionFactoryPaginated; 031import org.apache.commons.lang3.NotImplementedException; 032import org.apache.jena.query.*; 033import org.apache.jena.rdf.model.*; 034import org.apache.jena.riot.RDFDataMgr; 035import org.apache.jena.sparql.engine.http.QueryExceptionHTTP; 036import org.apache.jena.vocabulary.OWL; 037import org.apache.jena.vocabulary.OWL2; 038import org.apache.jena.vocabulary.RDF; 039import org.apache.jena.vocabulary.RDFS; 040import org.dllearner.core.*; 041import org.dllearner.core.annotations.NoConfigOption; 042import org.dllearner.core.config.ConfigOption; 043import org.dllearner.core.owl.ClassHierarchy; 044import org.dllearner.core.owl.DatatypePropertyHierarchy; 045import org.dllearner.core.owl.LazyClassHierarchy; 046import org.dllearner.core.owl.ObjectPropertyHierarchy; 047import org.dllearner.kb.LocalModelBasedSparqlEndpointKS; 048import org.dllearner.kb.OWLFile; 049import org.dllearner.kb.SparqlEndpointKS; 050import org.dllearner.kb.sparql.SPARQLQueryUtils; 051import org.dllearner.kb.sparql.SparqlEndpoint; 052import org.dllearner.utilities.OWLAPIUtils; 053import org.dllearner.utilities.OwlApiJenaUtils; 054import org.dllearner.utilities.datastructures.SortedSetTuple; 055import org.dllearner.utilities.owl.OWLClassExpressionToSPARQLConverter; 056import org.jetbrains.annotations.NotNull; 057import org.semanticweb.owlapi.model.*; 058import org.semanticweb.owlapi.util.OWLObjectDuplicator; 059import org.semanticweb.owlapi.vocab.OWL2Datatype; 060import org.semanticweb.owlapi.vocab.XSDVocabulary; 061import org.slf4j.Logger; 062import org.slf4j.LoggerFactory; 063import org.slf4j.Marker; 064import org.slf4j.helpers.BasicMarkerFactory; 065import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 066 067import java.util.*; 068import java.util.Map.Entry; 069import java.util.concurrent.TimeUnit; 070import java.util.stream.Collectors; 071import java.util.stream.StreamSupport; 072 073/** 074 * A reasoner implementation that provides inference services by the execution 075 * of SPARQL queries on 076 * <ul> 077 * <li> local files (usually in forms of JENA API models)</li> 078 * <li> remote SPARQL endpoints </li> 079 * </ul> 080 * <p> 081 * Compared to other reasoner implementations, it doesn't do any pre-computation 082 * by default because it might be too expensive on very large knowledge bases. 083 * </p> 084 * @author Lorenz Buehmann 085 * 086 */ 087@ComponentAnn(name = "SPARQL Reasoner", shortName = "spr", version = 0.1) 088public class SPARQLReasoner extends AbstractReasonerComponent implements SchemaReasoner, IndividualReasoner { 089 090 private static final Logger logger = LoggerFactory.getLogger(SPARQLReasoner.class); 091 private final static Marker sparql_debug = new BasicMarkerFactory().getMarker("SD"); 092 093 public enum PopularityType { 094 CLASS, OBJECT_PROPERTY, DATA_PROPERTY 095 } 096 097 private static final ParameterizedSparqlString CLASS_POPULARITY_QUERY = new ParameterizedSparqlString( 098 "SELECT (COUNT(*) AS ?cnt) WHERE {?s a ?entity .}"); 099 100 private static final ParameterizedSparqlString PROPERTY_POPULARITY_QUERY = new ParameterizedSparqlString( 101 "SELECT (COUNT(*) AS ?cnt) WHERE {?s ?entity ?o .}"); 102 103 private static final ParameterizedSparqlString INDIVIDUAL_POPULARITY_QUERY = new ParameterizedSparqlString( 104 "SELECT (COUNT(*) AS ?cnt) WHERE {?entity ?p ?o .}"); 105 106 @ConfigOption(description = "Use alternative relaxed Sparql-queries for Classes and Individuals", defaultValue = "false") 107 private boolean laxMode = false; 108 109 @ConfigOption(description = "Whether to use the generic facet generation code, which requires downloading all instances and is thus not recommended", defaultValue = "false") 110 private boolean useGenericSplitsCode = false; 111 112 @ConfigOption(description = "Whether to use SPARQL1.1 Value Lists", defaultValue = "false") 113 private boolean useValueLists = false; 114 115 @ConfigOption(defaultValue = "true", description = "Prefer ASK queries when there is a choice in implementation", required = false) 116 private boolean preferAsk = true; 117 118 private QueryExecutionFactory qef; 119 120 private SparqlEndpointKS ks; 121 private ClassHierarchy hierarchy; 122 123 private Map<OWLEntity, Integer> entityPopularityMap = new HashMap<>(); 124 private Map<OWLClass, Integer> classPopularityMap = new HashMap<>(); 125 private boolean batchedMode = true; 126 private Set<PopularityType> precomputedPopularityTypes = new HashSet<>(); 127 128 private boolean prepared = false; 129 130 protected OWLClassExpressionToSPARQLConverter converter = new OWLClassExpressionToSPARQLConverter(); 131 132 private OWLDataFactory df = new OWLDataFactoryImpl(); 133 private OWLObjectDuplicator duplicator = new OWLObjectDuplicator(df); 134 135 /** 136 * Default constructor for usage of config files + Spring API. 137 */ 138 public SPARQLReasoner() { 139 setPrecomputeClassHierarchy(false); 140 setPrecomputeObjectPropertyHierarchy(false); 141 setPrecomputeDataPropertyHierarchy(false); 142 } 143 144 public SPARQLReasoner(SparqlEndpointKS ks) { 145 super(ks); 146 this.qef = ks.getQueryExecutionFactory(); 147 } 148 149 public SPARQLReasoner(SparqlEndpoint endpoint) { 150 this(new QueryExecutionFactoryHttp(endpoint.getURL().toString(), endpoint.getDefaultGraphURIs())); 151 } 152 153 public SPARQLReasoner(Model model) { 154 this(new QueryExecutionFactoryModel(model)); 155 } 156 157 public SPARQLReasoner(QueryExecutionFactory qef) { 158 this(); 159 this.qef = qef; 160 } 161 162 /* (non-Javadoc) 163 * @see org.dllearner.core.Component#init() 164 */ 165 @Override 166 public void init() throws ComponentInitException { 167 classPopularityMap = new HashMap<>(); 168 169 // this is only done if the reasoner is setup via config file 170 if(qef == null) { 171 if(ks == null) { 172 KnowledgeSource abstract_ks = sources.iterator().next(); 173 if (SparqlEndpointKS.class.isAssignableFrom(abstract_ks.getClass())) { 174 ks = (SparqlEndpointKS) abstract_ks; 175 } else { 176 OWLFile owl_file = (OWLFile) abstract_ks; 177 Model model = RDFDataMgr.loadModel(owl_file.getURL().getFile()); 178 logger.debug(sparql_debug, "file reasoning: " + ((owl_file.getReasoning() == null || owl_file.getReasoning().getReasonerFactory() == null) ? "(none)" 179 : owl_file.getReasoning().getReasonerFactory().getURI())); 180 ks = new LocalModelBasedSparqlEndpointKS(model, owl_file.getReasoning()); 181 } 182 if (sources.size() > 1) { 183 throw new ComponentInitException("SPARQLReasoner only supports a single knowledge source"); 184 } 185 } 186 if(ks.isRemote()){ 187 qef = ks.getQueryExecutionFactory(); 188 qef = new QueryExecutionFactoryDelay(qef, 50); 189// qef = new QueryExecutionFactoryCacheEx(qef, cache); 190 qef = new QueryExecutionFactoryPaginated(qef, 10000); 191 } else { 192 qef = new QueryExecutionFactoryModel(((LocalModelBasedSparqlEndpointKS)ks).getModel()); 193 } 194 } 195 196 initialized = true; 197 } 198 199 public QueryExecutionFactory getQueryExecutionFactory() { 200 return qef; 201 } 202 203 public void precomputePopularities(PopularityType... popularityTypes){ 204 for (PopularityType popularityType : popularityTypes) { 205 switch (popularityType) { 206 case CLASS:precomputeClassPopularity();break; 207 case OBJECT_PROPERTY:precomputeObjectPropertyPopularity();break; 208 case DATA_PROPERTY:precomputeDataPropertyPopularity();break; 209 default: 210 break; 211 } 212 } 213 } 214 215 public void precomputePropertyDomains() { 216 logger.info("precomputing property domains..."); 217 String query = SPARQLQueryUtils.PREFIXES + 218 " SELECT * WHERE {?p rdfs:domain ?dom {?p a owl:ObjectProperty} UNION {?p a owl:DatatypeProperty}}"; 219 220 try { 221 ResultSet rs = executeSelectQuery(query); 222 223 while(rs.hasNext()) { 224 QuerySolution qs = rs.next(); 225 OWLObjectProperty p = df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI())); 226 OWLClass dom = df.getOWLClass(IRI.create(qs.getResource("dom").getURI())); 227 228 propertyDomains.put(p, dom); 229 } 230 } catch (Exception e) { 231 logger.error("Failed to compute property domains.", e); 232 } 233 logger.info("finished precomputing property domains."); 234 } 235 236 public void precomputeObjectPropertyRanges() { 237 logger.info("precomputing object property ranges..."); 238 String query = SPARQLQueryUtils.PREFIXES + 239 " SELECT * WHERE {?p rdfs:range ?ran; a owl:ObjectProperty }"; 240 241 try { 242 ResultSet rs = executeSelectQuery(query); 243 244 while(rs.hasNext()) { 245 QuerySolution qs = rs.next(); 246 OWLObjectProperty p = df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI())); 247 OWLClass dom = df.getOWLClass(IRI.create(qs.getResource("ran").getURI())); 248 249 objectPropertyRanges.put(p, dom); 250 } 251 } catch (Exception e) { 252 logger.error("Failed to compute property domains.", e); 253 } 254 logger.info("finished precomputing property domains."); 255 } 256 257 public void precomputePopularity(){ 258 precomputeClassPopularity(); 259 precomputeDataPropertyPopularity(); 260 precomputeObjectPropertyPopularity(); 261 } 262 263 public boolean isPrecomputed(PopularityType popularityType){ 264 return precomputedPopularityTypes.contains(popularityType); 265 } 266 267 public void precomputeClassPopularity() { 268 if(isPrecomputed(PopularityType.CLASS)){ 269 return; 270 } 271 logger.info("Precomputing class popularity ..."); 272 273 long start = System.currentTimeMillis(); 274 275 if (batchedMode) { 276 String query = "PREFIX owl:<http://www.w3.org/2002/07/owl#> SELECT ?type (COUNT(?s) AS ?cnt) WHERE {?s a ?type . ?type a owl:Class .} GROUP BY ?type"; 277 ResultSet rs = executeSelectQuery(query); 278 while (rs.hasNext()) { 279 QuerySolution qs = rs.next(); 280 if (qs.get("type").isURIResource()) { 281 OWLClass cls = df.getOWLClass(IRI.create(qs.getResource("type").getURI())); 282 int cnt = qs.getLiteral("cnt").getInt(); 283 classPopularityMap.put(cls, cnt); 284 } 285 } 286 } else { 287 Set<OWLClass> classes = getOWLClasses(); 288 String queryTemplate = "SELECT (COUNT(?s) AS ?cnt) WHERE {?s a <%s>}"; 289 for (OWLClass cls : classes) { 290 ResultSet rs = executeSelectQuery(String.format(queryTemplate, cls.toStringID())); 291 int cnt = rs.next().getLiteral("cnt").getInt(); 292 classPopularityMap.put(cls, cnt); 293 } 294 } 295 precomputedPopularityTypes.add(PopularityType.CLASS); 296 297 long end = System.currentTimeMillis(); 298 299 logger.info("... done in " + (end - start) + "ms."); 300 } 301 302 public void precomputeObjectPropertyPopularity(){ 303 if(isPrecomputed(PopularityType.OBJECT_PROPERTY)){ 304 return; 305 } 306 logger.info("Precomputing object property popularity ..."); 307 308 long start = System.currentTimeMillis(); 309 310 if (batchedMode) { 311 String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?p (COUNT(*) AS ?cnt) WHERE {?s ?p ?o . ?p a owl:ObjectProperty .} GROUP BY ?p"; 312 ResultSet rs = executeSelectQuery(query); 313 while (rs.hasNext()) { 314 QuerySolution qs = rs.next(); 315 if (qs.get("p").isURIResource()) { 316 OWLObjectProperty property = df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI())); 317 int cnt = qs.getLiteral("cnt").getInt(); 318 entityPopularityMap.put(property, cnt); 319 } 320 } 321 } else { 322 Set<OWLObjectProperty> properties = getOWLObjectProperties(); 323 String queryTemplate = "SELECT (COUNT(*) AS ?cnt) WHERE {?s <%s> ?o}"; 324 for (OWLObjectProperty property : properties) { 325 ResultSet rs = executeSelectQuery(String.format(queryTemplate, property.toStringID())); 326 int cnt = rs.next().getLiteral("cnt").getInt(); 327 entityPopularityMap.put(property, cnt); 328 } 329 } 330 precomputedPopularityTypes.add(PopularityType.OBJECT_PROPERTY); 331 332 long end = System.currentTimeMillis(); 333 334 logger.info("... done in " + (end - start) + "ms."); 335 } 336 337 public void precomputeDataPropertyPopularity(){ 338 if(isPrecomputed(PopularityType.DATA_PROPERTY)){ 339 return; 340 } 341 logger.info("Precomputing data property popularity ..."); 342 343 long start = System.currentTimeMillis(); 344 345 if (batchedMode) { 346 String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?p (COUNT(*) AS ?cnt) WHERE {?s ?p ?o . ?p a owl:DatatypeProperty .} GROUP BY ?p"; 347 ResultSet rs = executeSelectQuery(query); 348 while (rs.hasNext()) { 349 QuerySolution qs = rs.next(); 350 if (qs.get("p").isURIResource()) { 351 OWLDataProperty property = df.getOWLDataProperty(IRI.create(qs.getResource("p").getURI())); 352 int cnt = qs.getLiteral("cnt").getInt(); 353 entityPopularityMap.put(property, cnt); 354 } 355 } 356 } else { 357 Set<OWLDataProperty> properties = getOWLDataProperties(); 358 String queryTemplate = "SELECT (COUNT(*) AS ?cnt) WHERE {?s <%s> ?o}"; 359 for (OWLDataProperty property : properties) { 360 ResultSet rs = executeSelectQuery(String.format(queryTemplate, property.toStringID())); 361 int cnt = rs.next().getLiteral("cnt").getInt(); 362 entityPopularityMap.put(property, cnt); 363 } 364 } 365 precomputedPopularityTypes.add(PopularityType.DATA_PROPERTY); 366 367 long end = System.currentTimeMillis(); 368 369 logger.info("... done in " + (end - start) + "ms."); 370 } 371 372 public int getSubjectCountForProperty(OWLProperty p, long timeout, TimeUnit timeoutUnits){ 373 int cnt = -1; 374 String query = String.format( 375 "SELECT (COUNT(DISTINCT ?s) AS ?cnt) WHERE {?s <%s> ?o.}", 376 p.toStringID()); 377 ResultSet rs = executeSelectQuery(query, timeout, timeoutUnits); 378 if(rs.hasNext()){ 379 cnt = rs.next().getLiteral("cnt").getInt(); 380 } 381 382 return cnt; 383 } 384 385 public int getSubjectCountForProperty(OWLProperty p){ 386 int cnt = -1; 387 String query = String.format( 388 "SELECT (COUNT(DISTINCT ?s) AS ?cnt) WHERE {?s <%s> ?o.}", 389 p.toStringID()); 390 ResultSet rs = executeSelectQuery(query); 391 if(rs.hasNext()){ 392 cnt = rs.next().getLiteral("cnt").getInt(); 393 } 394 395 return cnt; 396 } 397 398 public int getObjectCountForProperty(OWLObjectProperty p, long timeout, TimeUnit timeoutUnits){ 399 int cnt = -1; 400 String query = String.format( 401 "SELECT (COUNT(DISTINCT ?o) AS ?cnt) WHERE {?s <%s> ?o.}", 402 p.toStringID()); 403 ResultSet rs = executeSelectQuery(query, timeout, timeoutUnits); 404 if(rs.hasNext()){ 405 cnt = rs.next().getLiteral("cnt").getInt(); 406 } 407 408 return cnt; 409 } 410 411 public int getObjectCountForProperty(OWLObjectProperty p){ 412 int cnt = -1; 413 String query = String.format( 414 "SELECT (COUNT(DISTINCT ?o) AS ?cnt) WHERE {?s <%s> ?o.}", 415 p.toStringID()); 416 ResultSet rs = executeSelectQuery(query); 417 if(rs.hasNext()){ 418 cnt = rs.next().getLiteral("cnt").getInt(); 419 } 420 421 return cnt; 422 } 423 424 /** 425 * Computes the popularity of the given entity. 426 * @param entity the entity 427 * @param <T> the OWL entity type 428 * @return the popularity 429 */ 430 public <T extends OWLEntity> int getPopularity(T entity){ 431 // check if we have the value cached 432 Integer popularity = entityPopularityMap.get(entity); 433 434 // compute the value if not cached 435 if(popularity == null){ 436 ParameterizedSparqlString queryTemplate; 437 if(entity.isOWLClass()){ 438 queryTemplate = CLASS_POPULARITY_QUERY; 439 } else if(entity.isOWLObjectProperty() || entity.isOWLDataProperty()){ 440 queryTemplate = PROPERTY_POPULARITY_QUERY; 441 } else if(entity.isOWLNamedIndividual()){ 442 queryTemplate = INDIVIDUAL_POPULARITY_QUERY; 443 } else { 444 throw new IllegalArgumentException("Popularity computation not supported for entity type " + entity.getEntityType().getName()); 445 } 446 447 queryTemplate.setIri("entity", entity.toStringID()); 448 ResultSet rs = executeSelectQuery(queryTemplate.toString()); 449 450 popularity = rs.next().getLiteral("cnt").getInt(); 451 452 // put to cache 453 entityPopularityMap.put(entity, popularity); 454 } 455 return popularity; 456 } 457 458 459 460 public int getPopularityOf(OWLClassExpression description){ 461 if(classPopularityMap != null && classPopularityMap.containsKey(description)){ 462 return classPopularityMap.get(description); 463 } else { 464 String query = converter.asCountQuery(description).toString(); 465 ResultSet rs = executeSelectQuery(query); 466 int cnt = rs.next().getLiteral("cnt").getInt(); 467 return cnt; 468 } 469 } 470 471 @Override 472 public ClassHierarchy prepareSubsumptionHierarchy() { 473 if(precomputeClassHierarchy) { 474 if(!prepared){ 475 hierarchy = prepareSubsumptionHierarchyFast(); 476 477 prepared = true; 478 } 479 } else { 480 hierarchy = new LazyClassHierarchy(this); 481 } 482 return hierarchy; 483 } 484 485 public boolean isFunctional(OWLObjectProperty property){ 486 String query = "ASK {<" + property.toStringID() + "> a <" + OWL.FunctionalProperty.getURI() + ">}"; 487 return executeAskQuery(query); 488 } 489 490 public boolean isInverseFunctional(OWLObjectProperty property){ 491 String query = "ASK {<" + property.toStringID() + "> a <" + OWL.InverseFunctionalProperty.getURI() + ">}"; 492 return executeAskQuery(query); 493 } 494 495 public boolean isAsymmetric(OWLObjectProperty property){ 496 String query = "ASK {<" + property.toStringID() + "> a <" + OWL2.AsymmetricProperty.getURI() + ">}"; 497 return executeAskQuery(query); 498 } 499 500 public boolean isSymmetric(OWLObjectProperty property){ 501 String query = "ASK {<" + property.toStringID() + "> a <" + OWL2.SymmetricProperty.getURI() + ">}"; 502 return executeAskQuery(query); 503 } 504 505 public boolean isIrreflexive(OWLObjectProperty property){ 506 String query = "ASK {<" + property.toStringID() + "> a <" + OWL2.IrreflexiveProperty.getURI() + ">}"; 507 return executeAskQuery(query); 508 } 509 510 public boolean isReflexive(OWLObjectProperty property){ 511 String query = "ASK {<" + property.toStringID() + "> a <" + OWL2.ReflexiveProperty.getURI() + ">}"; 512 return executeAskQuery(query); 513 } 514 515 public boolean isTransitive(OWLObjectProperty property){ 516 String query = "ASK {<" + property.toStringID() + "> a <" + OWL2.TransitiveProperty.getURI() + ">}"; 517 return executeAskQuery(query); 518 } 519 520 public boolean isFunctional(OWLDataProperty property){ 521 String query = "ASK {<" + property.toStringID() + "> a <" + OWL.FunctionalProperty.getURI() + ">}"; 522 return executeAskQuery(query); 523 } 524 525 // we have this variable so that the query can be overwritten in subclasses (for workarounds) 526 protected String buildSubsumptionHierarchyQuery() { 527 return "SELECT * WHERE {" 528 + " ?sub a <http://www.w3.org/2002/07/owl#Class> . " 529 + " OPTIONAL { " 530 + "?sub (<http://www.w3.org/2000/01/rdf-schema#subClassOf>|<http://www.w3.org/2002/07/owl#equivalentClass>) ?sup ." 531 + "} \n" 532 + "}"; 533 } 534 535 /** 536 * Pre-computes the class hierarchy. Instead of executing queries for each class, 537 * we query by the predicate rdfs:subClassOf. 538 * @return the class hierarchy 539 */ 540 public ClassHierarchy prepareSubsumptionHierarchyFast() { 541 logger.info("Preparing class subsumption hierarchy ..."); 542 long startTime = System.currentTimeMillis(); 543 TreeMap<OWLClassExpression, SortedSet<OWLClassExpression>> subsumptionHierarchyUp = new TreeMap<>(); 544 TreeMap<OWLClassExpression, SortedSet<OWLClassExpression>> subsumptionHierarchyDown = new TreeMap<>(); 545 546 ResultSet rs = executeSelectQuery(buildSubsumptionHierarchyQuery()); 547 548 while (rs.hasNext()) { 549 QuerySolution qs = rs.next(); 550 if (qs.get("sub").isURIResource() && (qs.get("sup") == null || qs.get("sup").isURIResource())) { 551 OWLClass sub = df.getOWLClass(IRI.create(qs.get("sub").asResource().getURI())); 552 OWLClass sup = qs.get("sup") == null ? df.getOWLThing() 553 : df.getOWLClass(IRI.create(qs.get("sup").asResource().getURI())); 554 555 // add subclass 556 subsumptionHierarchyDown 557 .computeIfAbsent(sup, k -> new TreeSet<>()) 558 .add(sub); 559 560 // add superclass 561 subsumptionHierarchyUp 562 .computeIfAbsent(sub, k -> new TreeSet<>()) 563 .add(sup); 564 } 565 } 566 567 logger.info("... done in {}ms", (System.currentTimeMillis()-startTime)); 568 hierarchy = new ClassHierarchy(subsumptionHierarchyUp, subsumptionHierarchyDown); 569 570 return hierarchy; 571 } 572 573 /* (non-Javadoc) 574 * @see org.dllearner.core.AbstractReasonerComponent#prepareObjectPropertyHierarchy() 575 */ 576 @Override 577 public ObjectPropertyHierarchy prepareObjectPropertyHierarchy() throws ReasoningMethodUnsupportedException { 578// if(precomputeObjectPropertyHierarchy) { 579 logger.info("Preparing object property subsumption hierarchy ..."); 580 long startTime = System.currentTimeMillis(); 581 TreeMap<OWLObjectProperty, SortedSet<OWLObjectProperty>> subsumptionHierarchyUp = new TreeMap<>( 582 ); 583 TreeMap<OWLObjectProperty, SortedSet<OWLObjectProperty>> subsumptionHierarchyDown = new TreeMap<>( 584 ); 585 586 String query = "SELECT * WHERE {" 587 + "?sub a <http://www.w3.org/2002/07/owl#ObjectProperty> . " 588 + "FILTER NOT EXISTS{?sub a <http://www.w3.org/2002/07/owl#DatatypeProperty>}" // TODO remove workaround 589 + "FILTER(?sub != <http://www.w3.org/2002/07/owl#bottomObjectProperty> && ?sub != <http://www.w3.org/2002/07/owl#topObjectProperty>)" 590 + "OPTIONAL {" 591 + "?sub <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?sup ." 592 + "?sup a <http://www.w3.org/2002/07/owl#ObjectProperty> . " 593 + "FILTER(?sup != ?sub && ?sup != <http://www.w3.org/2002/07/owl#topObjectProperty>)" 594 + "}" 595 + "}"; 596 ResultSet rs = executeSelectQuery(query); 597 598 while (rs.hasNext()) { 599 QuerySolution qs = rs.next(); 600 if (qs.get("sub").isURIResource()) { 601 IRI iri = IRI.create(qs.get("sub").asResource().getURI()); 602 603 if(!iri.isReservedVocabulary()) { 604 OWLObjectProperty sub = df.getOWLObjectProperty(iri); 605 606 // add sub properties entry 607 subsumptionHierarchyDown.putIfAbsent(sub, new TreeSet<>()); 608 609 // add super properties entry 610 subsumptionHierarchyUp.putIfAbsent(sub, new TreeSet<>()); 611 612 // if there is a super property 613 if(qs.get("sup") != null && qs.get("sup").isURIResource()){ 614 OWLObjectProperty sup = df.getOWLObjectProperty(IRI.create(qs.get("sup").asResource().getURI())); 615 616 // add sub properties entry 617 subsumptionHierarchyDown.putIfAbsent(sup, new TreeSet<>()); 618 619 // add super properties entry 620 subsumptionHierarchyUp.putIfAbsent(sup, new TreeSet<>()); 621 622 // add super properties entry 623 subsumptionHierarchyUp 624 .computeIfAbsent(sub, k -> new TreeSet<>()) 625 .add(sup); 626 627 // add sub properties entry 628 subsumptionHierarchyDown 629 .computeIfAbsent(sup, k -> new TreeSet<>()) 630 .add(sub); 631 } 632 } 633 } 634 } 635 logger.info("... done in {}ms", (System.currentTimeMillis()-startTime)); 636 roleHierarchy = new ObjectPropertyHierarchy(subsumptionHierarchyUp, subsumptionHierarchyDown); 637// } 638 return roleHierarchy; 639 } 640 641 /* (non-Javadoc) 642 * @see org.dllearner.core.AbstractReasonerComponent#prepareObjectPropertyHierarchy() 643 */ 644 @Override 645 public DatatypePropertyHierarchy prepareDatatypePropertyHierarchy() throws ReasoningMethodUnsupportedException { 646 logger.info("Preparing data property subsumption hierarchy ..."); 647 long startTime = System.currentTimeMillis(); 648 TreeMap<OWLDataProperty, SortedSet<OWLDataProperty>> subsumptionHierarchyUp = new TreeMap<>( 649 ); 650 TreeMap<OWLDataProperty, SortedSet<OWLDataProperty>> subsumptionHierarchyDown = new TreeMap<>( 651 ); 652 653 String query = "SELECT * WHERE {" 654 + "?sub a <http://www.w3.org/2002/07/owl#DatatypeProperty> . " 655 + "OPTIONAL {" 656 + "?sub <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?sup ." 657 + "?sup a <http://www.w3.org/2002/07/owl#DatatypeProperty> . " 658 + "FILTER(?sup != ?sub && ?sup != <http://www.w3.org/2002/07/owl#topDatatypeProperty> )" 659 + "}" 660 + "FILTER(?sub != <http://www.w3.org/2002/07/owl#topDatatypeProperty> && ?sub != <http://www.w3.org/2002/07/owl#bottomDatatypeProperty>)" 661 + "}"; 662 ResultSet rs = executeSelectQuery(query); 663 664 while (rs.hasNext()) { 665 QuerySolution qs = rs.next(); 666 if (qs.get("sub").isURIResource()) { 667 OWLDataProperty sub = df.getOWLDataProperty(IRI.create(qs.get("sub").asResource().getURI())); 668 669 // add sub properties entry 670 subsumptionHierarchyDown.putIfAbsent(sub, new TreeSet<>()); 671 672 // add super properties entry 673 subsumptionHierarchyUp.putIfAbsent(sub, new TreeSet<>()); 674 675 // if there is a super property 676 if(qs.get("sup") != null && qs.get("sup").isURIResource()){ 677 OWLDataProperty sup = df.getOWLDataProperty(IRI.create(qs.get("sup").asResource().getURI())); 678 679 // add sub properties entry 680 subsumptionHierarchyDown.putIfAbsent(sup, new TreeSet<>()); 681 682 // add super properties entry 683 subsumptionHierarchyUp.putIfAbsent(sup, new TreeSet<>()); 684 685 // add super properties entry 686 subsumptionHierarchyUp 687 .computeIfAbsent(sub, k -> new TreeSet<>()) 688 .add(sup); 689 690 // add sub properties entry 691 subsumptionHierarchyDown 692 .computeIfAbsent(sup, k -> new TreeSet<>()) 693 .add(sub); 694 } 695 } 696 } 697 698 logger.info("... done in {}ms", (System.currentTimeMillis()-startTime)); 699 datatypePropertyHierarchy = new DatatypePropertyHierarchy(subsumptionHierarchyUp, subsumptionHierarchyDown); 700 return datatypePropertyHierarchy; 701 } 702 703 public Model loadSchema(){ 704 return loadSchema(null); 705 } 706 707 public Model loadSchema(String namespace){ 708 Model model = ModelFactory.createDefaultModel(); 709 710 //load class hierarchy 711 String query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?o} WHERE " + 712 "{?s <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?o." + (namespace != null ? "FILTER(REGEX(STR(?s), '^" + namespace + "'))}" : ""); 713 model.add(loadIncrementally(query)); 714 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#equivalentClass> ?o} WHERE {?s <http://www.w3.org/2002/07/owl#equivalentClass> ?o}"; 715 model.add(loadIncrementally(query)); 716 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#disjointWith> ?o} WHERE {?s <http://www.w3.org/2002/07/owl#disjointWith> ?o}"; 717 model.add(loadIncrementally(query)); 718 //load domain axioms 719 query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#domain> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty> } " + 720 "WHERE {?s <http://www.w3.org/2000/01/rdf-schema#domain> ?o.?s a <http://www.w3.org/2002/07/owl#ObjectProperty>}"; 721 model.add(loadIncrementally(query)); 722 query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#domain> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>} " + 723 "WHERE {?s <http://www.w3.org/2000/01/rdf-schema#domain> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>}"; 724 model.add(loadIncrementally(query)); 725 //load range axioms 726 query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#range> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>} " + 727 "WHERE {?s <http://www.w3.org/2000/01/rdf-schema#range> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>}"; 728 model.add(loadIncrementally(query)); 729 query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#range> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>} " + 730 "WHERE {?s <http://www.w3.org/2000/01/rdf-schema#range> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>}"; 731 model.add(loadIncrementally(query)); 732 //load property hierarchy 733 query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>} " + 734 "WHERE {?s <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>}"; 735 model.add(loadIncrementally(query)); 736 query = "CONSTRUCT {?s <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>} " + 737 "WHERE {?s <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>}"; 738 model.add(loadIncrementally(query)); 739 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#equivalentProperty> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>} " + 740 "WHERE {?s <http://www.w3.org/2002/07/owl#equivalentProperty> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>}"; 741 model.add(loadIncrementally(query)); 742 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#equivalentProperty> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>} " + 743 "WHERE {?s <http://www.w3.org/2002/07/owl#equivalentProperty> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>}"; 744 model.add(loadIncrementally(query)); 745 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#propertyDisjointWith> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>} " + 746 "WHERE {?s <http://www.w3.org/2002/07/owl#propertyDisjointWith> ?o. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>}"; 747 model.add(loadIncrementally(query)); 748 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#propertyDisjointWith> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>} " + 749 "WHERE {?s <http://www.w3.org/2002/07/owl#propertyDisjointWith> ?o. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>}"; 750 model.add(loadIncrementally(query)); 751 //load inverse relation 752 query = "CONSTRUCT {?s <http://www.w3.org/2002/07/owl#inverseOf> ?o} WHERE {?s <http://www.w3.org/2002/07/owl#inverseOf> ?o}"; 753 model.add(loadIncrementally(query)); 754 //load property characteristics 755 Set<Resource> propertyCharacteristics = new HashSet<>(); 756 // propertyCharacteristics.add(OWL.FunctionalProperty); 757 propertyCharacteristics.add(OWL.InverseFunctionalProperty); 758 propertyCharacteristics.add(OWL.SymmetricProperty); 759 propertyCharacteristics.add(OWL.TransitiveProperty); 760 propertyCharacteristics.add(OWL2.ReflexiveProperty); 761 propertyCharacteristics.add(OWL2.IrreflexiveProperty); 762 propertyCharacteristics.add(OWL2.AsymmetricProperty); 763 764 for(Resource propChar : propertyCharacteristics){ 765 query = "CONSTRUCT {?s a <%s>. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>} WHERE {?s a <%s>.}".replaceAll("%s", propChar.getURI()); 766 model.add(loadIncrementally(query)); 767 } 768 //for functional properties we have to distinguish between data and object properties, 769 //i.e. we have to keep the property type information, otherwise conversion to OWLAPI ontology makes something curious 770 query = "CONSTRUCT {?s a <%s>. ?s a <http://www.w3.org/2002/07/owl#ObjectProperty>} WHERE {?s a <%s>.?s a <http://www.w3.org/2002/07/owl#ObjectProperty>}". 771 replaceAll("%s", OWL.FunctionalProperty.getURI()); 772 model.add(loadIncrementally(query)); 773 query = "CONSTRUCT {?s a <%s>. ?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>} WHERE {?s a <%s>.?s a <http://www.w3.org/2002/07/owl#DatatypeProperty>}". 774 replaceAll("%s", OWL.FunctionalProperty.getURI()); 775 model.add(loadIncrementally(query)); 776 777 return model; 778 } 779 780 /** 781 * Gets all logical axioms according to entities of type owl:Class, owl:ObjectProperty and owl:DatatypeProperty. 782 * @return the OWL schema as Jena model 783 */ 784 public Model loadOWLSchema(){ 785 Model schema = ModelFactory.createDefaultModel(); 786 String prefixes = 787 "PREFIX owl:<http://www.w3.org/2002/07/owl#> " 788 + "PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#> "; 789 790 // axioms related to owl:Class entities 791 String query = prefixes + 792 "CONSTRUCT {" + 793 "?s a owl:Class." + 794 "?s rdfs:subClassOf ?sup." + 795 "?s owl:equivalentClass ?equiv." + 796 "?s owl:disjointWith ?disj." + 797 "} WHERE {" + 798 "?s a owl:Class. " + 799 "OPTIONAL{?s rdfs:subClassOf ?sup.} " + 800 "OPTIONAL{?s owl:equivalentClass ?equiv.} " + 801 "OPTIONAL{?s owl:disjointWith ?disj.}" + 802 "}"; 803 schema.add(loadIncrementally(query)); 804 805 // axioms related to owl:ObjectProperty entities 806 query = prefixes + 807 "CONSTRUCT {" + 808 "?s a owl:ObjectProperty." + 809 "?s a ?type." + 810 "?s rdfs:domain ?domain." + 811 "?s rdfs:range ?range." + 812 "} WHERE {" + 813 "?s a owl:ObjectProperty." + 814 "?s a ?type. " + 815 "OPTIONAL{?s rdfs:domain ?domain.} " + 816 "OPTIONAL{?s rdfs:range ?range.}" + 817 "}"; 818 schema.add(loadIncrementally(query)); 819 820 // axioms related to owl:DatatypeProperty entities 821 query = prefixes + 822 "CONSTRUCT {" + 823 "?s a owl:DatatypeProperty." + 824 "?s a ?type." + 825 "?s rdfs:domain ?domain." + 826 "?s rdfs:range ?range." + 827 "} WHERE {" + 828 "?s a owl:DatatypeProperty." + 829 "?s a ?type. " + 830 "OPTIONAL{?s rdfs:domain ?domain.} " + 831 "OPTIONAL{?s rdfs:range ?range.}" + 832 "}"; 833 schema.add(loadIncrementally(query)); 834 835 return schema; 836 } 837 838 private Model loadIncrementally(String query){ 839 QueryExecutionFactory old = qef; 840 qef = new QueryExecutionFactoryPaginated(qef, 10000); 841 QueryExecution qe = qef.createQueryExecution(query); 842 if (logger.isTraceEnabled()) logger.trace("Sending query \n {}", query); 843 Model model = qe.execConstruct(); 844 qe.close(); 845 qef = old; 846 return model; 847 } 848 849 @Override 850 public Set<OWLClass> getTypesImpl(OWLIndividual individual) { 851 String query = String.format(SPARQLQueryUtils.SELECT_INSTANCE_TYPES_QUERY, individual.toStringID()); 852 ResultSet rs = executeSelectQuery(query); 853 SortedSet<OWLClass> types = asOWLEntities(EntityType.CLASS, rs, "var1"); 854 return types; 855 } 856 857 public Set<OWLClass> getTypes(OWLIndividual individual, String namespace) { 858 return getTypes(individual); 859 } 860 861 public Set<OWLClass> getMostSpecificTypes(OWLIndividual individual) { 862 Set<OWLClass> types = new HashSet<>(); 863 String query = String.format( 864 "SELECT ?type WHERE {<%s> a ?type ." 865 + "FILTER NOT EXISTS{<%s> a ?moreSpecificType ." 866 + "?moreSpecificType <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?type ." 867 + "FILTER((?type != ?moreSpecificType) && (?moreSpecificType!= <http://www.w3.org/2002/07/owl#Nothing>))}}", 868 individual.toStringID(), individual.toStringID()); 869 ResultSet rs = executeSelectQuery(query); 870 while(rs.hasNext()){ 871 QuerySolution qs = rs.next(); 872 IRI iri = IRI.create(qs.getResource("type").getURI()); 873 if(!iri.isReservedVocabulary()) { 874 types.add(df.getOWLClass(iri)); 875 } 876 877 } 878 return types; 879 } 880 881 882 /** 883 * Returns the entity type of the given resource IRI, i.e. whether the resource 884 * is a owl:Class, owl:ObjectProperty,owl:DatatypeProperty or owl:NamedIndividual. 885 * @param iri the IRI of the entity 886 * @return the entity type 887 */ 888 public EntityType<? extends OWLEntity> getOWLEntityType(String iri) { 889 ParameterizedSparqlString query = new ParameterizedSparqlString("SELECT ?type WHERE {?s a ?type .}"); 890 query.setIri("s", iri); 891 ResultSet rs = executeSelectQuery(query.toString()); 892 Set<EntityType<? extends OWLEntity>> entityTypes = new HashSet<>(); 893 while(rs.hasNext()){ 894 QuerySolution qs = rs.next(); 895 String uri = qs.getResource("type").getURI(); 896 for(EntityType<? extends OWLEntity> entityType : EntityType.values()){ 897 if(entityType.getIRI().toString().equals(uri)){ 898 entityTypes.add(entityType); 899 break; 900 } 901 } 902 } 903 if(entityTypes.size() == 1){ 904 return entityTypes.iterator().next(); 905 } 906 return null; 907 } 908 909 public Set<OWLClass> getTypes(String namespace) { 910 return getTypes(namespace, false); 911 } 912 913 public Set<OWLClass> getTypes(String namespace, boolean omitEmptyTypes) { 914 Set<OWLClass> types = new TreeSet<>(); 915 String query = "SELECT DISTINCT ?cls WHERE {[] a ?cls ." + 916 (omitEmptyTypes ? "[] a ?cls ." : "" ) + 917 (namespace != null ? ("FILTER(REGEX(?cls,'^" + namespace + "'))") : "") + "}"; 918 ResultSet rs = executeSelectQuery(query); 919 while(rs.hasNext()){ 920 QuerySolution qs = rs.next(); 921 types.add(df.getOWLClass(IRI.create(qs.getResource("cls").getURI()))); 922 } 923 return types; 924 } 925 926 /* (non-Javadoc) 927 * @see org.dllearner.core.BaseReasoner#getNamedClasses() 928 */ 929 @Override 930 public SortedSet<OWLClass> getClasses() { 931 return getOWLClasses(); 932 } 933 934 public SortedSet<OWLClass> getOWLClasses() { 935 return getOWLClasses(null); 936 } 937 938 public SortedSet<OWLClass> getOWLClasses(String namespace) { 939 ResultSet rs; 940 if (!laxMode) { 941 rs = executeSelectQuery(SPARQLQueryUtils.SELECT_CLASSES_QUERY); 942 } else { 943 rs = executeSelectQuery(SPARQLQueryUtils.SELECT_CLASSES_QUERY_ALT); 944 } 945 946 SortedSet<OWLClass> classes = asOWLEntities(EntityType.CLASS, rs, "var1"); 947 return classes; 948 } 949 950 public Set<OWLClass> getNonEmptyOWLClasses() { 951 String query = "SELECT DISTINCT ?var1 WHERE {?var1 a <http://www.w3.org/2002/07/owl#Class>. FILTER EXISTS{[] a ?var1}}"; 952 ResultSet rs = executeSelectQuery(query); 953 SortedSet<OWLClass> classes = asOWLEntities(EntityType.CLASS, rs, "var1"); 954 return classes; 955 } 956 957 /* (non-Javadoc) 958 * @see org.dllearner.core.BaseReasoner#getIndividuals() 959 */ 960 @Override 961 public SortedSet<OWLIndividual> getIndividuals() { 962 return getOWLIndividuals(); 963 } 964 965 public SortedSet<OWLIndividual> getOWLIndividuals() { 966 ResultSet rs; 967 if (!laxMode) { 968 rs = executeSelectQuery(SPARQLQueryUtils.SELECT_INDIVIDUALS_QUERY); 969 } else { 970 rs = executeSelectQuery(SPARQLQueryUtils.SELECT_INDIVIDUALS_QUERY_ALT); 971 } 972 SortedSet<OWLIndividual> individuals = new TreeSet<>(); 973 individuals.addAll(asOWLEntities(EntityType.NAMED_INDIVIDUAL, rs, "var1")); 974 return individuals; 975 } 976 977 /* (non-Javadoc) 978 * @see org.dllearner.core.BaseReasoner#getObjectProperties() 979 */ 980 @Override 981 public Set<OWLObjectProperty> getObjectPropertiesImpl() { 982 return getOWLObjectProperties(); 983 } 984 985 public SortedSet<OWLObjectProperty> getOWLObjectProperties() { 986 return getOWLObjectProperties(null); 987 } 988 989 public SortedSet<OWLObjectProperty> getOWLObjectProperties(String namespace) { 990 ResultSet rs = executeSelectQuery(SPARQLQueryUtils.SELECT_OBJECT_PROPERTIES_QUERY); 991 992 SortedSet<OWLObjectProperty> properties = asOWLEntities(EntityType.OBJECT_PROPERTY, rs, "var1"); 993 return properties; 994 } 995 996 /* (non-Javadoc) 997 * @see org.dllearner.core.AbstractReasonerComponent#getDatatypePropertiesImpl() 998 */ 999 @Override 1000 protected Set<OWLDataProperty> getDatatypePropertiesImpl() throws ReasoningMethodUnsupportedException { 1001 return getOWLDataProperties(); 1002 } 1003 1004 public SortedSet<OWLDataProperty> getOWLDataProperties() { 1005 return getOWLDataProperties(null); 1006 } 1007 1008 public SortedSet<OWLDataProperty> getOWLDataProperties(String namespace) { 1009 ResultSet rs = executeSelectQuery(SPARQLQueryUtils.SELECT_DATA_PROPERTIES_QUERY); 1010 1011 SortedSet<OWLDataProperty> properties = asOWLEntities(EntityType.DATA_PROPERTY, rs, "var1"); 1012 return properties; 1013 } 1014 1015 public Set<OWLDataProperty> getDataPropertiesByRange(XSDVocabulary xsdType) { 1016 return getDataPropertiesByRange(xsdType.getIRI()); 1017 } 1018 public Set<OWLDataProperty> getDataPropertiesByRange(Set<OWLDatatype> dts) { 1019 Set<OWLDataProperty> r = new TreeSet<>(); 1020 for (OWLDatatype dt:dts) { 1021 r.addAll(getDataPropertiesByRange(dt.getIRI())); 1022 } 1023 return r; 1024 } 1025 public Set<OWLDataProperty> getDataPropertiesByRange(IRI iri) { 1026 String query = String.format(SPARQLQueryUtils.SELECT_DATA_PROPERTIES_BY_RANGE_QUERY, iri.toString()); 1027 logger.debug(sparql_debug, "get properties by range query: " + query); 1028 ResultSet rs = executeSelectQuery(query); 1029 1030 SortedSet<OWLDataProperty> properties = asOWLEntities(EntityType.DATA_PROPERTY, rs, "var1"); 1031 return properties; 1032 } 1033 /* (non-Javadoc) 1034 * @see org.dllearner.core.AbstractReasonerComponent#getIntDatatypePropertiesImpl() 1035 */ 1036 @Override 1037 protected Set<OWLDataProperty> getIntDatatypePropertiesImpl() throws ReasoningMethodUnsupportedException { 1038 return getDataPropertiesByRange(OWLAPIUtils.intDatatypes); 1039 } 1040 1041 /* (non-Javadoc) 1042 * @see org.dllearner.core.AbstractReasonerComponent#getDoubleDatatypePropertiesImpl() 1043 */ 1044 @Override 1045 protected Set<OWLDataProperty> getDoubleDatatypePropertiesImpl() throws ReasoningMethodUnsupportedException { 1046 return getDataPropertiesByRange(OWLAPIUtils.floatDatatypes); 1047 } 1048 1049 /* (non-Javadoc) 1050 * @see org.dllearner.core.AbstractReasonerComponent#getBooleanDatatypePropertiesImpl() 1051 */ 1052 @Override 1053 protected Set<OWLDataProperty> getBooleanDatatypePropertiesImpl() throws ReasoningMethodUnsupportedException { 1054 return getDataPropertiesByRange(OWLAPIUtils.fixedDatatypes); 1055 } 1056 1057 /* (non-Javadoc) 1058 * @see org.dllearner.core.AbstractReasonerComponent#getStringDatatypePropertiesImpl() 1059 */ 1060 @Override 1061 protected Set<OWLDataProperty> getStringDatatypePropertiesImpl() throws ReasoningMethodUnsupportedException { 1062 return getDataPropertiesByRange(XSDVocabulary.STRING); 1063 } 1064 1065 public Set<OWLProperty> getProperties(boolean inferType, String namespace) { 1066 Set<OWLProperty> properties = new HashSet<>(); 1067 String query = "SELECT DISTINCT ?p ?type WHERE {?s ?p ?o ." 1068 + (namespace != null ? ("FILTER(STRSTARTS(STR(?p),'^" + namespace + "'))") : "") 1069 + "OPTIONAL{?p a ?type}}"; 1070 ResultSet rs = executeSelectQuery(query); 1071 Multimap<String, String> uri2Types = HashMultimap.create(); 1072 QuerySolution qs; 1073 while(rs.hasNext()){ 1074 qs = rs.next(); 1075 String uri = qs.getResource("p").getURI(); 1076 String type = ""; 1077 if(qs.getResource("type") != null){ 1078 type = qs.getResource("type").getURI(); 1079 } 1080 uri2Types.put(uri, type); 1081 } 1082 for (Entry<String, Collection<String>> entry : uri2Types.asMap().entrySet()) { 1083 String uri = entry.getKey(); 1084 Collection<String> types = entry.getValue(); 1085 if(types.contains(OWL.ObjectProperty.getURI()) && !types.contains(OWL.DatatypeProperty.getURI())){ 1086 properties.add(df.getOWLObjectProperty(IRI.create(uri))); 1087 } else if(!types.contains(OWL.ObjectProperty.getURI()) && types.contains(OWL.DatatypeProperty.getURI())){ 1088 properties.add(df.getOWLDataProperty(IRI.create(uri))); 1089 } else if(inferType){ 1090 //infer the type by values 1091 query = "SELECT ?o WHERE {?s <" + uri + "> ?o. } LIMIT 100"; 1092 rs = executeSelectQuery(query); 1093 boolean op = true; 1094 boolean dp = true; 1095 RDFNode node; 1096 while(rs.hasNext()){ 1097 node = rs.next().get("o"); 1098 op = node.isResource(); 1099 dp = node.isLiteral(); 1100 } 1101 if(op && !dp){ 1102 properties.add(df.getOWLObjectProperty(IRI.create(uri))); 1103 } else if(!op && dp){ 1104 properties.add(df.getOWLDataProperty(IRI.create(uri))); 1105 } else { 1106 //not possible to decide 1107 } 1108 } 1109 } 1110 return properties; 1111 } 1112 1113 public Set<OWLProperty> getProperties(boolean inferType) { 1114 return getProperties(inferType, null); 1115 } 1116 1117 /** 1118 * Returns a set of sibling classes, i.e. classes that are on the same level 1119 * in the class hierarchy. 1120 * @param cls the OWL class 1121 * @return the sibling classes 1122 */ 1123 public Set<OWLClass> getSiblingClasses(OWLClass cls) { 1124 String query = SPARQLQueryUtils.SELECT_SIBLING_CLASSES_QUERY.replace("%s", cls.toStringID()); 1125 ResultSet rs = executeSelectQuery(query); 1126 Set<OWLClass> siblings = asOWLEntities(EntityType.CLASS, rs, "var1"); 1127 return siblings; 1128 } 1129 1130 @Override 1131 public boolean hasTypeImpl(OWLClassExpression description, OWLIndividual individual) { 1132 if(description.isOWLThing()) { // owl:Thing -> TRUE 1133 return true; 1134 } else if(description.isOWLNothing()) { // owl:Nothing -> FALSE 1135 return false; 1136 } else if(!description.isAnonymous()) { // atomic classes 1137 String query = String.format("ASK {<%s> a <%s>}", individual.toStringID(), description.asOWLClass().toStringID()); 1138 boolean result = executeAskQuery(query); 1139 return result; 1140 } else { // complex class expressions 1141// //TODO use ASK queries 1142// SortedSet<OWLIndividual> individuals = getIndividuals(description, Collections.singleton(individual)); 1143// return individuals.contains(individual); 1144 // FIXME universal and cardinality restrictions do not work with ASK queries 1145 String queryBody = converter.convert("?ind", description); 1146 if (queryBody.isEmpty()) 1147 return true; 1148 queryBody = queryBody.replace("?ind", "<" + individual.toStringID() + ">"); 1149 String query = "ASK {" + queryBody + "}"; 1150 boolean b = executeAskQuery(query); 1151 return b; 1152 } 1153 } 1154 1155 @Override 1156 public SortedSet<OWLIndividual> hasTypeImpl(OWLClassExpression description, Set<OWLIndividual> individuals) { 1157 SortedSet<OWLIndividual> allIndividuals = getIndividuals(description, individuals); 1158 //allIndividuals.retainAll(individuals); 1159 return allIndividuals; 1160 } 1161 1162 @Override 1163 public SortedSet<OWLIndividual> getIndividualsImpl(OWLClassExpression description) { 1164 return getIndividuals(description, 0); 1165 } 1166 1167 protected String buildIndividualsQueryValues(OWLClassExpression description, Collection<OWLIndividual> indValues, boolean isCountQuery) { 1168 StringBuilder query; 1169 String tp = converter.convert("?ind", description); 1170 1171 if (isCountQuery) { 1172 query = new StringBuilder("SELECT (COUNT(DISTINCT ?ind) as ?cnt) WHERE { \n"); 1173 } else { 1174 query = new StringBuilder("SELECT DISTINCT ?ind WHERE { \n"); 1175 } 1176 1177 query.append("VALUES ?ind { \n"); 1178 for (OWLIndividual x:indValues) { 1179 query.append("<").append(x.toStringID()).append("> "); 1180 } 1181 query.append("}. \n ").append(tp).append("\n}"); 1182 1183 return query.toString(); 1184 } 1185 1186 public SortedSet<OWLIndividual> getIndividuals(OWLClassExpression description, int limit, Set<OWLIndividual> indValues) { 1187 // we need to copy it to get something like A AND B from A AND A AND B 1188 description = duplicator.duplicateObject(description); 1189 1190 SortedSet<OWLIndividual> individuals = new TreeSet<>(); 1191 String query; 1192 1193 if (indValues != null) { 1194 query = buildIndividualsQueryValues(description, indValues, false); 1195 } else { 1196 query = converter.asQuery("?ind", description, false).toString(); 1197 } 1198 if(limit != 0) { 1199 query += " LIMIT " + limit; 1200 } 1201// query = String.format(SPARQLQueryUtils.PREFIXES + " SELECT ?ind WHERE {?ind rdf:type/rdfs:subClassOf* <%s> .}", description.asOWLClass().toStringID()); 1202 logger.trace(sparql_debug, "get individuals query: " + query); 1203 1204 ResultSet rs = executeSelectQuery(query); 1205 while(rs.hasNext()){ 1206 QuerySolution qs = rs.next(); 1207 if(qs.get("ind").isURIResource()){ 1208 individuals.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1209 } 1210 } 1211 logger.trace(sparql_debug, "get individuals result: " + (individuals.size() > 2 ? individuals.first() + ".."+(individuals.size()-2)+".."+individuals.last() 1212 : individuals.size() == 1 ? individuals.first() : "0")); 1213 return individuals; 1214 } 1215 1216 public SortedSet<OWLIndividual> getIndividuals(OWLClassExpression description, int limit) { 1217 return getIndividuals(description, limit, null); 1218 } 1219 1220 public SortedSet<OWLIndividual> getIndividuals(OWLClassExpression description, Set<OWLIndividual> indValues) { 1221 return getIndividuals(description, 0, indValues); 1222 } 1223 1224 public int getIndividualsCount(OWLClassExpression description, int limit, Set<OWLIndividual> indValues) { 1225 description = duplicator.duplicateObject(description); 1226 1227 String query; 1228 1229 if (indValues != null) { 1230 query = buildIndividualsQueryValues(description, indValues, true); 1231 } else { 1232 query = converter.asQuery("?ind", description, true).toString(); 1233 System.err.println(query); 1234 throw new RuntimeException(); 1235 } 1236 if(limit != 0) { 1237 query += " LIMIT " + limit; 1238 } 1239 if(logger.isTraceEnabled()){ 1240 logger.trace(sparql_debug, "get individuals query: " + query); 1241 } 1242 ResultSet rs = executeSelectQuery(query); 1243 while(rs.hasNext()){ 1244 QuerySolution qs = rs.next(); 1245 if(qs.get("cnt").isLiteral()){ 1246 int ret = qs.get("cnt").asLiteral().getInt();logger.trace(sparql_debug, "result: "+ret); 1247 return ret; 1248 } 1249 } 1250 throw new Error("no result"); 1251 } 1252 1253 public int getIndividualsCount(OWLClassExpression description, int limit) { 1254 return getIndividualsCount(description, limit, null); 1255 } 1256 1257 public int getIndividualsCount(OWLClassExpression description, Set<OWLIndividual> indValues) { 1258 return getIndividualsCount(description, 0, indValues); 1259 } 1260 1261 /** 1262 * @param wantedClass the class to which the individuals must belong to 1263 * @param excludeClass the class to which the individuals must not belong to 1264 * @param limit the max. number of individuals 1265 * @return get individuals of class wantedClass excluding all individuals of type excludeClass 1266 */ 1267 public SortedSet<OWLIndividual> getIndividualsExcluding(OWLClassExpression wantedClass, OWLClassExpression excludeClass, int limit) { 1268 if(wantedClass.isAnonymous()){ 1269 throw new UnsupportedOperationException("Only named classes are supported."); 1270 } 1271 SortedSet<OWLIndividual> individuals = new TreeSet<>(); 1272 String query = 1273 "SELECT DISTINCT ?ind WHERE {" + 1274 "?ind a <"+((OWLClass)wantedClass).toStringID() + "> . " + 1275 "FILTER NOT EXISTS { ?ind a <" + ((OWLClass)excludeClass).toStringID() + "> } }"; 1276 if(limit != 0) { 1277 query += " LIMIT " + limit; 1278 } 1279 ResultSet rs = executeSelectQuery(query); 1280 while(rs.hasNext()){ 1281 QuerySolution qs = rs.next(); 1282 if(qs.get("ind").isURIResource()){ 1283 individuals.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1284 } 1285 } 1286 return individuals; 1287 } 1288 1289// /** 1290// * @param cls 1291// * @param limit 1292// * @return Random Individuals not including any of the input class individuals 1293// * @author sherif 1294// */ 1295// public SortedSet<OWLIndividual> getRandomIndividuals(OWLClass cls, int limit) { 1296// SortedSet<OWLIndividual> individuals = new TreeSet<OWLIndividual>(); 1297// String query = 1298// " SELECT DISTINCT ?ind WHERE {"+ 1299// "?ind ?p ?o ."+ 1300// "FILTER(NOT EXISTS { ?ind a <" + cls.toStringID() + "> } ) }"; 1301// if(limit != 0) { 1302// query += " LIMIT " + limit; 1303// } 1304// ResultSet rs = executeSelectQuery(query); 1305// QuerySolution qs; 1306// while(rs.hasNext()){ 1307// qs = rs.next(); 1308// if(qs.get("ind").isURIResource()){ 1309// individuals.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1310// } 1311// } 1312// return individuals; 1313// } 1314 1315// /** 1316// * @param cls 1317// * @param limit 1318// * @return Random Individuals not including any of the input classes individuals 1319// * @author sherif 1320// */ 1321// public SortedSet<OWLIndividual> getRandomIndividuals(Set<OWLClass> cls, int limit) { 1322// SortedSet<OWLIndividual> individuals = new TreeSet<OWLIndividual>(); 1323// 1324// String filterStr=""; 1325// for(OWLClass nc : cls){ 1326// filterStr = filterStr.concat("FILTER(NOT EXISTS { ?ind a <").concat(nc.toStringID()).concat("> } ) "); 1327// } 1328// 1329// String query = 1330// " SELECT DISTINCT ?ind WHERE {"+ 1331// "?ind a ?o .?o <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2002/07/owl#Class>"+ 1332// filterStr+ " }"; 1333// if(limit != 0) { 1334// query += " LIMIT " + limit; 1335// } 1336// 1337// System.out.println("!!!!!!!!!!!!!!!!!!!! "+query); 1338// ResultSet rs = executeSelectQuery(query); 1339// QuerySolution qs; 1340// while(rs.hasNext()){ 1341// qs = rs.next(); 1342// if(qs.get("ind").isURIResource()){ 1343// individuals.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1344// } 1345// } 1346// return individuals; 1347// } 1348 1349// /** 1350// * @param cls 1351// * @param limit 1352// * @return Super class of the input class Individuals not including any of the input class individuals 1353// * @author sherif 1354// */ 1355// public SortedSet<OWLIndividual> getSuperClassIndividuals(OWLClass cls, int limit) { 1356// SortedSet<OWLIndividual> individuals = new TreeSet<OWLIndividual>(); 1357// Set<OWLClassExpression> superClasses = getSuperClasses(cls); 1358// 1359// for(OWLClassExpression sup : superClasses){ 1360// if(!sup.isAnonymous()) { 1361// String query = "SELECT DISTINCT ?ind WHERE { " 1362// + "?ind a <" + sup.asOWLClass().toStringID() + "> . " 1363// + "FILTER NOT EXISTS { ?ind a <" + cls.toStringID() + "> } }"; 1364// if(limit != 0) { 1365// query += " LIMIT " + limit/superClasses.size(); 1366// } 1367// 1368// System.out.println("---------------------------------------------- "+query); 1369// 1370// ResultSet rs = executeSelectQuery(query); 1371// QuerySolution qs; 1372// while(rs.hasNext()){ 1373// qs = rs.next(); 1374// if(qs.get("ind").isURIResource()){ 1375// individuals.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1376// } 1377// } 1378// System.out.println(individuals.size()); 1379// System.out.println(individuals); 1380// } 1381// } 1382// 1383// return individuals; 1384// } 1385 1386 @Override 1387 public SortedSetTuple<OWLIndividual> doubleRetrievalImpl(OWLClassExpression description) { 1388 throw new UnsupportedOperationException(); 1389 } 1390 1391 @Override 1392 public Set<OWLIndividual> getRelatedIndividualsImpl(OWLIndividual individual, OWLObjectProperty objectProperty) { 1393 Set<OWLIndividual> individuals = new HashSet<>(); 1394 String query = String.format("SELECT ?ind WHERE {<%s> <%s> ?ind, FILTER(isIRI(?ind))}", individual.toStringID(), objectProperty.toStringID()); 1395 1396 ResultSet rs = executeSelectQuery(query); 1397 while(rs.hasNext()){ 1398 QuerySolution qs = rs.next(); 1399 individuals.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1400 } 1401 return individuals; 1402 } 1403 1404 @Override 1405 public Set<OWLLiteral> getRelatedValuesImpl(OWLIndividual individual, OWLDataProperty datatypeProperty) { 1406 // TODO Auto-generated method stub 1407 return null; 1408 } 1409 1410 @Override 1411 public Map<OWLObjectProperty, Set<OWLIndividual>> getObjectPropertyRelationshipsImpl(OWLIndividual individual) { 1412 Map<OWLObjectProperty, Set<OWLIndividual>> prop2individuals = new HashMap<>(); 1413 String query = String.format("SELECT ?prop ?ind WHERE {" + 1414 "<%s> ?prop ?ind." + 1415 " FILTER(isIRI(?ind) && ?prop != <%s> && ?prop != <%s>)}", 1416 individual.toStringID(), RDF.type.getURI(), OWL.sameAs.getURI()); 1417 1418 ResultSet rs = executeSelectQuery(query); 1419 while(rs.hasNext()){ 1420 QuerySolution qs = rs.next(); 1421 OWLIndividual ind = df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI())); 1422 OWLObjectProperty property = df.getOWLObjectProperty(IRI.create(qs.getResource("prop").getURI())); 1423 prop2individuals.computeIfAbsent(property, k -> new HashSet<>()).add(ind); 1424 } 1425 return prop2individuals; 1426 } 1427 1428 @Override 1429 public Map<OWLIndividual, SortedSet<OWLIndividual>> getPropertyMembersImpl(OWLObjectProperty objectProperty) { 1430 //if (logger.isTraceEnabled()) logger.trace(ExceptionUtils.getStackTrace(new Throwable())); 1431 Map<OWLIndividual, SortedSet<OWLIndividual>> subject2objects = new HashMap<>(); 1432 String query = String.format("SELECT ?s ?o WHERE {" + 1433 "?s <%s> ?o." + 1434 " FILTER(isIRI(?o))}", 1435 objectProperty.toStringID()); 1436 1437 ResultSet rs = executeSelectQuery(query); 1438 while(rs.hasNext()){ 1439 QuerySolution qs = rs.next(); 1440 if (qs.getResource("s") == null || qs.getResource("s").getURI() == null) { 1441 logger.warn(sparql_debug, "The ?s is empty {} {}", query, qs); 1442 continue; 1443 } 1444 OWLIndividual sub = df.getOWLNamedIndividual(IRI.create(qs.getResource("s").getURI())); 1445 OWLIndividual obj = df.getOWLNamedIndividual(IRI.create(qs.getResource("o").getURI())); 1446 subject2objects.computeIfAbsent(sub, k -> new TreeSet<>()).add(obj); 1447 } 1448 return subject2objects; 1449 } 1450 1451 protected String buildApplicablePropertiesValuesQuery(OWLClassExpression domain, Collection<? extends OWLObjectProperty> objectProperties) { 1452 String domQuery = converter.convert("?dom", domain); 1453 String props = objectProperties.stream().map(op -> "<" + op.toStringID() + ">").collect(Collectors.joining(" ")); 1454// String prop1 = converter.convert("?p", objectProperties.iterator().next()); 1455 1456 String query = "SELECT DISTINCT ?p WHERE { " + 1457 "" + domQuery + " ?dom ?p ?o . \n" + 1458 "" + " VALUES ?p { \n" + props + " } \n" + 1459 "" + " }"; 1460 return query; 1461 } 1462 1463 public Set<OWLObjectProperty> getApplicableProperties(OWLClassExpression domain, Set<OWLObjectProperty> objectProperties) { 1464 if (isPreferAsk()) { 1465 String domQuery = converter.convert("?dom", domain); 1466 return objectProperties.stream() 1467 .filter(p -> executeAskQuery("ASK { " + domQuery + " ?dom <" + p.toStringID() + "> ?o . }")) 1468 .collect(Collectors.toSet()); 1469 } else { 1470 Set<OWLObjectProperty> ret = new TreeSet<>(); 1471 1472 ResultSet rs = executeSelectQuery(buildApplicablePropertiesValuesQuery(domain, objectProperties)); 1473 while (rs.hasNext()) { 1474 QuerySolution qs = rs.next(); 1475 OWLObjectProperty prop = df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI())); 1476 ret.add(prop); 1477 } 1478 return ret; 1479 } 1480 } 1481 1482 @Override 1483 public Map<OWLIndividual, SortedSet<OWLLiteral>> getDatatypeMembersImpl(OWLDataProperty dataProperty) { 1484 Map<OWLIndividual, SortedSet<OWLLiteral>> subject2objects = new HashMap<>(); 1485 1486 String query = String.format(SPARQLQueryUtils.SELECT_PROPERTY_RELATIONSHIPS_QUERY, dataProperty.toStringID()); 1487 1488 ResultSet rs = executeSelectQuery(query); 1489 while(rs.hasNext()){ 1490 QuerySolution qs = rs.next(); 1491 OWLIndividual sub = df.getOWLNamedIndividual(IRI.create(qs.getResource("var1").getURI())); 1492 OWLLiteral obj = OwlApiJenaUtils.getOWLLiteral(qs.getLiteral("var2")); 1493 subject2objects.computeIfAbsent(sub, k -> new TreeSet<>()).add(obj); 1494 } 1495 return subject2objects; 1496 } 1497 1498 private String datatypeSparqlFilter(Iterable<OWLDatatype> dts) { 1499 return Joiner.on(" || ").join( 1500 StreamSupport.stream(dts.spliterator(), false) 1501 .map(input -> "DATATYPE(?o) = <" + input.toStringID() + ">") 1502 .collect(Collectors.toList()) 1503 ); 1504 } 1505 1506 @Override 1507 public Map<OWLIndividual, SortedSet<Double>> getDoubleDatatypeMembersImpl(OWLDataProperty datatypeProperty) { 1508 Map<OWLIndividual, SortedSet<Double>> subject2objects = new HashMap<>(); 1509 String query = "SELECT ?s ?o WHERE {" + 1510 String.format("?s <%s> ?o.", datatypeProperty.toStringID()) + 1511 " FILTER(" + datatypeSparqlFilter(OWLAPIUtils.floatDatatypes) + ")}"; 1512 1513 ResultSet rs = executeSelectQuery(query); 1514 while(rs.hasNext()){ 1515 QuerySolution qs = rs.next(); 1516 OWLIndividual sub = df.getOWLNamedIndividual(IRI.create(qs.getResource("s").getURI())); 1517 Literal val = qs.getLiteral("o").asLiteral(); 1518 // Virtuoso bug workaround which returns NAN instead of NaN 1519 Double obj = "NAN".equals(val.getLexicalForm()) ? Double.NaN : val.getDouble(); 1520 subject2objects.computeIfAbsent(sub, k -> new TreeSet<>()).add(obj); 1521 } 1522 return subject2objects; 1523 } 1524 1525 @Override 1526 public Map<OWLIndividual, SortedSet<Integer>> getIntDatatypeMembersImpl(OWLDataProperty datatypeProperty) { 1527 Map<OWLIndividual, SortedSet<Integer>> subject2objects = new HashMap<>(); 1528 String query = "SELECT ?s ?o WHERE {" + 1529 String.format("?s <%s> ?o.", datatypeProperty.toStringID()) + 1530 " FILTER(" + datatypeSparqlFilter(OWLAPIUtils.intDatatypes) + ")}"; 1531 1532 ResultSet rs = executeSelectQuery(query); 1533 while(rs.hasNext()){ 1534 QuerySolution qs = rs.next(); 1535 OWLIndividual sub = df.getOWLNamedIndividual(IRI.create(qs.getResource("s").getURI())); 1536 Integer obj = qs.getLiteral("o").getInt(); 1537 subject2objects.computeIfAbsent(sub, k -> new TreeSet<>()).add(obj); 1538 } 1539 return subject2objects; 1540 } 1541 1542 @Override 1543 public Map<OWLIndividual, SortedSet<Boolean>> getBooleanDatatypeMembersImpl(OWLDataProperty datatypeProperty) { 1544 Map<OWLIndividual, SortedSet<Boolean>> subject2objects = new HashMap<>(); 1545 String query = "SELECT ?s ?o WHERE {" + 1546 String.format("?s <%s> ?o.", datatypeProperty.toStringID()) + 1547 " FILTER(" + datatypeSparqlFilter(OWLAPIUtils.fixedDatatypes) + ")}"; 1548 1549 ResultSet rs = executeSelectQuery(query); 1550 while(rs.hasNext()){ 1551 QuerySolution qs = rs.next(); 1552 OWLIndividual sub = df.getOWLNamedIndividual(IRI.create(qs.getResource("s").getURI())); 1553 Boolean obj = qs.getLiteral("o").getBoolean(); 1554 subject2objects.computeIfAbsent(sub, k -> new TreeSet<>()).add(obj); 1555 } 1556 return subject2objects; 1557 } 1558 1559 @Override 1560 public SortedSet<OWLIndividual> getTrueDatatypeMembersImpl(OWLDataProperty datatypeProperty) { 1561 SortedSet<OWLIndividual> members = new TreeSet<>(); 1562 String query = String.format("SELECT ?ind WHERE {" + 1563 "?ind <%s> ?o." + 1564 " FILTER(isLiteral(?o) && DATATYPE(?o) = <%s> && ?o = %s)}", 1565 datatypeProperty.toStringID(), XSD.BOOLEAN.toStringID(), 1566 "\"true\"^^<" + XSD.BOOLEAN.toStringID() + ">"); 1567 1568 ResultSet rs = executeSelectQuery(query); 1569 while(rs.hasNext()){ 1570 QuerySolution qs = rs.next(); 1571 members.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1572 } 1573 return members; 1574 } 1575 1576 @Override 1577 public SortedSet<OWLIndividual> getFalseDatatypeMembersImpl(OWLDataProperty datatypeProperty) { 1578 SortedSet<OWLIndividual> members = new TreeSet<>(); 1579 String query = String.format("SELECT ?ind WHERE {" + 1580 "?ind <%s> ?o." + 1581 " FILTER(isLiteral(?o) && DATATYPE(?o) = <%s> && ?o = %s)}", 1582 datatypeProperty.toStringID(), XSD.BOOLEAN.toStringID(), 1583 "\"false\"^^<"+XSD.BOOLEAN.toStringID() + ">"); 1584 1585 ResultSet rs = executeSelectQuery(query); 1586 while(rs.hasNext()){ 1587 QuerySolution qs = rs.next(); 1588 members.add(df.getOWLNamedIndividual(IRI.create(qs.getResource("ind").getURI()))); 1589 } 1590 return members; 1591 } 1592 1593 @Override 1594 public Map<OWLIndividual, SortedSet<String>> getStringDatatypeMembersImpl(OWLDataProperty datatypeProperty) { 1595 // TODO Auto-generated method stub 1596 return null; 1597 } 1598 1599 @Override 1600 public Set<OWLClass> getInconsistentClassesImpl() { 1601 throw new UnsupportedOperationException(); 1602 } 1603 1604 private OWLClassExpression computeDomain(OWLProperty property) { 1605 String query = String.format("SELECT ?domain WHERE {" + 1606 "<%s> <%s> ?domain. FILTER(isIRI(?domain))" + 1607 "}", 1608 property.toStringID(), RDFS.domain.getURI()); 1609 1610 try { 1611 ResultSet rs = executeSelectQuery(query); 1612 SortedSet<OWLClassExpression> domains = new TreeSet<>(); 1613 while(rs.hasNext()){ 1614 QuerySolution qs = rs.next(); 1615 domains.add(df.getOWLClass(IRI.create(qs.getResource("domain").getURI()))); 1616 } 1617 domains.remove(df.getOWLThing()); 1618 if(domains.size() == 1){ 1619 return domains.first(); 1620 } else if(domains.size() > 1){ 1621 return df.getOWLObjectIntersectionOf(domains); 1622 } 1623 return df.getOWLThing(); 1624 } catch (Exception e) { 1625 logger.error("Failed to compute the domain for " + property + ".", e); 1626 } 1627 return null; 1628 } 1629 1630 @Override 1631 public OWLClassExpression getDomainImpl(OWLObjectProperty property) { 1632 return propertyDomains.computeIfAbsent(property, k -> computeDomain(property)); 1633 } 1634 1635 public Set<OWLObjectProperty> getObjectPropertiesWithDomain(OWLClass domain) { 1636 Set<OWLObjectProperty> properties = new TreeSet<>(); 1637 1638 String query = "SELECT ?p WHERE {?p <http://www.w3.org/2000/01/rdf-schema#domain> <" + domain.toStringID() + ">.}"; 1639 ResultSet rs = executeSelectQuery(query); 1640 QuerySolution qs; 1641 while(rs.hasNext()){ 1642 qs = rs.next(); 1643 properties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI()))); 1644 } 1645 1646 return properties; 1647 } 1648 1649 public Set<OWLObjectProperty> getObjectProperties(OWLClass cls) { 1650 Set<OWLObjectProperty> properties = new TreeSet<>(); 1651 1652 String query = "SELECT DISTINCT ?p WHERE {?s a <" + cls.toStringID() + ">. ?s ?p ?o}"; 1653 ResultSet rs = executeSelectQuery(query); 1654 QuerySolution qs; 1655 while(rs.hasNext()){ 1656 qs = rs.next(); 1657 properties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI()))); 1658 } 1659 1660 return properties; 1661 } 1662 1663 public SortedSet<OWLClass> getDomains(OWLObjectProperty objectProperty) { 1664 String query = String.format("SELECT ?domain WHERE {" + 1665 "<%s> <%s> ?domain. FILTER(isIRI(?domain))" + 1666 "}", 1667 objectProperty.toStringID(), RDFS.domain.getURI()); 1668 1669 ResultSet rs = executeSelectQuery(query); 1670 QuerySolution qs; 1671 SortedSet<OWLClass> domains = new TreeSet<>(); 1672 while(rs.hasNext()){ 1673 qs = rs.next(); 1674 domains.add(df.getOWLClass(IRI.create(qs.getResource("domain").getURI()))); 1675 1676 } 1677 return domains; 1678 } 1679 1680 @Override 1681 public OWLClassExpression getDomainImpl(OWLDataProperty property) { 1682 return propertyDomains.computeIfAbsent(property, k -> computeDomain(property)); 1683 } 1684 1685 @Override 1686 public OWLClassExpression getRangeImpl(OWLObjectProperty property) { 1687 return objectPropertyRanges.computeIfAbsent(property, k -> { 1688 String query = String.format("SELECT ?range WHERE {" + 1689 "<%s> <%s> ?range. FILTER(isIRI(?range))" + 1690 "}", 1691 property.toStringID(), RDFS.range.getURI()); 1692 1693 try { 1694 ResultSet rs = executeSelectQuery(query); 1695 SortedSet<OWLClassExpression> ranges = new TreeSet<>(); 1696 while (rs.hasNext()) { 1697 QuerySolution qs = rs.next(); 1698 ranges.add(df.getOWLClass(IRI.create(qs.getResource("range").getURI()))); 1699 } 1700 ranges.remove(df.getOWLThing()); 1701 if (ranges.size() == 1) { 1702 return ranges.first(); 1703 } else if (ranges.size() > 1) { 1704 return df.getOWLObjectIntersectionOf(ranges); 1705 } 1706 return df.getOWLThing(); 1707 } catch (Exception e) { 1708 logger.error("Failed to compute range for " + property, e); 1709 } 1710 return null; 1711 }); 1712 } 1713 1714 public SortedSet<OWLClass> getRanges(OWLObjectProperty objectProperty) { 1715 String query = String.format("SELECT ?range WHERE {" + 1716 "<%s> <%s> ?range. FILTER(isIRI(?range))" + 1717 "}", 1718 objectProperty.toStringID(), RDFS.range.getURI()); 1719 1720 ResultSet rs = executeSelectQuery(query); 1721 QuerySolution qs; 1722 SortedSet<OWLClass> ranges = new TreeSet<>(); 1723 while(rs.hasNext()){ 1724 qs = rs.next(); 1725 ranges.add(df.getOWLClass(IRI.create(qs.getResource("range").getURI()))); 1726 } 1727 return ranges; 1728 } 1729 1730 public boolean isObjectProperty(String propertyURI){ 1731 String query = String.format("ASK {<%s> a <%s>}", propertyURI, OWL.ObjectProperty.getURI()); 1732 boolean isObjectProperty = executeAskQuery(query); 1733 return isObjectProperty; 1734 } 1735 1736 public boolean isObjectProperty(String propertyURI, boolean analyzeData){ 1737 String query = String.format("ASK {<%s> a <%s>}", propertyURI, OWL.ObjectProperty.getURI()); 1738 boolean isObjectProperty = executeAskQuery(query); 1739 if(!isObjectProperty && analyzeData){ 1740 query = String.format("ASK {?s <%s> ?o.FILTER(isURI(?o))}", propertyURI); 1741 isObjectProperty = executeAskQuery(query); 1742 } 1743 return isObjectProperty; 1744 } 1745 1746 public boolean isDataProperty(String propertyURI){ 1747 if(propertyURI.equals("http://www.w3.org/2000/01/rdf-schema#label")) return true; 1748 String query = String.format("ASK {<%s> a <%s>}", propertyURI, OWL.DatatypeProperty.getURI()); 1749 boolean isDataProperty = executeAskQuery(query); 1750 return isDataProperty; 1751 } 1752 1753 public boolean isDataProperty(String propertyURI, boolean analyzeData){ 1754 if(propertyURI.equals("http://www.w3.org/2000/01/rdf-schema#label")) return true; 1755 String query = String.format("ASK {<%s> a <%s>}", propertyURI, OWL.DatatypeProperty.getURI()); 1756 boolean isDataProperty = executeAskQuery(query); 1757 if(!isDataProperty && analyzeData){ 1758 query = String.format("ASK {?s <%s> ?o.FILTER(isLITERAL(?o))}", propertyURI); 1759 isDataProperty = executeAskQuery(query); 1760 } 1761 return isDataProperty; 1762 } 1763 1764 public int getIndividualsCount(OWLClass cls){ 1765 String query = String.format("SELECT (COUNT(?s) AS ?cnt) WHERE {?s a <%s>.}", cls.toStringID()); 1766 ResultSet rs = executeSelectQuery(query); 1767 int cnt = rs.next().get(rs.getResultVars().get(0)).asLiteral().getInt(); 1768 return cnt; 1769 1770 } 1771 1772 public int getPropertyCount(OWLObjectProperty property){ 1773 String query = String.format("SELECT (COUNT(*) AS ?cnt) WHERE {?s <%s> ?o.}", property.toStringID()); 1774 ResultSet rs = executeSelectQuery(query); 1775 int cnt = rs.next().get(rs.getResultVars().get(0)).asLiteral().getInt(); 1776 return cnt; 1777 1778 } 1779 1780 public SortedSet<OWLObjectProperty> getInverseObjectProperties(OWLObjectProperty property){ 1781 SortedSet<OWLObjectProperty> inverseObjectProperties = new TreeSet<>(); 1782 String query = "SELECT ?p WHERE {" + 1783 "{<%p> <%ax> ?p.} UNION {?p <%ax> <%p>}}".replace("%p", property.toStringID()).replace("%ax", OWL.inverseOf.getURI()); 1784 ResultSet rs = executeSelectQuery(query); 1785 QuerySolution qs; 1786 while(rs.hasNext()){ 1787 qs = rs.next(); 1788 inverseObjectProperties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI()))); 1789 1790 } 1791 return inverseObjectProperties; 1792 } 1793 1794 @Override 1795 public OWLDataRange getRangeImpl(OWLDataProperty datatypeProperty) { 1796 String query = String.format("SELECT ?range WHERE {" + 1797 "<%s> <%s> ?range. FILTER(isIRI(?range))" + 1798 "}", 1799 datatypeProperty.toStringID(), RDFS.range.getURI()); 1800 1801 ResultSet rs = executeSelectQuery(query); 1802 QuerySolution qs; 1803 OWLDataRange range = null; 1804 while(rs.hasNext()){ 1805 qs = rs.next(); 1806 range = df.getOWLDatatype(IRI.create(qs.getResource("range").getURI())); 1807 1808 } 1809 return range == null ? df.getOWLDatatype(OWL2Datatype.RDFS_LITERAL.getIRI()) : range; 1810 } 1811 1812 @Override 1813 public boolean isSuperClassOfImpl(OWLClassExpression superClass, OWLClassExpression subClass) { 1814 if(subClass.isAnonymous() || superClass.isAnonymous()){ 1815// throw new IllegalArgumentException("Only named classes are supported."); 1816 return false; 1817 } 1818 String query = String.format("ASK {<%s> <%s> <%s>.}", 1819 ((OWLClass)subClass).toStringID(), 1820 RDFS.subClassOf.getURI(), 1821 ((OWLClass)superClass).toStringID()); 1822 boolean superClassOf = executeAskQuery(query); 1823 return superClassOf; 1824 } 1825 1826 @Override 1827 public boolean isEquivalentClassImpl(OWLClassExpression class1, OWLClassExpression class2) { 1828 if(class1.isAnonymous() || class2.isAnonymous()){ 1829// throw new IllegalArgumentException("Only named classes are supported."); 1830 return false; 1831 } 1832 String query = String.format("ASK {<%s> <%s> <%s>.}", 1833 ((OWLClass)class1).toStringID(), 1834 OWL.equivalentClass.getURI(), 1835 ((OWLClass)class2).toStringID()); 1836 boolean equivalentClass = executeAskQuery(query); 1837 return equivalentClass; 1838 } 1839 1840 @Override 1841 public Set<OWLClassExpression> getAssertedDefinitions(OWLClass cls) { 1842 // currently we are not able to do this because of the blank node style representation of complex class expressions in RDF 1843 return Collections.emptySet(); 1844// Set<OWLClassExpression> definitions = new HashSet<OWLClassExpression>(); 1845// String query = String.format(SPARQLQueryUtils.SELECT_EQUIVALENT_CLASSES_QUERY, cls.toStringID(), cls.toStringID()); 1846// 1847// ResultSet rs = executeSelectQuery(query); 1848// QuerySolution qs; 1849// while(rs.hasNext()){ 1850// qs = rs.next(); 1851//// definitions.add(df.getOWLClass(IRI.create(qs.getResource("class").getURI()))); 1852// } 1853// return definitions; 1854 } 1855 1856 @Override 1857 public Set<OWLClassExpression> isSuperClassOfImpl(Set<OWLClassExpression> superClasses, OWLClassExpression subClasses) { 1858 // TODO Auto-generated method stub 1859 return null; 1860 } 1861 1862 1863 public SortedSet<OWLClassExpression> getMostGeneralClasses() { 1864 return hierarchy.getMostGeneralClasses(); 1865 } 1866 1867 public SortedSet<OWLClass> getMostSpecificClasses() { 1868 SortedSet<OWLClass> classes = new TreeSet<>(); 1869 String query = "SELECT ?cls WHERE {?cls a <http://www.w3.org/2002/07/owl#Class>. " 1870 + "FILTER NOT EXISTS{?sub <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?cls. FILTER(?sub != <http://www.w3.org/2002/07/owl#Nothing>)}}"; 1871 ResultSet rs = executeSelectQuery(query); 1872 QuerySolution qs; 1873 while(rs.hasNext()){ 1874 qs = rs.next(); 1875 classes.add(df.getOWLClass(IRI.create(qs.getResource("cls").getURI()))); 1876 } 1877 return classes; 1878 } 1879 1880 @Override 1881 public SortedSet<OWLClassExpression> getSuperClassesImpl(OWLClassExpression description) { 1882 String query; 1883 if(description.isAnonymous()){ 1884 throw new IllegalArgumentException("Only named classes are supported."); 1885 } else if(description.isOWLThing()) { 1886 return Sets.newTreeSet(); 1887 } else if(description.isOWLNothing()) { 1888 query = SPARQLQueryUtils.SELECT_LEAF_CLASSES_OWL; 1889 } else { 1890 query = String.format( 1891 SPARQLQueryUtils.SELECT_DIRECT_SUPERCLASS_OF_QUERY, 1892 description.asOWLClass().toStringID() 1893 ); 1894 } 1895 1896 ResultSet rs = executeSelectQuery(query); 1897 1898 SortedSet<OWLClass> superClasses = asOWLEntities(EntityType.CLASS, rs, "var1"); 1899 superClasses.remove(description); 1900// System.out.println("Sup(" + description + "):" + superClasses); 1901 return new TreeSet<OWLClassExpression>(superClasses); 1902 } 1903 1904 public SortedSet<OWLClassExpression> getSuperClasses(OWLClassExpression description, boolean direct){ 1905 if(description.isAnonymous()){ 1906 throw new IllegalArgumentException("Only named classes are supported."); 1907 } 1908 SortedSet<OWLClassExpression> superClasses = new TreeSet<>(); 1909 String query; 1910 if(direct){ 1911 query = String.format("SELECT ?sup {<%s> <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?sup. FILTER(isIRI(?sup))}", 1912 description.asOWLClass().toStringID()); 1913 } else { 1914 query = String.format("SELECT ?sup {<%s> <http://www.w3.org/2000/01/rdf-schema#subClassOf>* ?sup. FILTER(isIRI(?sup))}", 1915 description.asOWLClass().toStringID()); 1916 } 1917 ResultSet rs = executeSelectQuery(query); 1918 QuerySolution qs; 1919 while(rs.hasNext()){ 1920 qs = rs.next(); 1921 superClasses.add(df.getOWLClass(IRI.create(qs.getResource("sup").getURI()))); 1922 } 1923 superClasses.remove(description); 1924 1925 return superClasses; 1926 } 1927 1928 @Override 1929 public SortedSet<OWLClassExpression> getSubClassesImpl(OWLClassExpression description) { 1930 return getSubClasses(description, true); 1931 } 1932 1933 public SortedSet<OWLClassExpression> getSubClasses(OWLClassExpression description, boolean direct) { 1934 if(description.isAnonymous()){ 1935 throw new IllegalArgumentException("Only named classes are supported."); 1936 } 1937 SortedSet<OWLClassExpression> subClasses = new TreeSet<>(); 1938 1939 String query; 1940 if(description.isOWLThing()) { 1941 query = SPARQLQueryUtils.SELECT_TOP_LEVEL_OWL_CLASSES; 1942 } else { 1943 query = String.format(SPARQLQueryUtils.SELECT_SUBCLASS_OF_QUERY, description.asOWLClass().toStringID()); 1944 if(direct){ 1945 1946 } else { 1947 1948 } 1949 } 1950 1951 ResultSet rs = executeSelectQuery(query); 1952 subClasses.addAll(asOWLEntities(EntityType.CLASS, rs, "var1")); 1953 1954 subClasses.remove(description); 1955 subClasses.remove(df.getOWLNothing()); 1956// System.out.println("Sub(" + description + "):" + subClasses); 1957 return new TreeSet<>(subClasses); 1958 } 1959 1960 public boolean isSuperClassOf(OWLClass sup, OWLClass sub, boolean direct) { 1961 String query = direct ? SPARQLQueryUtils.SELECT_SUPERCLASS_OF_QUERY : SPARQLQueryUtils.SELECT_SUPERCLASS_OF_QUERY_RDFS; 1962 query = String.format(query, sub.toStringID()); 1963 ResultSet rs = executeSelectQuery(query); 1964 SortedSet<OWLClass> superClasses = asOWLEntities(EntityType.CLASS, rs, "var1"); 1965 return superClasses.contains(sup); 1966 } 1967 1968 @Override 1969 public SortedSet<OWLObjectProperty> getSuperPropertiesImpl(OWLObjectProperty objectProperty) { 1970 SortedSet<OWLObjectProperty> properties = new TreeSet<>(); 1971 String query = String.format( 1972 SPARQLQueryUtils.SELECT_SUPERPROPERTY_OF_QUERY, 1973 objectProperty.toStringID() 1974 ); 1975 ResultSet rs = executeSelectQuery(query); 1976 QuerySolution qs; 1977 while(rs.hasNext()){ 1978 qs = rs.next(); 1979 properties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("var1").getURI()))); 1980 } 1981 properties.remove(objectProperty); 1982 properties.remove(df.getOWLTopObjectProperty()); 1983 return properties; 1984 } 1985 1986 @Override 1987 public SortedSet<OWLObjectProperty> getSubPropertiesImpl(OWLObjectProperty objectProperty) { 1988 SortedSet<OWLObjectProperty> properties = new TreeSet<>(); 1989 String query = String.format( 1990 SPARQLQueryUtils.SELECT_SUBPROPERTY_OF_QUERY, 1991 objectProperty.toStringID() 1992 ); 1993 ResultSet rs = executeSelectQuery(query); 1994 QuerySolution qs; 1995 while(rs.hasNext()){ 1996 qs = rs.next(); 1997 properties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("var1").getURI()))); 1998 } 1999 properties.remove(objectProperty); 2000 properties.remove(df.getOWLBottomObjectProperty()); 2001 return properties; 2002 } 2003 2004 public SortedSet<OWLObjectProperty> getEquivalentProperties(OWLObjectProperty objectProperty) { 2005 SortedSet<OWLObjectProperty> properties = new TreeSet<>(); 2006 String query = String.format( 2007 SPARQLQueryUtils.SELECT_EQUIVALENT_PROPERTIES_QUERY, objectProperty.toStringID(), objectProperty.toStringID() 2008 ); 2009 ResultSet rs = executeSelectQuery(query); 2010 QuerySolution qs; 2011 while(rs.hasNext()){ 2012 qs = rs.next(); 2013 properties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("var1").getURI()))); 2014 } 2015 return properties; 2016 } 2017 2018 public SortedSet<OWLObjectProperty> getDisjointProperties(OWLObjectProperty objectProperty) { 2019 SortedSet<OWLObjectProperty> properties = new TreeSet<>(); 2020 String query = String.format( 2021 SPARQLQueryUtils.SELECT_DISJOINT_PROPERTIES_QUERY, 2022 objectProperty.toStringID(), objectProperty.toStringID() 2023 ); 2024 ResultSet rs = executeSelectQuery(query); 2025 QuerySolution qs; 2026 while(rs.hasNext()){ 2027 qs = rs.next(); 2028 properties.add(df.getOWLObjectProperty(IRI.create(qs.getResource("var1").getURI()))); 2029 } 2030 return properties; 2031 } 2032 2033 public SortedSet<OWLDataProperty> getEquivalentProperties(OWLDataProperty objectProperty) { 2034 SortedSet<OWLDataProperty> superProperties = new TreeSet<>(); 2035 String query = String.format( 2036 SPARQLQueryUtils.SELECT_EQUIVALENT_PROPERTIES_QUERY, 2037 objectProperty.toStringID(), objectProperty.toStringID() 2038 ); 2039 ResultSet rs = executeSelectQuery(query); 2040 QuerySolution qs; 2041 while(rs.hasNext()){ 2042 qs = rs.next(); 2043 superProperties.add(df.getOWLDataProperty(IRI.create(qs.getResource("var1").getURI()))); 2044 } 2045 return superProperties; 2046 } 2047 2048 @Override 2049 public SortedSet<OWLDataProperty> getSuperPropertiesImpl(OWLDataProperty dataProperty) { 2050 SortedSet<OWLDataProperty> properties = new TreeSet<>(); 2051 String query = String.format( 2052 SPARQLQueryUtils.SELECT_SUPERPROPERTY_OF_QUERY, 2053 dataProperty.toStringID() 2054 ); 2055 ResultSet rs = executeSelectQuery(query); 2056 QuerySolution qs; 2057 while(rs.hasNext()){ 2058 qs = rs.next(); 2059 properties.add(df.getOWLDataProperty(IRI.create(qs.getResource("var1").getURI()))); 2060 } 2061 properties.remove(dataProperty); 2062 properties.remove(df.getOWLTopDataProperty()); 2063 return properties; 2064 } 2065 2066 @Override 2067 public SortedSet<OWLDataProperty> getSubPropertiesImpl(OWLDataProperty dataProperty) { 2068 SortedSet<OWLDataProperty> properties = new TreeSet<>(); 2069 String query = String.format( 2070 SPARQLQueryUtils.SELECT_SUPERPROPERTY_OF_QUERY, 2071 dataProperty.toStringID() 2072 ); 2073 ResultSet rs = executeSelectQuery(query); 2074 QuerySolution qs; 2075 while(rs.hasNext()){ 2076 qs = rs.next(); 2077 properties.add(df.getOWLDataProperty(IRI.create(qs.getResource("var1").getURI()))); 2078 } 2079 properties.remove(dataProperty); 2080 properties.remove(df.getOWLBottomDataProperty()); 2081 return properties; 2082 } 2083 2084 public SortedSet<OWLDataProperty> getDisjointProperties(OWLDataProperty dataProperty) { 2085 SortedSet<OWLDataProperty> properties = new TreeSet<>(); 2086 String query = String.format( 2087 SPARQLQueryUtils.SELECT_DISJOINT_PROPERTIES_QUERY, 2088 dataProperty.toStringID(), dataProperty.toStringID() 2089 ); 2090 ResultSet rs = executeSelectQuery(query); 2091 QuerySolution qs; 2092 while(rs.hasNext()){ 2093 qs = rs.next(); 2094 properties.add(df.getOWLDataProperty(IRI.create(qs.getResource("var1").getURI()))); 2095 } 2096 properties.remove(dataProperty); 2097 return properties; 2098 } 2099 2100 /* (non-Javadoc) 2101 * @see org.dllearner.core.AbstractReasonerComponent#getObjectPropertyDomains() 2102 */ 2103 @Override 2104 public Map<OWLObjectProperty, OWLClassExpression> getObjectPropertyDomains() { 2105 Map<OWLObjectProperty, OWLClassExpression> result = new HashMap<>(); 2106 2107 String query = SPARQLQueryUtils.PREFIXES + "SELECT ?p ?dom WHERE {?p a owl:ObjectProperty . OPTIONAL{?p rdfs:domain ?dom .}}"; 2108 ResultSet rs = executeSelectQuery(query); 2109 while(rs.hasNext()) { 2110 QuerySolution qs = rs.next(); 2111 OWLObjectProperty op = df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI())); 2112 2113 // default domain is owl:Thing 2114 OWLClassExpression domain = df.getOWLThing(); 2115 if(qs.get("dom") != null) { 2116 if(qs.get("dom").isURIResource()) { 2117 domain = df.getOWLClass(IRI.create(qs.getResource("dom").getURI())); 2118 2119 } else { 2120 logger.warn("Can not resolve complex domain for object property " + op); 2121 } 2122 } 2123 result.put(op, domain); 2124 } 2125 return result; 2126 } 2127 2128 /* (non-Javadoc) 2129 * @see org.dllearner.core.AbstractReasonerComponent#getObjectPropertyRanges() 2130 */ 2131 @Override 2132 public Map<OWLObjectProperty, OWLClassExpression> getObjectPropertyRanges() { 2133 Map<OWLObjectProperty, OWLClassExpression> result = new HashMap<>(); 2134 2135 String query = SPARQLQueryUtils.PREFIXES + "SELECT ?p ?ran WHERE {?p a owl:ObjectProperty . OPTIONAL{?p rdfs:range ?ran .}}"; 2136 ResultSet rs = executeSelectQuery(query); 2137 while(rs.hasNext()) { 2138 QuerySolution qs = rs.next(); 2139 OWLObjectProperty op = df.getOWLObjectProperty(IRI.create(qs.getResource("p").getURI())); 2140 2141 // default range is owl:Thing 2142 OWLClassExpression range = df.getOWLThing(); 2143 if (qs.get("ran") != null) { 2144 if(qs.get("ran").isURIResource()) { 2145 range = df.getOWLClass(IRI.create(qs.getResource("ran").getURI())); 2146 } else { 2147 logger.warn("Can not resolve complex range for object property " + op); 2148 } 2149 } 2150 result.put(op, range); 2151 } 2152 return result; 2153 } 2154 2155 /* (non-Javadoc) 2156 * @see org.dllearner.core.AbstractReasonerComponent#getDataPropertyDomains() 2157 */ 2158 @Override 2159 public Map<OWLDataProperty, OWLClassExpression> getDataPropertyDomains() { 2160 Map<OWLDataProperty, OWLClassExpression> result = new HashMap<>(); 2161 2162 String query = SPARQLQueryUtils.PREFIXES + "SELECT ?p ?dom WHERE {?p a owl:DatatypeProperty . OPTIONAL{?p rdfs:domain ?dom .}}"; 2163 ResultSet rs = executeSelectQuery(query); 2164 while(rs.hasNext()) { 2165 QuerySolution qs = rs.next(); 2166 OWLDataProperty dp = df.getOWLDataProperty(IRI.create(qs.getResource("p").getURI())); 2167 2168 // default domain is owl:Thing 2169 OWLClassExpression domain = df.getOWLThing(); 2170 if (qs.get("dom") != null) { 2171 if (qs.get("dom").isURIResource()) { 2172 domain = df.getOWLClass(IRI.create(qs.getResource("dom").getURI())); 2173 2174 } else { 2175 logger.warn("Can not resolve complex domain for data property " + dp); 2176 } 2177 } 2178 result.put(dp, domain); 2179 } 2180 return result; 2181 } 2182 2183 2184 2185 2186 public SortedSet<OWLClassExpression> getMeaningfulClasses(OWLClassExpression index, SortedSet<OWLClassExpression> targetClasses) { 2187 String query = buildMeaningfulClassesQuery(index, targetClasses); 2188 if (logger.isDebugEnabled()) logger.debug(sparql_debug, query); 2189 2190 SortedSet<OWLClassExpression> meaningfulClasses = new TreeSet<>(); 2191 ResultSet rs = executeSelectQuery(query); 2192 while(rs.hasNext()) { 2193 QuerySolution qs = rs.next(); 2194 meaningfulClasses.add(df.getOWLClass(IRI.create(qs.getResource("concept").getURI()))); 2195 } 2196 return meaningfulClasses; 2197 } 2198 2199 protected String buildMeaningfulClassesQuery(OWLClassExpression index, SortedSet<OWLClassExpression> targetClasses) { 2200 String query = "SELECT DISTINCT ?concept WHERE {"; 2201 query += converter.convert("?ind", index); 2202 query += "?ind a ?concept . "; 2203 query += "VALUES ?concept {" 2204 + targetClasses.stream().map(ce -> "<" + ce.asOWLClass().toStringID() + ">").collect(Collectors.joining(" ")) 2205 + "}"; 2206 query += "}"; 2207 return query; 2208 } 2209 2210 2211 /** 2212 * Convert a SPARQL resultset into OWL entities based on the given entity type. 2213 * @param entityType the entity type 2214 * @param rs the Jena resultset 2215 * @param var the var name in the resultset 2216 * @return a set of entities of the given entity type 2217 */ 2218 private <E extends OWLEntity> SortedSet<E> asOWLEntities(EntityType<E> entityType, ResultSet rs, String var) { 2219 Collection<IRI> entityIRIs = new HashSet<>(); 2220 while(rs.hasNext()) { 2221 QuerySolution qs = rs.next(); 2222 Resource resource = qs.getResource(var); 2223 if(resource.isURIResource()) { 2224 entityIRIs.add(IRI.create(resource.getURI())); 2225 } 2226 } 2227 return asOWLEntities(entityType, entityIRIs); 2228 } 2229 2230 /** 2231 * Convert a collection of IRIs into OWL entities based on the given entity type. 2232 * @param entityType the entity type 2233 * @param entityIRIs the entity IRIs 2234 * @return a set of entities of the given entity type 2235 */ 2236 private <E extends OWLEntity> SortedSet<E> asOWLEntities(EntityType<E> entityType, Collection<IRI> entityIRIs) { 2237 SortedSet<E> entities = new TreeSet<>(); 2238 for (IRI iri : entityIRIs) { 2239 if(!iri.isReservedVocabulary()) { 2240 entities.add(df.getOWLEntity(entityType, iri)); 2241 } 2242 } 2243 2244 // remove top and bottom entities 2245 entities.remove(df.getOWLThing()); 2246 entities.remove(df.getOWLNothing()); 2247 entities.remove(df.getOWLTopObjectProperty()); 2248 entities.remove(df.getOWLBottomObjectProperty()); 2249 entities.remove(df.getOWLTopDataProperty()); 2250 entities.remove(df.getOWLBottomDataProperty()); 2251 2252 return entities; 2253 } 2254 2255 protected ResultSet executeSelectQuery(String queryString, long timeout, TimeUnit timeoutUnits){ 2256 if (logger.isTraceEnabled()) { 2257 logger.trace("Sending query \n {}", queryString); 2258 } 2259 try(QueryExecution qe = qef.createQueryExecution(queryString)) { 2260 qe.setTimeout(timeout, timeoutUnits); 2261 ResultSet rs = qe.execSelect(); 2262 return ResultSetFactory.copyResults(rs); 2263 } catch (QueryExceptionHTTP e) { 2264 throw new QueryExceptionHTTP("Error sending query \"" + queryString + "\" to endpoint " + qef.getId(), e); 2265 } catch (Exception e) { 2266 throw new RuntimeException("Error sending query \"" + queryString + "\" to endpoint " + qef.getId(), e); 2267 } 2268 } 2269 2270 protected ResultSet executeSelectQuery(String queryString) { 2271 return executeSelectQuery(queryString, -1, TimeUnit.MILLISECONDS); 2272 } 2273 2274 protected boolean executeAskQuery(String queryString){ 2275 if (logger.isTraceEnabled()) logger.trace("Sending query \n {}", queryString); 2276 try(QueryExecution qe = qef.createQueryExecution(queryString)) { 2277 boolean ret = qe.execAsk(); 2278 qe.close(); 2279 return ret; 2280 } catch (QueryExceptionHTTP e) { 2281 throw new QueryExceptionHTTP("Error sending query \"" + queryString + "\" to endpoint " + qef.getId(), e); 2282 } catch (Exception e) { 2283 throw new RuntimeException("Error sending query \"" + queryString + "\" to endpoint " + qef.getId(), e); 2284 } 2285 } 2286 2287 /** 2288 * @return TRUE if the class hierarchy was computed before, otherwise FALSE 2289 */ 2290 public boolean isPrepared(){ 2291 return hierarchy != null; 2292 } 2293 2294 public boolean supportsSPARQL1_1(){ 2295 try { 2296 String query = "SELECT ?s WHERE {?s a <http://foo.org/A> . FILTER NOT EXISTS {?s a <http://foo.org/B>}} LIMIT 1"; 2297 ResultSet rs = executeSelectQuery(query); 2298 return true; 2299 } catch (Exception e) { 2300 logger.error("Endpoint does not support SPARQL 1.1, e.g. FILTER NOT EXISTS", e); 2301 } 2302 return false; 2303 } 2304 2305 /* (non-Javadoc) 2306 * @see org.dllearner.core.BaseReasoner#getBaseURI() 2307 */ 2308 @Override 2309 public String getBaseURI() { 2310 return null; 2311 } 2312 2313 /* (non-Javadoc) 2314 * @see org.dllearner.core.BaseReasoner#getPrefixes() 2315 */ 2316 @Override 2317 public Map<String, String> getPrefixes() { 2318 return null; 2319 } 2320 2321 /* (non-Javadoc) 2322 * @see org.dllearner.core.AbstractReasonerComponent#remainsSatisfiableImpl(org.semanticweb.owlapi.model.OWLAxiom) 2323 */ 2324 @Override 2325 protected boolean remainsSatisfiableImpl(OWLAxiom axiom) throws ReasoningMethodUnsupportedException { 2326 return true; 2327 } 2328 2329 /* (non-Javadoc) 2330 * @see org.dllearner.core.AbstractReasonerComponent#getReasonerType() 2331 */ 2332 @Override 2333 public ReasonerType getReasonerType() { 2334 return ReasonerType.SPARQL_NATIVE; 2335 } 2336 2337 /* (non-Javadoc) 2338 * @see org.dllearner.core.AbstractReasonerComponent#releaseKB() 2339 */ 2340 @Override 2341 public void releaseKB() { 2342 } 2343 2344 public boolean isLaxMode() { 2345 return laxMode; 2346 } 2347 2348 public void setLaxMode(boolean laxMode) { 2349 this.laxMode = laxMode; 2350 } 2351 2352 public boolean isUseGenericSplitsCode() { 2353 return useGenericSplitsCode; 2354 } 2355 2356 public void setUseGenericSplitsCode(boolean useGenericSplitsCode) { 2357 this.useGenericSplitsCode = useGenericSplitsCode; 2358 } 2359 2360 /* (non-Javadoc) 2361 * @see org.dllearner.core.AbstractReasonerComponent#getDatatype(org.semanticweb.owlapi.model.OWLDataProperty) 2362 */ 2363 @Override 2364 public OWLDatatype getDatatype(OWLDataProperty dp) { 2365 // get the range of the property 2366 OWLDataRange range = getRangeImpl(dp); 2367 2368 // if range is a datatype return this 2369 if(range != null && range.isDatatype()) { 2370 return range.asOWLDatatype(); 2371 } 2372 2373 // otherwise, return xsd:string as default datatype 2374 return XSD.STRING; 2375 } 2376 2377 /* (non-Javadoc) 2378 * @see org.dllearner.core.AbstractReasonerComponent#setSynchronized() 2379 */ 2380 @Override @NoConfigOption 2381 public void setSynchronized() { 2382 throw new NotImplementedException("Method setSynchronized() not implemented yet!"); 2383 } 2384 2385 public boolean isUseValueLists() { 2386 return useValueLists; 2387 } 2388 2389 public void setUseValueLists(boolean useValueLists) { 2390 this.useValueLists = useValueLists; 2391 } 2392 2393 public boolean isPreferAsk() { 2394 return preferAsk; 2395 } 2396 2397 public void setPreferAsk(boolean preferAsk) { 2398 this.preferAsk = preferAsk; 2399 } 2400}