001 /**
002 * Copyright (C) 2007-2008, 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 *
019 */
020
021 package org.dllearner.tools.ore;
022
023 import java.net.URI;
024 import java.util.Collection;
025 import java.util.Collections;
026 import java.util.HashSet;
027 import java.util.LinkedList;
028 import java.util.List;
029 import java.util.Set;
030
031 import org.dllearner.core.ReasonerComponent;
032 import org.dllearner.core.owl.Description;
033 import org.dllearner.core.owl.Individual;
034 import org.dllearner.core.owl.NamedClass;
035 import org.dllearner.core.owl.Negation;
036 import org.dllearner.core.owl.ObjectProperty;
037 import org.dllearner.core.owl.ObjectPropertyAssertion;
038 import org.dllearner.core.owl.ObjectQuantorRestriction;
039 import org.dllearner.reasoning.OWLAPIReasoner;
040 import org.dllearner.utilities.owl.OWLAPIDescriptionConvertVisitor;
041 import org.mindswap.pellet.owlapi.Reasoner;
042 import org.semanticweb.owl.apibinding.OWLManager;
043 import org.semanticweb.owl.debugging.BlackBoxOWLDebugger;
044 import org.semanticweb.owl.debugging.OWLDebugger;
045 import org.semanticweb.owl.inference.OWLReasonerException;
046 import org.semanticweb.owl.inference.OWLSatisfiabilityChecker;
047 import org.semanticweb.owl.io.RDFXMLOntologyFormat;
048 import org.semanticweb.owl.model.AddAxiom;
049 import org.semanticweb.owl.model.OWLAxiom;
050 import org.semanticweb.owl.model.OWLClass;
051 import org.semanticweb.owl.model.OWLClassAssertionAxiom;
052 import org.semanticweb.owl.model.OWLDataFactory;
053 import org.semanticweb.owl.model.OWLDescription;
054 import org.semanticweb.owl.model.OWLEquivalentClassesAxiom;
055 import org.semanticweb.owl.model.OWLException;
056 import org.semanticweb.owl.model.OWLIndividual;
057 import org.semanticweb.owl.model.OWLInverseObjectPropertiesAxiom;
058 import org.semanticweb.owl.model.OWLObjectProperty;
059 import org.semanticweb.owl.model.OWLObjectPropertyAssertionAxiom;
060 import org.semanticweb.owl.model.OWLObjectPropertyExpression;
061 import org.semanticweb.owl.model.OWLOntology;
062 import org.semanticweb.owl.model.OWLOntologyChange;
063 import org.semanticweb.owl.model.OWLOntologyChangeException;
064 import org.semanticweb.owl.model.OWLOntologyManager;
065 import org.semanticweb.owl.model.OWLOntologyStorageException;
066 import org.semanticweb.owl.model.RemoveAxiom;
067 import org.semanticweb.owl.model.UnknownOWLOntologyException;
068 import org.semanticweb.owl.util.OWLEntityRemover;
069
070 /**
071 * This class provides several methods to modify the ontology by using OWL-API.
072 * @author Lorenz Buehmann
073 *
074 */
075 public class OntologyModifier {
076
077 private OWLOntology ontology;
078 private ReasonerComponent reasoner;
079 private OWLDataFactory factory;
080 private OWLOntologyManager manager;
081 private ReasonerComponent rs;
082
083
084 public OntologyModifier(ReasonerComponent reasoner, ReasonerComponent rs){
085 this.reasoner = reasoner;
086 this.manager = OWLManager.createOWLOntologyManager();
087 this.factory = manager.getOWLDataFactory();
088 this.ontology = ((OWLAPIReasoner)reasoner).getOWLAPIOntologies().get(0);
089 this.rs = rs;
090 }
091
092 /**
093 * Adds an EquivalentClassesAxiom axiom to the ontology.
094 * @param newDesc new axiom to add
095 * @param oldDesc old description
096 */
097 public OWLOntologyChange addAxiomToOWL(Description newDesc, Description oldDesc){
098
099
100 OWLDescription newConceptOWLAPI = OWLAPIDescriptionConvertVisitor.getOWLDescription(newDesc);
101 OWLDescription oldConceptOWLAPI = OWLAPIDescriptionConvertVisitor.getOWLDescription(oldDesc);
102
103 Set<OWLDescription> ds = new HashSet<OWLDescription>();
104 ds.add(newConceptOWLAPI);
105 ds.add(oldConceptOWLAPI);
106
107 OWLAxiom axiomOWLAPI = factory.getOWLEquivalentClassesAxiom(ds);
108
109
110 AddAxiom axiom = new AddAxiom(ontology, axiomOWLAPI);
111 try {
112 manager.applyChange(axiom);
113 } catch (OWLOntologyChangeException e) {
114 // TODO Auto-generated catch block
115 e.printStackTrace();
116 }
117 return axiom;
118
119 }
120
121 /**
122 * Rewrite ontology by replacing old class with new learned class description.
123 * @param newDesc
124 * @param oldClass
125 */
126 public List<OWLOntologyChange> rewriteClassDescription(Description newDesc, Description oldClass){
127 OWLDescription newClassDesc = OWLAPIDescriptionConvertVisitor.getOWLDescription(newDesc);
128 // OWLDescription oldClassDesc = OWLAPIDescriptionConvertVisitor.getOWLDescription(oldClass);
129
130 OWLClass oldClassOWL = factory.getOWLClass(URI.create(oldClass.toString()));
131
132 Set<OWLEquivalentClassesAxiom> equivalenceAxioms = ontology.getEquivalentClassesAxioms(oldClassOWL);
133
134 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
135
136 //add old equivalence axioms to changes
137 for(OWLEquivalentClassesAxiom eqAxiom : equivalenceAxioms){
138 changes.add(new RemoveAxiom(ontology, eqAxiom));
139
140 }
141
142 //create and add new equivalence axiom to changes
143
144 Set<OWLDescription> newEquivalenceDesc = new HashSet<OWLDescription>();
145 newEquivalenceDesc.add(newClassDesc);
146 newEquivalenceDesc.add(oldClassOWL);
147 OWLAxiom equivalenceAxiom = factory.getOWLEquivalentClassesAxiom(newEquivalenceDesc);
148 AddAxiom addAxiom = new AddAxiom(ontology, equivalenceAxiom);
149 changes.add(addAxiom);
150
151 //apply changes to ontology
152 try {
153 manager.applyChanges(changes);
154 } catch (OWLOntologyChangeException e) {
155 System.err.println("Error: rewriting class description failed");
156 e.printStackTrace();
157 }
158
159 return changes;
160
161 }
162
163 /**
164 * Saves the ontology as RDF-file.
165 */
166 public void saveOntology(){
167
168
169
170 URI physicalURI2 = URI.create("file:/tmp/MyOnt2.owl");
171
172 try {
173 manager.saveOntology(ontology, new RDFXMLOntologyFormat(), physicalURI2);
174 } catch (UnknownOWLOntologyException e) {
175 // TODO Auto-generated catch block
176 e.printStackTrace();
177 } catch (OWLOntologyStorageException e) {
178 // TODO Auto-generated catch block
179 e.printStackTrace();
180 }
181
182 }
183 /**
184 * Deletes the complete individual from the ontology.
185 * @param ind the individual to delete
186 */
187 public List<OWLOntologyChange> deleteIndividual(Individual ind){
188
189 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
190
191 OWLIndividual individualOWLAPI = factory.getOWLIndividual(URI.create(ind.getName()));
192
193 OWLEntityRemover remover = new OWLEntityRemover(manager, Collections.singleton(ontology));
194
195 individualOWLAPI.accept(remover);
196 changes.addAll(remover.getChanges());
197 try {
198 manager.applyChanges(changes);
199 saveOntology();
200 return changes;
201 } catch (OWLOntologyChangeException e) {
202 // TODO Auto-generated catch block
203 e.printStackTrace();
204 }
205
206
207
208 return null;
209
210 }
211 /**
212 * Removes a classAssertion.
213 * @param ind the individual which has to removed from class
214 * @param desc the class to which the individual is asserted
215 * @return changes that have been done
216 */
217 public List<OWLOntologyChange> removeClassAssertion(Individual ind, Description desc){
218
219 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
220
221 OWLIndividual individualOWLAPI = factory.getOWLIndividual(URI.create(ind.getName()));
222 OWLDescription owlDesc = OWLAPIDescriptionConvertVisitor.getOWLDescription(desc);
223
224 OWLClassAssertionAxiom owlCl = factory.getOWLClassAssertionAxiom(individualOWLAPI, owlDesc);
225
226 RemoveAxiom rm = new RemoveAxiom(ontology, owlCl);
227 changes.add(rm);
228 try {
229 manager.applyChange(rm);
230 return changes;
231 } catch (OWLOntologyChangeException e) {
232 // TODO Auto-generated catch block
233 e.printStackTrace();
234 }
235
236
237
238 return null;
239 }
240
241 /**
242 * Adds a classAssertion.
243 * @param ind the individual which has to be asserted to class
244 * @param desc the class to which the individual has to be asserted
245 * @return changes that have been done
246 */
247 public List<OWLOntologyChange> addClassAssertion(Individual ind, Description desc){
248
249 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
250
251 OWLIndividual individualOWLAPI = factory.getOWLIndividual(URI.create(ind.getName()));
252 OWLDescription owlDesc = OWLAPIDescriptionConvertVisitor.getOWLDescription(desc);
253
254 OWLClassAssertionAxiom owlCl = factory.getOWLClassAssertionAxiom(individualOWLAPI, owlDesc);
255
256 AddAxiom am = new AddAxiom(ontology, owlCl);
257
258
259 changes.add(am);
260 try {
261 manager.applyChange(am);
262 return changes;
263 } catch (OWLOntologyChangeException e) {
264 // TODO Auto-generated catch block
265 e.printStackTrace();
266 }
267
268
269
270 return null;
271
272 }
273
274 /**
275 * Removes classAssertion between individual to a old class, and creates a new classAssertion.
276 * @param ind individual which has to be moved
277 * @param oldClass class where individual is asserted before
278 * @param newClass class where individual is moved to
279 * @return changes that have been done
280 */
281 public List<OWLOntologyChange> moveIndividual(Individual ind, Description oldClass, Description newClass){
282
283 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
284
285 OWLIndividual individualOWLAPI = factory.getOWLIndividual(URI.create(ind.getName()));
286
287 //Loeschen
288 OWLDescription oldDesc = OWLAPIDescriptionConvertVisitor.getOWLDescription(oldClass);
289 OWLClassAssertionAxiom owlCl = factory.getOWLClassAssertionAxiom(individualOWLAPI, oldDesc);
290 RemoveAxiom rem = new RemoveAxiom(ontology, owlCl);
291 changes.add(rem);
292
293 //Hinzufuegen
294
295 OWLDescription newDesc = OWLAPIDescriptionConvertVisitor.getOWLDescription(newClass);
296 OWLAxiom axiomOWLAPI = factory.getOWLClassAssertionAxiom(individualOWLAPI, newDesc);
297 AddAxiom axiom = new AddAxiom(ontology, axiomOWLAPI);
298 changes.add(axiom);
299
300
301 try {
302 manager.applyChanges(changes);
303 saveOntology();
304
305 return changes;
306 } catch (OWLOntologyChangeException e) {
307 // TODO Auto-generated catch block
308 e.printStackTrace();
309 }
310
311 return null;
312
313 }
314
315 /**
316 * Removes all object property assertions with role, and it's inverse.
317 * @param ind the individual which property has to be removed
318 * @param objSome the property which has to be removed
319 * @return changes that have been done
320 */
321 public List<OWLOntologyChange> deleteObjectProperty(Individual ind, ObjectQuantorRestriction objSome){
322
323 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
324
325 OWLIndividual individualOWLAPI = factory.getOWLIndividual(URI.create(ind.getName()));
326 OWLObjectProperty propertyOWLAPI = factory.getOWLObjectProperty(URI.create(objSome.getRole().getName()));
327
328 Set<OWLObjectPropertyAssertionAxiom> properties = ontology.getObjectPropertyAssertionAxioms(individualOWLAPI);
329 Set<OWLInverseObjectPropertiesAxiom> invProperties = ontology.getInverseObjectPropertyAxioms(propertyOWLAPI);
330
331 OWLObjectPropertyExpression invProperty = null;
332
333 for(OWLInverseObjectPropertiesAxiom inv : invProperties){
334 if(propertyOWLAPI.equals(inv.getSecondProperty())){
335 invProperty = inv.getFirstProperty();
336 } else{
337 invProperty = inv.getSecondProperty();
338 }
339 }
340
341
342 List<RemoveAxiom> removeList = new LinkedList<RemoveAxiom>();
343
344 for(OWLObjectPropertyAssertionAxiom o :properties){
345 if((o.getProperty().equals(propertyOWLAPI)) && (o.getSubject().equals(individualOWLAPI))){
346 removeList.add(new RemoveAxiom(ontology, o));
347 }
348 if(invProperty != null){
349 for(OWLObjectPropertyAssertionAxiom ob :ontology.getObjectPropertyAssertionAxioms(o.getObject())){
350 if(ob.getProperty().equals(invProperty) && ob.getObject().equals(individualOWLAPI)){
351 removeList.add(new RemoveAxiom(ontology, ob));
352 }
353 }
354 }
355
356
357 }
358 changes.addAll(removeList);
359
360 try {
361 manager.applyChanges(removeList);
362 return changes;
363 } catch (OWLOntologyChangeException e) {
364 // TODO Auto-generated catch block
365 e.printStackTrace();
366 }
367
368 return null;
369
370 }
371
372
373 /**
374 * Removes an object property assertion from the ontology if the axiom is existing in the ontology.
375 * @param subject
376 * @param objSome
377 * @param object
378 * @return changes that have been done
379 */
380 public List<OWLOntologyChange> removeObjectPropertyAssertion(Individual subject, ObjectQuantorRestriction objSome, Individual object){
381
382 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
383
384 OWLIndividual subjectOWLAPI = factory.getOWLIndividual(URI.create(subject.getName()));
385 OWLIndividual objectOWLAPI = factory.getOWLIndividual(URI.create(object.getName()));
386 OWLObjectProperty propertyOWLAPI = factory.getOWLObjectProperty(URI.create(objSome.getRole().getName()));
387
388 Set<OWLObjectPropertyAssertionAxiom> properties = ontology.getObjectPropertyAssertionAxioms(subjectOWLAPI);
389
390 RemoveAxiom remove = null;
391 for(OWLObjectPropertyAssertionAxiom o :properties){
392 if((o.getProperty().equals(propertyOWLAPI)) && (o.getSubject().equals(subjectOWLAPI)) && (o.getObject().equals(objectOWLAPI))){
393 remove = new RemoveAxiom(ontology, o);
394 }
395 }
396
397
398
399 changes.add(remove);
400
401 try {
402 if(remove != null){
403 manager.applyChange(remove);
404
405 }
406 return changes;
407 } catch (OWLOntologyChangeException e) {
408 // TODO Auto-generated catch block
409 e.printStackTrace();
410 }
411
412 return null;
413
414 }
415
416 /**
417 * Adds an object property assertion to the ontology.
418 * @param subInd the individual which is subject in the objectProperty
419 * @param objSome the property which has to be added to subject
420 * @param objInd the individual which is object in the objectProperty
421 * @return changes that have been done
422 */
423 public List<OWLOntologyChange> addObjectProperty(Individual subInd, ObjectQuantorRestriction objSome, Individual objInd){
424
425 List<OWLOntologyChange> changes = new LinkedList<OWLOntologyChange>();
426
427 OWLIndividual subjectOWLAPI = factory.getOWLIndividual(URI.create(subInd.getName()));
428 OWLIndividual objectOWLAPI = factory.getOWLIndividual(URI.create(objInd.getName()));
429 OWLObjectProperty propertyOWLAPI = factory.getOWLObjectProperty(URI.create(objSome.getRole().getName()));
430
431 OWLObjectPropertyAssertionAxiom objAssertion = factory.getOWLObjectPropertyAssertionAxiom(subjectOWLAPI, propertyOWLAPI, objectOWLAPI);
432 AddAxiom axiom = new AddAxiom(ontology, objAssertion);
433 changes.add(axiom);
434 try {
435 manager.applyChange(axiom);
436 return changes;
437 } catch (OWLOntologyChangeException e) {
438 // TODO Auto-generated catch block
439 e.printStackTrace();
440 }
441
442 return null;
443 }
444
445
446
447 /**
448 * undo changes of type {@link OWLOntologyChange}.
449 * @param changes
450 */
451 public void undoChanges(Collection<OWLOntologyChange> changes){
452
453
454 for(OWLOntologyChange change : changes){
455 if(change instanceof RemoveAxiom){
456 AddAxiom add = new AddAxiom(ontology, change.getAxiom());
457 try {
458 manager.applyChange(add);
459 } catch (OWLOntologyChangeException e) {
460 e.printStackTrace();
461 }
462 } else if(change instanceof AddAxiom){
463 RemoveAxiom remove = new RemoveAxiom(ontology, change.getAxiom());
464 try {
465 manager.applyChange(remove);
466 } catch (OWLOntologyChangeException e) {
467 e.printStackTrace();
468 }
469 }
470
471 }
472
473
474 }
475
476 /**
477 * checks whether desc1 and desc2 are disjoint.
478 * @param desc1 class 1
479 * @param desc2 class 2
480 */
481 public boolean isComplement(Description desc1, Description desc2){
482
483 OWLClass owlClass1 = OWLAPIDescriptionConvertVisitor.getOWLDescription(desc1).asOWLClass();
484 OWLClass owlClass2 = OWLAPIDescriptionConvertVisitor.getOWLDescription(desc2).asOWLClass();
485
486 //superclasses and class1
487 // Set<OWLDescription> superClasses1 = owlClass1.getSuperClasses(ontology);
488 Set<OWLDescription> superClasses1 = new HashSet<OWLDescription>();
489 for(Description d1 : rs.getSuperClasses(desc1)){
490 superClasses1.add(OWLAPIDescriptionConvertVisitor.getOWLDescription(d1));
491 }
492 superClasses1.add(owlClass1);
493 // System.out.println(desc1 + "::" + superClasses1);
494
495 //superclasses and class2
496 // Set<OWLDescription> superClasses2 = owlClass2.getSuperClasses(ontology);
497 Set<OWLDescription> superClasses2 = new HashSet<OWLDescription>();
498 for(Description d2 : rs.getSuperClasses(desc2)){
499 superClasses2.add(OWLAPIDescriptionConvertVisitor.getOWLDescription(d2));
500 }
501 superClasses2.add(owlClass2);
502
503 // System.out.println("superklassen von " + desc2 + " sind: " + superClasses2);
504 for(OWLDescription o1 : superClasses1){
505
506 OWLDescription negO1 = OWLAPIDescriptionConvertVisitor.getOWLDescription(new Negation(new NamedClass(o1.toString())));
507 for(OWLDescription o2 : superClasses2){
508
509 OWLDescription negO2 = OWLAPIDescriptionConvertVisitor.getOWLDescription(new Negation(new NamedClass(o2.toString())));
510
511 if(ontology.containsAxiom(factory.getOWLDisjointClassesAxiom(o1, o2))){
512 return true;
513 }else if(ontology.containsAxiom(factory.getOWLDisjointClassesAxiom(o2, o1))){
514 return true;
515 }else if(ontology.containsAxiom(factory.getOWLEquivalentClassesAxiom(o1, negO2))){
516 return true;
517 }else if(ontology.containsAxiom(factory.getOWLEquivalentClassesAxiom(o2, negO1))){
518 return true;
519 }
520 }
521
522 }
523
524 // for(OWLAxiom ax : ontology.getAxioms()){
525 //
526 // for(OWLDescription o1 : superClasses1){
527 //
528 // OWLDescription negO1 = OWLAPIDescriptionConvertVisitor.getOWLDescription(new Negation(new NamedClass(o1.toString())));
529 // for(OWLDescription o2 : superClasses2){
530 //
531 // OWLDescription negO2 = OWLAPIDescriptionConvertVisitor.getOWLDescription(new Negation(new NamedClass(o2.toString())));
532 //
533 // if(ax.toString().equals(factory.getOWLDisjointClassesAxiom(o1, o2).toString())){
534 // return true;
535 // }else if(ax.toString().equals(factory.getOWLDisjointClassesAxiom(o2, o1).toString())){
536 // return true;
537 // }else if(ax.toString().equals(factory.getOWLEquivalentClassesAxiom(o1, negO2).toString())){
538 // return true;
539 // }else if(ax.toString().equals(factory.getOWLEquivalentClassesAxiom(o2, negO1).toString())){
540 // return true;
541 // }
542 // }
543 //
544 // }
545 // }
546
547
548
549 return false;
550
551 }
552
553 /**
554 * Returns object properties for an individual.
555 * @param ind
556 */
557 public Set<ObjectPropertyAssertion> getObjectProperties(Individual ind){
558 Set<ObjectPropertyAssertion> objectProperties = new HashSet<ObjectPropertyAssertion>();
559 Set<OWLObjectPropertyAssertionAxiom> owlObjectProperties = ontology.getObjectPropertyAssertionAxioms(factory.getOWLIndividual(URI.create(ind.getName())));
560
561
562 for(OWLObjectPropertyAssertionAxiom o : owlObjectProperties){
563 ObjectProperty ob = new ObjectProperty(o.getProperty().asOWLObjectProperty().getURI().toString());
564 Individual obj = new Individual(o.getObject().getURI().toString());
565 objectProperties.add(new ObjectPropertyAssertion(ob, ind, obj));
566
567 }
568 return objectProperties;
569 }
570
571 /**
572 * Returns the actual ontology.
573 * @return ontology
574 */
575 public OWLOntology getOntology() {
576 return ontology;
577 }
578
579
580 /**
581 * Prints reasons for inconsistent classes.
582 */
583 public void reason(){
584 // reasoner.getInconsistencyReasons(ontology);
585
586
587
588 /* Create a satisfiability checker */
589 OWLSatisfiabilityChecker checker = new Reasoner(manager);
590 try {
591 checker.loadOntologies(Collections.singleton(ontology));
592 } catch (OWLReasonerException e) {
593 // TODO Auto-generated catch block
594 e.printStackTrace();
595 }
596 OWLDebugger debugger = new BlackBoxOWLDebugger(manager, ontology, checker);
597
598 for(OWLClass owlClass : ((OWLAPIReasoner)reasoner).getInconsistentOWLClasses()){
599 /* Find the sets of support and print them */
600 Set<Set<OWLAxiom>> allsos = null;
601 try {
602 allsos = debugger.getAllSOSForIncosistentClass(owlClass);
603 } catch (OWLException e) {
604 // TODO Auto-generated catch block
605 e.printStackTrace();
606 }
607
608 for (Set<OWLAxiom> sos : allsos){
609 System.out.println(sos);
610 }
611 }
612
613
614
615 }
616
617
618
619
620
621
622
623
624 }