001 // This file is part of the Attempto Java Packages. 002 // Copyright 2008-2009, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 003 // 004 // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the 005 // terms of the GNU Lesser General Public License as published by the Free Software Foundation, 006 // either version 3 of the License, or (at your option) any later version. 007 // 008 // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY 009 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 010 // PURPOSE. See the GNU Lesser General Public License for more details. 011 // 012 // You should have received a copy of the GNU Lesser General Public License along with the Attempto 013 // Java Packages. If not, see http://www.gnu.org/licenses/. 014 015 package ch.uzh.ifi.attempto.acewiki.core.ontology; 016 017 import java.io.File; 018 import java.io.FileInputStream; 019 import java.io.FileOutputStream; 020 import java.io.IOException; 021 import java.io.StringWriter; 022 import java.net.URI; 023 import java.net.URISyntaxException; 024 import java.util.ArrayList; 025 import java.util.Collection; 026 import java.util.HashMap; 027 import java.util.HashSet; 028 import java.util.Hashtable; 029 import java.util.List; 030 import java.util.Set; 031 032 import org.coode.owlapi.owlxml.renderer.OWLXMLRenderer; 033 import org.mindswap.pellet.owlapi.Reasoner; 034 import org.semanticweb.owl.apibinding.OWLManager; 035 import org.semanticweb.owl.inference.OWLReasoner; 036 import org.semanticweb.owl.inference.OWLReasonerException; 037 import org.semanticweb.owl.io.StringInputSource; 038 import org.semanticweb.owl.model.OWLClass; 039 import org.semanticweb.owl.model.OWLDescription; 040 import org.semanticweb.owl.model.OWLIndividual; 041 import org.semanticweb.owl.model.OWLObjectOneOf; 042 import org.semanticweb.owl.model.OWLOntology; 043 import org.semanticweb.owl.model.OWLOntologyCreationException; 044 import org.semanticweb.owl.model.OWLOntologySetProvider; 045 import org.semanticweb.owl.model.OWLSubClassAxiom; 046 import org.semanticweb.owl.util.OWLOntologyMerger; 047 048 import uk.ac.manchester.cs.owl.OWLClassImpl; 049 import uk.ac.manchester.cs.owl.OWLDataFactoryImpl; 050 import ch.uzh.ifi.attempto.acewiki.Logger; 051 052 /** 053 * This class represents an AceWiki ontology which consists of ontology element definitions and 054 * of ontological statements. Each ontology element has its own article that consists of ontological 055 * statements. 056 * 057 * @author Tobias Kuhn 058 */ 059 public class Ontology { 060 061 private static final HashMap<String, Ontology> ontologies = new HashMap<String, Ontology>(); 062 063 private ArrayList<OntologyElement> elements = new ArrayList<OntologyElement>(); 064 private Hashtable<String, OntologyElement> wordIndex = new Hashtable<String, OntologyElement>(); 065 private Hashtable<Long, OntologyElement> idIndex = new Hashtable<Long, OntologyElement>(); 066 067 private final String name; 068 private final String baseURI; 069 private long idCount = 0; 070 private long stateID = 0; 071 072 private OWLReasoner reasoner; 073 private OWLOntology differentIndividualsAxiom; 074 075 /** 076 * Creates a new empty ontology with the given name and base URI. 077 * 078 * @param name The name of the ontology. 079 * @param baseURI The base URI that is used to identify the ontology elements. 080 */ 081 private Ontology(String name, String baseURI) { 082 this.name = name.toString(); // null value throws an exception 083 this.baseURI = baseURI; 084 if (baseURI == null) { 085 baseURI = ""; 086 } 087 ontologies.put(name, this); 088 } 089 090 /** 091 * Loads an ontology (or creates an empty ontology if the ontology cannot be found). The complete 092 * URI of the ontology is baseURI + name. 093 * 094 * @param name The name of the ontology. 095 * @param baseURI The base URI that is used to identify the ontology elements. 096 * @return The loaded ontology. 097 */ 098 public synchronized static Ontology loadOntology(String name, String baseURI) { 099 if (ontologies.get(name) != null) { 100 return ontologies.get(name); 101 } 102 Ontology ontology = new Ontology(name, baseURI); 103 ontology.log("loading ontology"); 104 File dataDir = new File("data/" + name); 105 if (dataDir.exists()) { 106 for (File file : dataDir.listFiles()) { 107 try { 108 long id = new Long(file.getName()); 109 ontology.log("reading file: " + file.getName()); 110 FileInputStream in = new FileInputStream(file); 111 byte[] bytes = new byte[in.available()]; 112 in.read(bytes); 113 in.close(); 114 String s = new String(bytes, "UTF-8"); 115 OntologyElement.loadOntologyElement(s, id, ontology); 116 } catch (NumberFormatException ex) { 117 ontology.log("ignoring file: " + file.getName()); 118 } catch (IOException ex) { 119 ontology.log("cannot read file: " + file.getName()); 120 } 121 } 122 } else { 123 ontology.log("no data found; blank ontology is created"); 124 } 125 ontology.refreshReasoner(); 126 return ontology; 127 } 128 129 synchronized void save(OntologyElement oe) { 130 if (!(new File("data")).exists()) (new File("data")).mkdir(); 131 if (!(new File("data/" + name)).exists()) (new File("data/" + name)).mkdir(); 132 133 if (!elements.contains(oe)) { 134 (new File("data/" + name + "/" + oe.getId())).delete(); 135 return; 136 } 137 138 try { 139 FileOutputStream out = new FileOutputStream("data/" + name + "/" + oe.getId()); 140 out.write(oe.serialize().getBytes("UTF-8")); 141 out.close(); 142 } catch (IOException ex) { 143 ex.printStackTrace(); 144 } 145 } 146 147 synchronized void register(OntologyElement element) { 148 if (elements.contains(element)) { 149 log("error: element already registered"); 150 throw new RuntimeException("Registration failed: Element is already registered."); 151 } 152 153 log("register: " + element); 154 stateID++; 155 156 if (element.getId() == -1) { 157 element.setId(nextId()); 158 } 159 elements.add(element); 160 idIndex.put(element.getId(), element); 161 if (element.getId() > idCount) idCount = element.getId(); 162 163 for (String word : element.getWords()) { 164 if (word == null) continue; 165 166 if (wordIndex.get(word) == null) { 167 wordIndex.put(word, element); 168 } else if (wordIndex.get(word) != element) { 169 log("error: word already used"); 170 throw new RuntimeException("Registration failed: The word '" + word + "' is already used."); 171 } 172 } 173 174 if (element instanceof Individual) { 175 updateDifferentIndividualsAxiom(); 176 } 177 178 } 179 180 synchronized void removeFromWordIndex(OntologyElement oe) { 181 for (String word : oe.getWords()) { 182 if (word != null) { 183 wordIndex.remove(word); 184 } 185 } 186 } 187 188 synchronized void addToWordIndex(OntologyElement oe) { 189 for (String word : oe.getWords()) { 190 if (word != null) { 191 if (wordIndex.get(word) == null) { 192 wordIndex.put(word, oe); 193 } else if (wordIndex.get(word) != oe) { 194 throw new RuntimeException("Word update failed: The word '" + word + "' is already used."); 195 } 196 } 197 } 198 } 199 200 /** 201 * Removes the given ontology element from the ontology. 202 * 203 * @param element The ontology element to be removed. 204 */ 205 public synchronized void remove(OntologyElement element) { 206 if (!elements.contains(element)) { 207 log("error: unknown element"); 208 return; 209 } 210 211 log("remove: " + element.getWord()); 212 stateID++; 213 214 for (String word : element.getWords()) { 215 if (word == null) continue; 216 wordIndex.remove(word); 217 } 218 elements.remove(element); 219 idIndex.remove(element.getId()); 220 for (Sentence s : element.getSentences()) { 221 retractSentence(s); 222 } 223 save(element); 224 225 if (element instanceof Individual) { 226 updateDifferentIndividualsAxiom(); 227 } 228 229 } 230 231 /** 232 * Returns all the sentences that use the given word form (by word number) of the given 233 * ontology element. 234 * 235 * @param element The ontology element. 236 * @param wordNumber The word number. 237 * @return A list of all sentence that contain the word. 238 */ 239 public synchronized List<Sentence> getReferences(OntologyElement element, int wordNumber) { 240 List<Sentence> list = new ArrayList<Sentence>(); 241 for (OntologyElement el : elements) { 242 for (Sentence s : el.getSentences()) { 243 if ((wordNumber == -1 && s.contains(element)) || (wordNumber > -1 && s.contains(element, wordNumber))) { 244 list.add(s); 245 } 246 } 247 } 248 return list; 249 } 250 251 /** 252 * Returns all the sentences that use the given ontology element (no matter which word form 253 * is used). 254 * 255 * @param element The ontology element. 256 * @return A list of all sentence that contain the ontology element. 257 */ 258 public synchronized List<Sentence> getReferences(OntologyElement element) { 259 return getReferences(element, -1); 260 } 261 262 /** 263 * Returns the ontology element with the given name, or null if there is no such element. 264 * 265 * @param name The name of the ontology element. 266 * @return The ontology element. 267 */ 268 public OntologyElement get(String name) { 269 return wordIndex.get(name); 270 } 271 272 OntologyElement get(long id) { 273 return idIndex.get(id); 274 } 275 276 /** 277 * Returns all ontology elements. 278 * 279 * @return A collection of all ontology elements. 280 */ 281 public Collection<OntologyElement> getOntologyElements() { 282 return new ArrayList<OntologyElement>(elements); 283 } 284 285 /** 286 * Returns true if the given ontology element is contained by the ontology (identity check). 287 * 288 * @param ontologyElement The ontology element. 289 * @return true if the ontology element is contained by the ontology. 290 */ 291 public boolean contains(OntologyElement ontologyElement) { 292 return elements.contains(ontologyElement); 293 } 294 295 /** 296 * Returns the name of the ontology. 297 * 298 * @return The name of the ontology. 299 */ 300 public String getName() { 301 return name; 302 } 303 304 /** 305 * Returns the URI of the ontology (baseURI + name). 306 * 307 * @return The URI of the ontology. 308 */ 309 public String getURI() { 310 return baseURI + name; 311 } 312 313 /** 314 * Returns the complete ontology as an OWL/XML formatted string. All sentences that participate in 315 * reasoning are included. 316 * 317 * @return A string that contains the complete ontology in OWL/XML format. 318 */ 319 public synchronized String getOWLOntologyAsXML() { 320 StringWriter sw = new StringWriter(); 321 try { 322 OWLXMLRenderer renderer = new OWLXMLRenderer(OWLManager.createOWLOntologyManager()); 323 renderer.render(getOWLOntology(), sw); 324 sw.close(); 325 } catch (Exception ex) { 326 ex.printStackTrace(); 327 } 328 return sw.toString(); 329 } 330 331 /** 332 * Returns an OWL ontology object that contains the complete ontology. More precisely, all sentences 333 * that participate in reasoning are included. 334 * 335 * @return An OWL ontology object containing the complete ontology. 336 */ 337 public synchronized OWLOntology getOWLOntology() { 338 OWLOntologySetProvider setProvider = new OWLOntologySetProvider() { 339 340 public Set<OWLOntology> getOntologies() { 341 HashSet<OWLOntology> ontologies = new HashSet<OWLOntology>(); 342 for (OntologyElement el : elements) { 343 for (Sentence s : el.getSentences()) { 344 if (!s.isReasonerParticipant() || !s.isIntegrated()) continue; 345 346 OWLOntology o = s.getOWLOntology(); 347 if (o != null) ontologies.add(o); 348 } 349 } 350 ontologies.add(differentIndividualsAxiom); 351 return ontologies; 352 } 353 354 }; 355 356 URI uri = null; 357 try { 358 uri = new URI("http://attempto.ifi.uzh.ch/default/"); 359 uri = new URI(getURI()); 360 } catch (URISyntaxException ex) { 361 ex.printStackTrace(); 362 } 363 364 OWLOntology owlOntology = null; 365 try { 366 OWLOntologyMerger ontologyMerger = new OWLOntologyMerger(setProvider); 367 owlOntology = ontologyMerger.createMergedOntology(OWLManager.createOWLOntologyManager(), uri); 368 } catch (Exception ex) { 369 ex.printStackTrace(); 370 } 371 return owlOntology; 372 } 373 374 private synchronized void refreshReasoner() { 375 log("refresh reasoner"); 376 377 if (reasoner == null) { 378 // for Pellet: 379 reasoner = new Reasoner(OWLManager.createOWLOntologyManager()); 380 // for HermiT: (doesn't work for some reason...) 381 //reasoner = (new ReasonerFactory()).createReasoner(OWLManager.createOWLOntologyManager()); 382 } else { 383 clearOntologies(); 384 } 385 updateDifferentIndividualsAxiom(); 386 387 log("reasoner: loading statements"); 388 HashSet<OWLOntology> ontologies = new HashSet<OWLOntology>(); 389 390 for (OntologyElement oe : elements) { 391 for (Sentence s : oe.getSentences()) { 392 if (s.isReasonerParticipant() && s.isIntegrated()) { 393 OWLOntology o = s.getOWLOntology(); 394 if (o != null) ontologies.add(o); 395 } 396 } 397 } 398 try { 399 reasoner.loadOntologies(ontologies); 400 } catch (OWLReasonerException ex) { 401 ex.printStackTrace(); 402 } 403 log("reasoner: statements loaded"); 404 } 405 406 /** 407 * Refreshes the given ontology element. All sentences that use the ontology element are 408 * updated. 409 * 410 * @param element The ontology element to be refreshed. 411 */ 412 synchronized void refresh(OntologyElement element) { 413 for (Sentence s : getReferences(element)) { 414 if (s.isIntegrated()) { 415 retractSentence(s); 416 s.parse(); 417 commitSentence(s); 418 } else { 419 s.parse(); 420 } 421 } 422 save(element); 423 } 424 425 /** 426 * Uses the ontology manager to read an OWL ontology from a string (that contains an ontology 427 * in OWL-XML format). 428 * 429 * @param owlxml The serialized OWL-XML ontology. 430 * @return The OWL ontology object. 431 * @throws OWLOntologyCreationException If the string cannot be parsed. 432 */ 433 public OWLOntology readOWLOntology(String owlxml) throws OWLOntologyCreationException { 434 return OWLManager.createOWLOntologyManager().loadOntology(new StringInputSource(owlxml)); 435 } 436 437 /** 438 * Commits the sentence. This means that it is added to the reasoner. An integer value is returned 439 * that denotes the success or failure of the operation: 440 * 0 is returned if the operation succeeds. 441 * 1 is returned if it fails because the sentence introduces inconsistency into the knowledge base. 442 * 2 is returned if the reasoner runs out of memory (this can occur sometimes with large ontologies). 443 * 444 * @param sentence The sentence to be commited. 445 * @return An integer value denoting the success/failure of the operation. 446 */ 447 synchronized int commitSentence(Sentence sentence) { 448 if (reasoner == null || sentence == null || sentence.isIntegrated()) return 0; 449 450 if (!sentence.isReasonerParticipant()) { 451 sentence.setIntegrated(true); 452 return 0; 453 } 454 455 log("commit sentence"); 456 457 try { 458 loadOntology(sentence.getOWLOntology()); 459 } catch (OutOfMemoryError err) { 460 log("error: out of memory"); 461 System.gc(); 462 refreshReasoner(); 463 return 2; 464 } 465 466 log("check for consistency"); 467 if (isConsistent()) { 468 log("consistent!"); 469 sentence.setIntegrated(true); 470 stateID++; 471 return 0; 472 } else { 473 log("not consistent!"); 474 unloadOntology(sentence.getOWLOntology()); 475 return 1; 476 } 477 } 478 479 /** 480 * Retracts the sentence. This means that the sentence is removed from the reasoner. 481 * 482 * @param sentence The sentence to be retracted. 483 */ 484 synchronized void retractSentence(Sentence sentence) { 485 if ( 486 reasoner == null || 487 sentence == null || 488 !sentence.isIntegrated() || 489 !sentence.isReasonerParticipant() 490 ) return; 491 492 log("retract sentence"); 493 stateID++; 494 unloadOntology(sentence.getOWLOntology()); 495 sentence.setIntegrated(false); 496 } 497 498 void log(String text) { 499 Logger.log(name, "onto", 0, "onto", text); 500 } 501 502 /** 503 * Updates the axiom that states that all named individuals are different. Thus, unique 504 * name assumption is applied. 505 */ 506 private synchronized void updateDifferentIndividualsAxiom() { 507 if (reasoner == null) return; 508 509 if (differentIndividualsAxiom != null) { 510 unloadOntology(differentIndividualsAxiom); 511 } 512 513 String owlString = 514 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" + 515 "<Ontology " + 516 "xml:base=\"http://www.w3.org/2006/12/owl11-xml#\" " + 517 "xmlns=\"http://www.w3.org/2006/12/owl11-xml#\" " + 518 "URI=\"" + getURI() + "/different_individuals/" + stateID + "\">\n" + 519 "\t<DifferentIndividuals>\n"; 520 for (OntologyElement oe : getOntologyElements()) { 521 if (oe instanceof Individual) { 522 String word = ((Individual) oe).getWord(); 523 if (word.startsWith("the ")) word = word.substring(4); 524 owlString += "\t\t<Individual URI=\"" + ((Individual) oe).getURI() + "\" />\n"; 525 } 526 } 527 owlString += 528 "\t</DifferentIndividuals>\n" + 529 "</Ontology>"; 530 531 try { 532 differentIndividualsAxiom = readOWLOntology(owlString); 533 loadOntology(differentIndividualsAxiom); 534 } catch (OWLOntologyCreationException ex) { 535 log("unexpected error"); 536 ex.printStackTrace(); 537 } 538 } 539 540 /** 541 * Returns all concepts the given individual belongs to. The reasoner is used for this. 542 * 543 * @param ind The individual. 544 * @return A list of all concepts of the individual. 545 * @see Individual#getConcepts() 546 */ 547 public synchronized List<Concept> getConcepts(Individual ind) { 548 OWLIndividual owlIndividual = (new OWLDataFactoryImpl()).getOWLIndividual(ind.getURI()); 549 ArrayList<Concept> concepts = new ArrayList<Concept>(); 550 try { 551 Set<Set<OWLClass>> owlClasses = reasoner.getTypes(owlIndividual, false); 552 for (Set<OWLClass> s : owlClasses) { 553 for (OWLClass oc : s) { 554 if (oc.isOWLThing() || oc.isOWLNothing()) continue; 555 String conceptURI = oc.getURI().toASCIIString(); 556 String conceptName = conceptURI.substring(conceptURI.indexOf("#") + 1); 557 concepts.add((Concept) get(conceptName)); 558 } 559 } 560 } catch (OWLReasonerException ex) { 561 ex.printStackTrace(); 562 } 563 return concepts; 564 } 565 566 /** 567 * Returns all individuals that belong to the given concept. The reasoner is used for this. 568 * 569 * @param concept The concept. 570 * @return A list of all individuals of the concept. 571 * @see Concept#getIndividuals() 572 */ 573 public synchronized List<Individual> getIndividuals(Concept concept) { 574 OWLClass owlClass = new OWLClassImpl(new OWLDataFactoryImpl(), concept.getURI()); 575 ArrayList<Individual> individuals = new ArrayList<Individual>(); 576 try { 577 Set<OWLIndividual> owlIndividuals = reasoner.getIndividuals(owlClass, false); 578 for (OWLIndividual oi : owlIndividuals) { 579 String indURI = oi.getURI().toASCIIString(); 580 String indName = indURI.substring(indURI.indexOf("#") + 1); 581 if (!indName.matches("I[0-9]+")) { 582 individuals.add((Individual) get(indName)); 583 } 584 } 585 } catch (OWLReasonerException ex) { 586 ex.printStackTrace(); 587 } 588 return individuals; 589 } 590 591 /** 592 * Returns all super-concepts of the given concept. The reasoner is used for this. 593 * 594 * @param concept The concept for which all super-concepts should be returned. 595 * @return A list of all super-concepts. 596 * @see Concept#getSuperConcepts() 597 */ 598 public synchronized List<Concept> getSuperConcepts(Concept concept) { 599 OWLClass owlClass = new OWLClassImpl(new OWLDataFactoryImpl(), concept.getURI()); 600 ArrayList<Concept> concepts = new ArrayList<Concept>(); 601 try { 602 Set<Set<OWLClass>> owlClasses = reasoner.getAncestorClasses(owlClass); 603 for (Set<OWLClass> s : owlClasses) { 604 for (OWLClass oc : s) { 605 if (oc.isOWLThing() || oc.isOWLNothing()) continue; 606 String conceptURI = oc.getURI().toASCIIString(); 607 String conceptName = conceptURI.substring(conceptURI.indexOf("#") + 1); 608 concepts.add((Concept) get(conceptName)); 609 } 610 } 611 } catch (OWLReasonerException ex) { 612 ex.printStackTrace(); 613 } 614 return concepts; 615 } 616 617 /** 618 * Returns all the sub-concepts of the given concept. The reasoner is used for this. 619 * 620 * @param concept The concept for which all sub-concepts should be returned. 621 * @return A list of all sub-concepts. 622 * @see Concept#getSubConcepts() 623 */ 624 public synchronized List<Concept> getSubConcepts(Concept concept) { 625 OWLClass owlClass = new OWLClassImpl(new OWLDataFactoryImpl(), concept.getURI()); 626 ArrayList<Concept> concepts = new ArrayList<Concept>(); 627 try { 628 Set<Set<OWLClass>> owlClasses = reasoner.getDescendantClasses(owlClass); 629 for (Set<OWLClass> s : owlClasses) { 630 for (OWLClass oc : s) { 631 if (oc.isOWLThing() || oc.isOWLNothing()) continue; 632 String conceptURI = oc.getURI().toASCIIString(); 633 String conceptName = conceptURI.substring(conceptURI.indexOf("#") + 1); 634 concepts.add((Concept) get(conceptName)); 635 } 636 } 637 } catch (OWLReasonerException ex) { 638 ex.printStackTrace(); 639 } 640 return concepts; 641 } 642 643 /** 644 * Returns a list of ontology elements that answer the given question. The reasoner is used 645 * for this. In the case the sentence has the form "what is (Individual)?" then the answer 646 * contains all concepts the individual belongs to. Otherwise, the question is 647 * processed as a "DL Query" that describes a concept. In this case, the answer consists 648 * of all individuals that belong to the concept. The null value is returned if the 649 * sentence is not a question. 650 * 651 * @param questionSentence The question sentence that should be answered. 652 * @return A list of ontology elements that are the answer for the question. 653 * @see Sentence#getAnswer() 654 */ 655 public synchronized List<OntologyElement> getAnswer(Sentence questionSentence) { 656 if (!questionSentence.isQuestion()) return null; 657 658 OWLOntology o = questionSentence.getOWLOntology(); 659 if (o == null || o.isEmpty()) return null; 660 661 ArrayList<OntologyElement> answer = new ArrayList<OntologyElement>(); 662 663 try { 664 OWLSubClassAxiom answerOWLAxiom = (OWLSubClassAxiom) o.getAxioms().iterator().next(); 665 OWLDescription answerOWLClass = answerOWLAxiom.getSubClass(); 666 667 if (answerOWLClass instanceof OWLObjectOneOf && ((OWLObjectOneOf) answerOWLClass).getIndividuals().size() == 1) { 668 OWLIndividual oi = ((OWLObjectOneOf) answerOWLClass).getIndividuals().iterator().next(); 669 Set<Set<OWLClass>> owlClasses = reasoner.getTypes(oi, false); 670 for (Set<OWLClass> classSet : owlClasses) { 671 for (OWLClass owlClass : classSet) { 672 String classURI = owlClass.getURI().toASCIIString(); 673 String className = classURI.substring(classURI.indexOf("#") + 1); 674 if (!owlClass.isOWLThing() && !owlClass.isOWLNothing()) { 675 answer.add(get(className)); 676 } 677 } 678 } 679 } else { 680 Set<OWLIndividual> owlIndividuals = reasoner.getIndividuals(answerOWLClass, false); 681 for (OWLIndividual oi : owlIndividuals) { 682 String indURI = oi.getURI().toASCIIString(); 683 String indName = indURI.substring(indURI.indexOf("#") + 1); 684 if (!indName.matches("I[0-9]+")) { 685 answer.add(get(indName)); 686 } 687 } 688 } 689 } catch (Exception ex) { 690 ex.printStackTrace(); 691 } 692 return answer; 693 } 694 695 /** 696 * Returns true if the ontology is consistent. If nothing goes wrong, this should always return true. 697 * The reasoner is used for this. 698 * 699 * @return true if the ontology is consistent. 700 */ 701 public synchronized boolean isConsistent() { 702 boolean isConsistent = true; 703 try { 704 isConsistent = reasoner.isSatisfiable((new OWLDataFactoryImpl()).getOWLThing()); 705 } catch (OWLReasonerException ex) { 706 ex.printStackTrace(); 707 } 708 return isConsistent; 709 } 710 711 /** 712 * Checks if the given concept is satisfiable. The reasoner is used for this. 713 * 714 * @param concept The concept. 715 * @return true if the concept is satisfiable. 716 */ 717 public synchronized boolean isSatisfiable(Concept concept) { 718 OWLClass owlClass = new OWLClassImpl(new OWLDataFactoryImpl(), concept.getURI()); 719 boolean isSatisfiable = false; 720 try { 721 isSatisfiable = (!reasoner.isDefined(owlClass) || reasoner.isSatisfiable(owlClass)); 722 } catch (OWLReasonerException ex) { 723 ex.printStackTrace(); 724 } 725 return isSatisfiable; 726 } 727 728 private void loadOntology(OWLOntology ontology) { 729 if (ontology == null) return; 730 731 HashSet<OWLOntology> ontologies = new HashSet<OWLOntology>(); 732 ontologies.add(ontology); 733 try { 734 reasoner.loadOntologies(ontologies); 735 } catch (OWLReasonerException ex) { 736 ex.printStackTrace(); 737 } 738 } 739 740 private void unloadOntology(OWLOntology ontology) { 741 if (ontology == null) return; 742 743 HashSet<OWLOntology> ontologies = new HashSet<OWLOntology>(); 744 ontologies.add(ontology); 745 try { 746 reasoner.unloadOntologies(ontologies); 747 } catch (OWLReasonerException ex) { 748 ex.printStackTrace(); 749 } 750 } 751 752 private void clearOntologies() { 753 try { 754 reasoner.clearOntologies(); 755 } catch (OWLReasonerException ex) { 756 ex.printStackTrace(); 757 } 758 } 759 760 private long nextId() { 761 return ++idCount; 762 } 763 764 /** 765 * Returns the state id of the ontology. This id increases each time the ontology changes (more precisely: 766 * each time the part of the ontology that participates in reasoning changes). This id is used to find out 767 * whether cached information is still valid or has to be recalculated. 768 * 769 * @return The state id of the ontology. 770 */ 771 long getStateID() { 772 return stateID; 773 } 774 775 }