001    /**
002     * Copyright (C) 2007-2011, 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    package org.dllearner.reasoning;
021    
022    import com.clarkparsia.pellet.owlapiv3.PelletReasonerFactory;
023    import org.apache.log4j.Level;
024    import org.apache.log4j.Logger;
025    import org.dllearner.core.ComponentInitException;
026    import org.dllearner.core.AbstractKnowledgeSource;
027    import org.dllearner.core.AbstractReasonerComponent;
028    import org.dllearner.core.configurators.OWLAPIReasonerConfigurator;
029    import org.dllearner.core.options.*;
030    import org.dllearner.core.owl.*;
031    import org.dllearner.kb.OWLAPIOntology;
032    import org.dllearner.kb.OWLFile;
033    import org.dllearner.kb.sparql.SparqlKnowledgeSource;
034    import org.dllearner.utilities.owl.*;
035    import org.semanticweb.HermiT.Reasoner.ReasonerFactory;
036    import org.semanticweb.owlapi.apibinding.OWLManager;
037    import org.semanticweb.owlapi.model.*;
038    import org.semanticweb.owlapi.owllink.OWLlinkHTTPXMLReasonerFactory;
039    import org.semanticweb.owlapi.owllink.OWLlinkReasonerConfiguration;
040    import org.semanticweb.owlapi.reasoner.*;
041    import org.semanticweb.owlapi.util.SimpleIRIMapper;
042    import org.semanticweb.owlapi.vocab.PrefixOWLOntologyFormat;
043    import uk.ac.manchester.cs.factplusplus.owlapiv3.FaCTPlusPlusReasonerFactory;
044    
045    import java.io.File;
046    import java.net.MalformedURLException;
047    import java.net.URI;
048    import java.net.URISyntaxException;
049    import java.net.URL;
050    import java.util.*;
051    import java.util.Map.Entry;
052    
053    /**
054     * Mapping to OWL API reasoner interface. The OWL API currently
055     * supports three reasoners: FaCT++, HermiT and Pellet. FaCT++ is connected
056     * using JNI and native libraries, while HermiT and Pellet are pure Java
057     * libraries.
058     *
059     * @author Jens Lehmann
060     */
061    public class OWLAPIReasoner extends AbstractReasonerComponent {
062    
063    //      private static Logger logger = Logger
064    //      .getLogger(OWLAPIReasoner.class);       
065    
066        //private String reasonerType = "pellet";
067        private OWLAPIReasonerConfigurator configurator;
068    
069        @Override
070        public OWLAPIReasonerConfigurator getConfigurator() {
071            return configurator;
072        }
073    
074        private OWLReasoner reasoner;
075        private OWLOntologyManager manager;
076    
077        private OWLOntology ontology;
078        // the data factory is used to generate OWL API objects
079        private OWLDataFactory factory;
080        // static factory
081    //      private static OWLDataFactory staticFactory = OWLManager.createOWLOntologyManager().getOWLDataFactory();
082    
083        private ConceptComparator conceptComparator = new ConceptComparator();
084        private RoleComparator roleComparator = new RoleComparator();
085    //      private ClassHierarchy subsumptionHierarchy;
086    //      private ObjectPropertyHierarchy roleHierarchy;  
087    //      private DatatypePropertyHierarchy datatypePropertyHierarchy;
088    //      private Set<Description> allowedConceptsInSubsumptionHierarchy;
089    
090        // primitives
091        Set<NamedClass> atomicConcepts = new TreeSet<NamedClass>(conceptComparator);
092        Set<ObjectProperty> atomicRoles = new TreeSet<ObjectProperty>(roleComparator);
093        SortedSet<DatatypeProperty> datatypeProperties = new TreeSet<DatatypeProperty>();
094        SortedSet<DatatypeProperty> booleanDatatypeProperties = new TreeSet<DatatypeProperty>();
095        SortedSet<DatatypeProperty> doubleDatatypeProperties = new TreeSet<DatatypeProperty>();
096        SortedSet<DatatypeProperty> intDatatypeProperties = new TreeSet<DatatypeProperty>();
097        SortedSet<DatatypeProperty> stringDatatypeProperties = new TreeSet<DatatypeProperty>();
098        SortedSet<Individual> individuals = new TreeSet<Individual>();
099    
100        // namespaces
101        private Map<String, String> prefixes = new TreeMap<String, String>();
102        private String baseURI;
103    
104        // references to OWL API ontologies
105        private List<OWLOntology> owlAPIOntologies = new LinkedList<OWLOntology>();
106    
107        public OWLAPIReasoner(Set<AbstractKnowledgeSource> sources) {
108            super(sources);
109            this.configurator = new OWLAPIReasonerConfigurator(this);
110        }
111    
112        public static String getName() {
113            return "OWL API reasoner";
114        }
115    
116    
117        public static Collection<ConfigOption<?>> createConfigOptions() {
118            Collection<ConfigOption<?>> options = new LinkedList<ConfigOption<?>>();
119            StringConfigOption type = new StringConfigOption("reasonerType", "FaCT++, HermiT, OWLlink or Pellet, which means \"fact\", \"hermit\", \"owllink\" or \"pellet\"", "pellet", false, true);
120            type.setAllowedValues(new String[]{"fact", "hermit", "owllink", "pellet"});
121    
122            // closure option? see:
123            // http://owlapi.svn.sourceforge.net/viewvc/owlapi/owl1_1/trunk/tutorial/src/main/java/uk/ac/manchester/owl/tutorial/examples/ClosureAxiomsExample.java?view=markup
124            options.add(type);
125            try {
126                URLConfigOption owlLinkURL = new URLConfigOption("owlLinkURL", "the URL to the remote OWLlink server", new URL("http://localhost:8080/"), false, true);
127                options.add(owlLinkURL);
128            } catch (MalformedURLException e) {
129                e.printStackTrace();
130            }
131            return options;
132        }
133    
134        /* (non-Javadoc)
135          * @see org.dllearner.core.Component#applyConfigEntry(org.dllearner.core.config.ConfigEntry)
136          */
137        @Override
138        public <T> void applyConfigEntry(ConfigEntry<T> entry) throws InvalidConfigOptionValueException {
139    
140        }
141    
142        @Override
143        public void init() throws ComponentInitException {
144            // reset variables (otherwise subsequent initialisation with
145            // different knowledge sources will merge both)
146            atomicConcepts = new TreeSet<NamedClass>(conceptComparator);
147            atomicRoles = new TreeSet<ObjectProperty>(roleComparator);
148            datatypeProperties = new TreeSet<DatatypeProperty>();
149            booleanDatatypeProperties = new TreeSet<DatatypeProperty>();
150            doubleDatatypeProperties = new TreeSet<DatatypeProperty>();
151            intDatatypeProperties = new TreeSet<DatatypeProperty>();
152            stringDatatypeProperties = new TreeSet<DatatypeProperty>();
153            individuals = new TreeSet<Individual>();
154    
155            // create OWL API ontology manager
156            manager = OWLManager.createOWLOntologyManager();
157    
158            // it is a bit cumbersome to obtain all classes, because there
159            // are no reasoner queries to obtain them => hence we query them
160            // for each ontology and add them to a set; a comparator avoids
161            // duplicates by checking URIs
162            Comparator<OWLNamedObject> namedObjectComparator = new Comparator<OWLNamedObject>() {
163                public int compare(OWLNamedObject o1, OWLNamedObject o2) {
164                    return o1.getIRI().compareTo(o2.getIRI());
165                }
166            };
167            Set<OWLClass> classes = new TreeSet<OWLClass>(namedObjectComparator);
168            Set<OWLObjectProperty> owlObjectProperties = new TreeSet<OWLObjectProperty>(namedObjectComparator);
169            Set<OWLDataProperty> owlDatatypeProperties = new TreeSet<OWLDataProperty>(namedObjectComparator);
170            Set<OWLNamedIndividual> owlIndividuals = new TreeSet<OWLNamedIndividual>(namedObjectComparator);
171    
172            Set<OWLOntology> allImports = new HashSet<OWLOntology>();
173            prefixes = new TreeMap<String, String>();
174    
175            for (AbstractKnowledgeSource source : sources) {
176    
177                if (source instanceof OWLFile || source instanceof SparqlKnowledgeSource || source instanceof OWLAPIOntology) {
178                    URL url = null;
179                    if (source instanceof OWLFile) {
180                        url = ((OWLFile) source).getURL();
181                    }
182    
183                    try {
184    
185                        if (source instanceof OWLAPIOntology) {
186                            ontology = ((OWLAPIOntology) source).getOWLOntolgy();
187                            manager = ontology.getOWLOntologyManager();
188                        } else if (source instanceof SparqlKnowledgeSource) {
189                            ontology = ((SparqlKnowledgeSource) source).getOWLAPIOntology();
190                            manager = ontology.getOWLOntologyManager();
191                        } else {
192                            ontology = manager.loadOntologyFromOntologyDocument(IRI.create(url.toURI()));
193                        }
194    
195                        owlAPIOntologies.add(ontology);
196                        try {
197                            // imports includes the ontology itself
198                            //FIXME this line throws the strange error
199                            Set<OWLOntology> imports = manager.getImportsClosure(ontology);
200                            allImports.addAll(imports);
201    
202    //                                      System.out.println(imports);
203                            for (OWLOntology ont : imports) {
204                                classes.addAll(ont.getClassesInSignature());
205                                owlObjectProperties.addAll(ont.getObjectPropertiesInSignature());
206                                owlDatatypeProperties.addAll(ont.getDataPropertiesInSignature());
207                                owlIndividuals.addAll(ont.getIndividualsInSignature());
208                            }
209    
210                        } catch (UnknownOWLOntologyException uooe) {
211                            logger.error("UnknownOWLOntologyException occured, imports were not loaded! This is a bug, which has not been fixed yet.");
212                        }
213    
214                        // if several knowledge sources are included, then we can only
215                        // guarantee that the base URI is from one of those sources (there
216                        // can't be more than one); but we will take care that all prefixes are
217                        // correctly imported
218                        OWLOntologyFormat format = manager.getOntologyFormat(ontology);
219                        if (format instanceof PrefixOWLOntologyFormat) {
220                            prefixes.putAll(((PrefixOWLOntologyFormat) format).getPrefixName2PrefixMap());
221                            baseURI = ((PrefixOWLOntologyFormat) format).getDefaultPrefix();
222                            prefixes.remove("");
223                        }
224    
225                    } catch (OWLOntologyCreationException e) {
226                        e.printStackTrace();
227                    } catch (URISyntaxException e) {
228                        e.printStackTrace();
229                    }
230                    // all other sources are converted to KB and then to an
231                    // OWL API ontology
232                } else {
233                    KB kb = source.toKB();
234    //                              System.out.println(kb.toString(null,null));
235    
236                    IRI ontologyURI = IRI.create("http://example.com");
237                    ontology = null;
238                    try {
239                        ontology = manager.createOntology(ontologyURI);
240                    } catch (OWLOntologyCreationException e) {
241                        e.printStackTrace();
242                    }
243                    OWLAPIAxiomConvertVisitor.fillOWLOntology(manager, ontology, kb);
244                    owlAPIOntologies.add(ontology);
245                    allImports.add(ontology);
246                    atomicConcepts.addAll(kb.findAllAtomicConcepts());
247                    atomicRoles.addAll(kb.findAllAtomicRoles());
248                    individuals.addAll(kb.findAllIndividuals());
249                    // TODO: add method to find datatypes
250                }
251            }
252            try {
253                ontology = manager.createOntology(IRI.create("http://dl-learner/all"), new HashSet<OWLOntology>(owlAPIOntologies));
254            } catch (OWLOntologyCreationException e1) {
255                e1.printStackTrace();
256            }
257    
258            //configure reasoner
259            ReasonerProgressMonitor progressMonitor = new NullReasonerProgressMonitor();
260            FreshEntityPolicy freshEntityPolicy = FreshEntityPolicy.ALLOW;
261            long timeOut = Integer.MAX_VALUE;
262            IndividualNodeSetPolicy individualNodeSetPolicy = IndividualNodeSetPolicy.BY_NAME;
263            OWLReasonerConfiguration conf = new SimpleConfiguration(progressMonitor, freshEntityPolicy, timeOut, individualNodeSetPolicy);
264    
265            // create actual reasoner
266            if (configurator.getReasonerType().equals("fact")) {
267                try {
268                    reasoner = new FaCTPlusPlusReasonerFactory().createNonBufferingReasoner(ontology, conf);
269                } catch (Exception e) {
270                    e.printStackTrace();
271                }
272                System.out.println("Using FaCT++.");
273            } else if (configurator.getReasonerType().equals("hermit")) {
274                // instantiate HermiT reasoner
275                reasoner = new ReasonerFactory().createNonBufferingReasoner(ontology, conf);
276            } else if (configurator.getReasonerType().equals("pellet")) {
277                // instantiate Pellet reasoner
278                reasoner = PelletReasonerFactory.getInstance().createNonBufferingReasoner(ontology, conf);
279    
280                // change log level to WARN for Pellet, because otherwise log
281                // output will be very large
282                Logger pelletLogger = Logger.getLogger("org.mindswap.pellet");
283                pelletLogger.setLevel(Level.WARN);
284            } else {
285                try {
286                    OWLlinkHTTPXMLReasonerFactory factory = new OWLlinkHTTPXMLReasonerFactory();
287                    URL url = getConfigurator().getOwlLinkURL();//Configure the server end-point
288                    OWLlinkReasonerConfiguration config = new OWLlinkReasonerConfiguration(url);
289                    reasoner = factory.createNonBufferingReasoner(ontology, config);
290                    System.out.println(reasoner.getReasonerName());
291                } catch (Exception e) {
292    //                              e.printStackTrace();
293                    throw new ComponentInitException(e);
294                }
295            }
296    
297            /*
298              Set<OWLOntology> importsClosure = manager.getImportsClosure(ontology);
299              System.out.println("imports closure : " + importsClosure);
300              try {
301                  reasoner.loadOntologies(importsClosure);
302              } catch (OWLReasonerException e1) {
303                  // TODO Auto-generated catch block
304                  e1.printStackTrace();
305              }*/
306    
307    //              System.out.println(classes);
308    //              System.out.println(properties);
309    //              System.out.println(individuals);
310    
311            // compute class hierarchy and types of individuals
312            // (done here to speed up later reasoner calls)
313            boolean inconsistentOntology = !reasoner.isConsistent();
314    
315            if (!inconsistentOntology) {
316                reasoner.precomputeInferences(InferenceType.CLASS_HIERARCHY, InferenceType.CLASS_ASSERTIONS);
317            } else {
318                throw new ComponentInitException("Inconsistent ontologies.");
319            }
320    
321            factory = manager.getOWLDataFactory();
322    
323    //              try {
324    //                      if(reasoner.isDefined(factory.getOWLIndividual(URI.create("http://example.com/father#female"))))
325    //                              System.out.println("DEFINED.");
326    //                      else
327    //                              System.out.println("NOT DEFINED.");
328    //              } catch (OWLReasonerException e) {
329    //                      // TODO Auto-generated catch block
330    //                      e.printStackTrace();
331    //              }
332    
333            // read in primitives
334            for (OWLClass owlClass : classes)
335                atomicConcepts.add(new NamedClass(owlClass.toStringID()));
336            for (OWLObjectProperty owlProperty : owlObjectProperties)
337                atomicRoles.add(new ObjectProperty(owlProperty.toStringID()));
338            for (OWLDataProperty owlProperty : owlDatatypeProperties) {
339                DatatypeProperty dtp = new DatatypeProperty(owlProperty.toStringID());
340                Set<OWLDataRange> ranges = owlProperty.getRanges(allImports);
341                Iterator<OWLDataRange> it = ranges.iterator();
342                if (it.hasNext()) {
343                    OWLDataRange range = it.next();
344                    if (range.isDatatype()) {
345                        URI uri = ((OWLDatatype) range).getIRI().toURI();
346                        if (uri.equals(OWL2Datatype.BOOLEAN.getURI())) booleanDatatypeProperties.add(dtp);
347                        else if (uri.equals(OWL2Datatype.DOUBLE.getURI())) doubleDatatypeProperties.add(dtp);
348                        else if (uri.equals(OWL2Datatype.INT.getURI())) intDatatypeProperties.add(dtp);
349                        else if (uri.equals(OWL2Datatype.STRING.getURI())) stringDatatypeProperties.add(dtp);
350                    }
351                } else {
352                    stringDatatypeProperties.add(dtp);
353                }
354                datatypeProperties.add(dtp);
355            }
356            for (OWLNamedIndividual owlIndividual : owlIndividuals) {
357                individuals.add(new Individual(owlIndividual.toStringID()));
358            }
359    
360            // remove top and bottom properties (for backwards compatibility)
361    //              atomicRoles.remove(new ObjectProperty("http://www.w3.org/2002/07/owl#bottomObjectProperty"));
362    //              atomicRoles.remove(new ObjectProperty("http://www.w3.org/2002/07/owl#topObjectProperty"));
363        }
364    
365        /* (non-Javadoc)
366          * @see org.dllearner.core.Reasoner#getAtomicConcepts()
367          */
368        public Set<NamedClass> getNamedClasses() {
369            return Collections.unmodifiableSet(atomicConcepts);
370        }
371    
372        /* (non-Javadoc)
373          * @see org.dllearner.core.Reasoner#getAtomicRoles()
374          */
375        public Set<ObjectProperty> getObjectProperties() {
376            return Collections.unmodifiableSet(atomicRoles);
377        }
378    
379        @Override
380        public SortedSet<DatatypeProperty> getDatatypePropertiesImpl() {
381            return datatypeProperties;
382        }
383    
384        /* (non-Javadoc)
385          * @see org.dllearner.core.Reasoner#getIndividuals()
386          */
387        public SortedSet<Individual> getIndividuals() {
388            return individuals;
389        }
390    
391        /* (non-Javadoc)
392          * @see org.dllearner.core.Reasoner#getReasonerType()
393          */
394        @Override
395        public ReasonerType getReasonerType() {
396            if (configurator.getReasonerType().equals("fact")) {
397                return ReasonerType.OWLAPI_FACT;
398            } else if (configurator.getReasonerType().equals("hermit")) {
399                return ReasonerType.OWLAPI_HERMIT;
400            } else {
401                return ReasonerType.OWLAPI_PELLET;
402            }
403        }
404    
405    //      @Override
406    //      public ObjectPropertyHierarchy prepareRoleHierarchy() {
407    //              // code copied from DIG reasoner
408    //              
409    //              TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyUp = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
410    //                              roleComparator);
411    //              TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyDown = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
412    //                              roleComparator);
413    // 
414    //              // refinement of atomic concepts
415    //              for (ObjectProperty role : atomicRoles) {
416    //                      roleHierarchyDown.put(role, getMoreSpecialRolesImpl(role));
417    //                      roleHierarchyUp.put(role, getMoreGeneralRolesImpl(role));
418    //              }
419    //
420    //              roleHierarchy = new ObjectPropertyHierarchy(atomicRoles, roleHierarchyUp,
421    //                              roleHierarchyDown);
422    //              return roleHierarchy;
423    //      }
424    
425        /* (non-Javadoc)
426          * @see org.dllearner.core.Reasoner#prepareRoleHierarchy(java.util.Set)
427          */
428    //      public void prepareRoleHierarchy(Set<ObjectProperty> allowedRoles) {
429    //              // code copied from DIG reasoner
430    //              
431    //              TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyUp = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
432    //                              roleComparator);
433    //              TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyDown = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
434    //                              roleComparator);
435    // 
436    //              // refinement of atomic concepts
437    //              for (ObjectProperty role : atomicRoles) {
438    //                      roleHierarchyDown.put(role, getMoreSpecialRolesImpl(role));
439    //                      roleHierarchyUp.put(role, getMoreGeneralRolesImpl(role));
440    //              }
441    //
442    //              roleHierarchy = new ObjectPropertyHierarchy(allowedRoles, roleHierarchyUp,
443    //                              roleHierarchyDown);
444    //      }       
445    
446    //      @Override
447    //      public ObjectPropertyHierarchy getRoleHierarchy() {
448    //              return roleHierarchy;
449    //      }       
450    
451    //      public void prepareDatatypePropertyHierarchyImpl(Set<DatatypeProperty> allowedRoles) {
452    //              // code copied from DIG reasoner
453    //              
454    //              TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>> datatypePropertyHierarchyUp = new TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>>(
455    //                              roleComparator);
456    //              TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>> datatypePropertyHierarchyDown = new TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>>(
457    //                              roleComparator);
458    // 
459    //              // refinement of atomic concepts
460    //              for (DatatypeProperty role : datatypeProperties) {
461    //                      datatypePropertyHierarchyDown.put(role, getMoreSpecialDatatypePropertiesImpl(role));
462    //                      datatypePropertyHierarchyUp.put(role, getMoreGeneralDatatypePropertiesImpl(role));
463    //              }
464    //
465    //              datatypePropertyHierarchy = new DatatypePropertyHierarchy(allowedRoles, datatypePropertyHierarchyUp,
466    //                              datatypePropertyHierarchyDown);
467    //      }       
468    
469    //      @Override
470    //      public DatatypePropertyHierarchy getDatatypePropertyHierarchy() {
471    //              return datatypePropertyHierarchy;
472    //      }               
473    
474        @Override
475        public boolean isSuperClassOfImpl(Description superConcept, Description subConcept) {
476            return reasoner.isEntailed(factory.getOWLSubClassOfAxiom(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(subConcept), OWLAPIDescriptionConvertVisitor.getOWLClassExpression(superConcept)));
477        }
478    
479        @Override
480        protected boolean isEquivalentClassImpl(Description class1, Description class2) {
481            return reasoner.isEntailed(factory.getOWLEquivalentClassesAxiom(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(class1), OWLAPIDescriptionConvertVisitor.getOWLClassExpression(class2)));
482        }
483    
484        @Override
485        protected TreeSet<Description> getSuperClassesImpl(Description concept) {
486            NodeSet<OWLClass> classes = null;
487    
488            classes = reasoner.getSuperClasses(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept), true);
489    
490            return getFirstClasses(classes);
491        }
492    
493        @Override
494        protected TreeSet<Description> getSubClassesImpl(Description concept) {
495            NodeSet<OWLClass> classes = null;
496    
497            classes = reasoner.getSubClasses(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept), true);
498    
499            return getFirstClasses(classes);
500        }
501    
502        @Override
503        protected TreeSet<ObjectProperty> getSuperPropertiesImpl(ObjectProperty role) {
504            NodeSet<OWLObjectPropertyExpression> properties = null;
505    
506            properties = reasoner.getSuperObjectProperties(OWLAPIConverter.getOWLAPIObjectProperty(role), true);
507    
508            return getFirstObjectProperties(properties);
509        }
510    
511        @Override
512        protected TreeSet<ObjectProperty> getSubPropertiesImpl(ObjectProperty role) {
513            NodeSet<OWLObjectPropertyExpression> properties = null;
514    
515            properties = reasoner.getSubObjectProperties(OWLAPIConverter.getOWLAPIObjectProperty(role), true);
516    
517            return getFirstObjectProperties(properties);
518        }
519    
520        @Override
521        protected TreeSet<DatatypeProperty> getSuperPropertiesImpl(DatatypeProperty role) {
522            NodeSet<OWLDataProperty> properties = null;
523    
524            properties = reasoner.getSuperDataProperties(OWLAPIConverter.getOWLAPIDataProperty(role), true);
525    
526            return getFirstDatatypeProperties(properties);
527        }
528    
529        @Override
530        protected TreeSet<DatatypeProperty> getSubPropertiesImpl(DatatypeProperty role) {
531            NodeSet<OWLDataProperty> properties = null;
532    
533            properties = reasoner.getSubDataProperties(OWLAPIConverter.getOWLAPIDataProperty(role), true);
534    
535            return getFirstDatatypeProperties(properties);
536        }
537    
538        @Override
539        public boolean hasTypeImpl(Description concept, Individual individual) {
540            OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept);
541            OWLIndividual i = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
542            return reasoner.isEntailed(factory.getOWLClassAssertionAxiom(d, i));
543        }
544    
545        @Override
546        public SortedSet<Individual> getIndividualsImpl(Description concept) {
547    //              OWLDescription d = getOWLAPIDescription(concept);
548            OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept);
549            Set<OWLNamedIndividual> individuals = reasoner.getInstances(d, false).getFlattened();
550            SortedSet<Individual> inds = new TreeSet<Individual>();
551            for (OWLNamedIndividual ind : individuals)
552                //ugly code
553                if (ind != null) inds.add(new Individual(ind.toStringID()));
554            return inds;
555        }
556    
557        @Override
558        public Set<NamedClass> getTypesImpl(Individual individual) {
559            Set<Node<OWLClass>> result = null;
560    
561            result = reasoner.getTypes(factory.getOWLNamedIndividual(IRI.create(individual.getName())), false).getNodes();
562    
563            return getFirstClassesNoTopBottom(result);
564        }
565    
566        @Override
567        public boolean isSatisfiableImpl() {
568            return reasoner.isSatisfiable(factory.getOWLThing());
569        }
570    
571        @Override
572        public Description getDomainImpl(ObjectProperty objectProperty) {
573            OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(objectProperty);
574    
575            // Pellet returns a set of nodes of named classes, which are more
576            // general than the actual domain/range
577            NodeSet<OWLClass> set = reasoner.getObjectPropertyDomains(prop, false);
578            return getDescriptionFromReturnedDomain(set);
579    
580        }
581    
582        @Override
583        public Description getDomainImpl(DatatypeProperty datatypeProperty) {
584            OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
585    
586            NodeSet<OWLClass> set = reasoner.getDataPropertyDomains(prop, true);
587            return getDescriptionFromReturnedDomain(set);
588    
589        }
590    
591        @Override
592        public Description getRangeImpl(ObjectProperty objectProperty) {
593            OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(objectProperty);
594    
595            NodeSet<OWLClass> set = reasoner.getObjectPropertyRanges(prop, true);
596            if (set.isEmpty()) return new Thing();
597            OWLClass oc = set.iterator().next().getRepresentativeElement();
598            if (oc.isOWLThing()) {
599                return Thing.instance;
600            }
601            return new NamedClass(oc.toStringID());
602    
603        }
604    
605        private Description getDescriptionFromReturnedDomain(NodeSet<OWLClass> set) {
606            if (set.isEmpty()) return new Thing();
607    
608            Set<OWLClassExpression> union = new HashSet<OWLClassExpression>();
609            Set<OWLClassExpression> domains = new HashSet<OWLClassExpression>();
610    
611            for (Node<OWLClass> descs : set) {
612                for (OWLClassExpression desc : descs) {
613                    union.add(desc);
614                }
615            }
616            for (OWLClassExpression desc : union) {
617                boolean isSuperClass = false;
618                for (Description d : getClassHierarchy().getSubClasses(OWLAPIConverter.convertClass(desc.asOWLClass()))) {
619                    if (union.contains(OWLAPIConverter.getOWLAPIDescription(d))) {
620                        isSuperClass = true;
621                        break;
622                    }
623                }
624                if (!isSuperClass) {
625                    domains.add(desc);
626                }
627            }
628    
629            OWLClass oc = (OWLClass) domains.iterator().next();
630            if (oc.isOWLThing()) {
631                return new Thing();
632            } else {
633                return new NamedClass(oc.toStringID());
634            }
635        }
636    
637        @Override
638        public Map<Individual, SortedSet<Individual>> getPropertyMembersImpl(ObjectProperty atomicRole) {
639            OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(atomicRole);
640            Map<Individual, SortedSet<Individual>> map = new TreeMap<Individual, SortedSet<Individual>>();
641            for (Individual i : individuals) {
642                OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(i.getName()));
643    
644                // get all related individuals via OWL API
645                Set<OWLNamedIndividual> inds = reasoner.getObjectPropertyValues(ind, prop).getFlattened();
646    
647                // convert data back to DL-Learner structures
648                SortedSet<Individual> is = new TreeSet<Individual>();
649                for (OWLNamedIndividual oi : inds)
650                    is.add(new Individual(oi.toStringID()));
651                map.put(i, is);
652            }
653            return map;
654        }
655    
656        @Override
657        protected Map<ObjectProperty, Set<Individual>> getObjectPropertyRelationshipsImpl(Individual individual) {
658            OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
659            Map<OWLObjectPropertyExpression, Set<OWLNamedIndividual>> mapAPI = new HashMap<OWLObjectPropertyExpression, Set<OWLNamedIndividual>>();
660    
661    //              Map<OWLObjectPropertyExpression, Set<OWLIndividual>> mapAPI = ind.getObjectPropertyValues(ontology);
662            //no method found in the new reasoner interface, so we have to ask the reasoner for each property in the ontology
663            for (OWLObjectProperty prop : ontology.getObjectPropertiesInSignature(true)) {
664                mapAPI.put(prop, reasoner.getObjectPropertyValues(ind, prop).getFlattened());
665            }
666    
667            Map<ObjectProperty, Set<Individual>> map = new TreeMap<ObjectProperty, Set<Individual>>();
668            for (Entry<OWLObjectPropertyExpression, Set<OWLNamedIndividual>> entry : mapAPI.entrySet()) {
669                ObjectProperty prop = OWLAPIConverter.convertObjectProperty(entry.getKey().asOWLObjectProperty());
670                Set<Individual> inds = OWLAPIConverter.convertIndividuals(entry.getValue());
671                map.put(prop, inds);
672            }
673            return map;
674        }
675    
676        @Override
677        public Set<Individual> getRelatedIndividualsImpl(Individual individual, ObjectProperty objectProperty) {
678            OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
679            OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(objectProperty);
680            Set<OWLNamedIndividual> inds = null;
681    
682            inds = reasoner.getObjectPropertyValues(ind, prop).getFlattened();
683    
684            // convert data back to DL-Learner structures
685            SortedSet<Individual> is = new TreeSet<Individual>();
686            for (OWLNamedIndividual oi : inds) {
687                is.add(new Individual(oi.toStringID()));
688            }
689            return is;
690        }
691    
692        @Override
693        public Set<Constant> getRelatedValuesImpl(Individual individual, DatatypeProperty datatypeProperty) {
694            OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
695            OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
696            Set<OWLLiteral> constants = null;
697    
698            constants = reasoner.getDataPropertyValues(ind, prop);
699    
700            return OWLAPIConverter.convertConstants(constants);
701        }
702    
703        public Map<Individual, SortedSet<Double>> getDoubleValues(DatatypeProperty datatypeProperty) {
704            OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
705            Map<Individual, SortedSet<Double>> map = new TreeMap<Individual, SortedSet<Double>>();
706            for (Individual i : individuals) {
707                OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(i.getName()));
708    
709                // get all related individuals via OWL API
710                Set<OWLLiteral> inds = null;
711    
712                inds = reasoner.getDataPropertyValues(ind, prop);
713    
714                // convert data back to DL-Learner structures
715                SortedSet<Double> is = new TreeSet<Double>();
716                for (OWLLiteral oi : inds) {
717                    Double d = Double.parseDouble(oi.getLiteral());
718                    is.add(d);
719                }
720                map.put(i, is);
721            }
722            return map;
723        }
724    
725        @Override
726        public Map<Individual, SortedSet<Constant>> getDatatypeMembersImpl(DatatypeProperty datatypeProperty) {
727            OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
728            Map<Individual, SortedSet<Constant>> map = new TreeMap<Individual, SortedSet<Constant>>();
729            for (Individual i : individuals) {
730                OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(i.getName()));
731    
732                // get all related values via OWL API
733                Set<OWLLiteral> constants = null;
734    
735                constants = reasoner.getDataPropertyValues(ind, prop);
736    
737                // convert data back to DL-Learner structures
738                SortedSet<Constant> is = new TreeSet<Constant>();
739                for (OWLLiteral literal : constants) {
740                    // for typed constants we have to figure out the correct
741                    // data type and value
742                    if (!literal.isRDFPlainLiteral()) {
743                        Datatype dt = OWLAPIConverter.convertDatatype(literal.getDatatype());
744                        is.add(new TypedConstant(literal.getLiteral(), dt));
745                        // for untyped constants we have to figure out the value
746                        // and language tag (if any)
747                    } else {
748                        if (literal.hasLang()) is.add(new UntypedConstant(literal.getLiteral(), literal.getLang()));
749                        else is.add(new UntypedConstant(literal.getLiteral()));
750                    }
751                }
752                // only add individuals using the datatype property
753                if (is.size() > 0) map.put(i, is);
754            }
755            return map;
756        }
757    
758        // OWL API returns a set of nodes of classes, where each node
759        // consists of equivalent classes; this method picks one class
760        // from each node to flatten the set of nodes
761        private TreeSet<Description> getFirstClasses(NodeSet<OWLClass> nodeSet) {
762            TreeSet<Description> concepts = new TreeSet<Description>(conceptComparator);
763            for (Node<OWLClass> node : nodeSet) {
764                // take one element from the set and ignore the rest
765                // (TODO: we need to make sure we always ignore the same concepts)
766                OWLClass concept = node.getRepresentativeElement();
767                if (concept.isOWLThing()) {
768                    concepts.add(new Thing());
769                } else if (concept.isOWLNothing()) {
770                    concepts.add(new Nothing());
771                } else {
772                    concepts.add(new NamedClass(concept.toStringID()));
773                }
774            }
775            return concepts;
776        }
777    
778        private Set<NamedClass> getFirstClassesNoTopBottom(Set<Node<OWLClass>> nodeSet) {
779            Set<NamedClass> concepts = new HashSet<NamedClass>();
780            for (Node<OWLClass> node : nodeSet) {
781                // take one element from the set and ignore the rest
782                // (TODO: we need to make sure we always ignore the same concepts)
783                OWLClass concept = node.getRepresentativeElement();
784                if (!concept.isOWLThing() && !concept.isOWLNothing()) concepts.add(new NamedClass(concept.toStringID()));
785            }
786            return concepts;
787        }
788    
789        private TreeSet<ObjectProperty> getFirstObjectProperties(NodeSet<OWLObjectPropertyExpression> nodeSet) {
790            TreeSet<ObjectProperty> roles = new TreeSet<ObjectProperty>(roleComparator);
791            for (Node<OWLObjectPropertyExpression> node : nodeSet) {
792                if (node.isBottomNode() || node.isTopNode()) {
793                    continue;
794                }
795                // take one element from the set and ignore the rest
796                // (TODO: we need to make sure we always ignore the same concepts)
797                OWLObjectPropertyExpression property = node.getRepresentativeElement();
798                roles.add(new ObjectProperty(property.asOWLObjectProperty().toStringID()));
799            }
800            roles.remove(new ObjectProperty(factory.getOWLTopObjectProperty().toStringID()));
801            roles.remove(new ObjectProperty(factory.getOWLBottomObjectProperty().toStringID()));
802            return roles;
803        }
804    
805        private TreeSet<DatatypeProperty> getFirstDatatypeProperties(NodeSet<OWLDataProperty> nodeSet) {
806            TreeSet<DatatypeProperty> roles = new TreeSet<DatatypeProperty>(roleComparator);
807            for (Node<OWLDataProperty> node : nodeSet) {
808                if (node.isBottomNode() || node.isTopNode()) {
809                    continue;
810                }
811                OWLDataProperty property = node.getRepresentativeElement();
812                roles.add(new DatatypeProperty(property.toStringID()));
813            }
814            roles.remove(new DatatypeProperty(factory.getOWLTopDataProperty().toStringID()));
815            roles.remove(new DatatypeProperty(factory.getOWLBottomDataProperty().toStringID()));
816            return roles;
817        }
818    
819        @SuppressWarnings({"unused"})
820        private Set<Description> owlClassesToAtomicConcepts(Set<OWLClass> owlClasses) {
821            Set<Description> concepts = new HashSet<Description>();
822            for (OWLClass owlClass : owlClasses)
823                concepts.add(OWLAPIConverter.convertClass(owlClass));
824            return concepts;
825        }
826    
827        public static void exportKBToOWL(File owlOutputFile, KB kb, IRI ontologyIRI) {
828            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
829            //URI ontologyURI = URI.create("http://example.com");
830            IRI physicalIRI = IRI.create(owlOutputFile.toURI());
831            SimpleIRIMapper mapper = new SimpleIRIMapper(ontologyIRI, physicalIRI);
832            manager.addIRIMapper(mapper);
833            OWLOntology ontology;
834            try {
835                ontology = manager.createOntology(ontologyIRI);
836                // OWLAPIReasoner.fillOWLAPIOntology(manager, ontology, kb);
837                OWLAPIAxiomConvertVisitor.fillOWLOntology(manager, ontology, kb);
838                manager.saveOntology(ontology);
839            } catch (OWLOntologyCreationException e) {
840                // TODO Auto-generated catch block
841                e.printStackTrace();
842            } catch (UnknownOWLOntologyException e) {
843                // TODO Auto-generated catch block
844                e.printStackTrace();
845            } catch (OWLOntologyStorageException e) {
846                // TODO Auto-generated catch block
847                e.printStackTrace();
848            }
849        }
850    
851        /**
852         * Test
853         *
854         * @param args
855         */
856        public static void main(String[] args) {
857            String iri = "http://www.co-ode.org/ontologies/pizza/2007/02/12/pizza.owl";
858    
859            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
860            try {
861                OWLOntology ontology = manager.loadOntologyFromOntologyDocument(IRI.create(iri));
862                new PelletReasonerFactory().createReasoner(ontology);
863                System.out.println("Reasoner loaded succesfully.");
864            } catch (Exception e) {
865                e.printStackTrace();
866            }
867        }
868    
869        /**
870         * @return the booleanDatatypeProperties
871         */
872        @Override
873        public SortedSet<DatatypeProperty> getBooleanDatatypePropertiesImpl() {
874            return booleanDatatypeProperties;
875        }
876    
877        /**
878         * @return the doubleDatatypeProperties
879         */
880        @Override
881        public SortedSet<DatatypeProperty> getDoubleDatatypePropertiesImpl() {
882            return doubleDatatypeProperties;
883        }
884    
885        /**
886         * @return the intDatatypeProperties
887         */
888        @Override
889        public SortedSet<DatatypeProperty> getIntDatatypePropertiesImpl() {
890            return intDatatypeProperties;
891        }
892    
893        /**
894         * @return the intDatatypeProperties
895         */
896        @Override
897        public SortedSet<DatatypeProperty> getStringDatatypePropertiesImpl() {
898            return stringDatatypeProperties;
899        }
900    
901        /* (non-Javadoc)
902          * @see org.dllearner.core.Reasoner#getBaseURI()
903          */
904        public String getBaseURI() {
905            return baseURI;
906        }
907    
908        /* (non-Javadoc)
909          * @see org.dllearner.core.Reasoner#getPrefixes()
910          */
911        public Map<String, String> getPrefixes() {
912            return prefixes;
913        }
914    
915        /* (non-Javadoc)
916          * @see org.dllearner.core.ReasonerComponent#releaseKB()
917          */
918        @Override
919        public void releaseKB() {
920            reasoner.dispose();
921        }
922    
923        public List<OWLOntology> getOWLAPIOntologies() {
924            return owlAPIOntologies;
925        }
926    
927        /*public void setReasonerType(String type){
928             configurator.setReasonerType(type);
929         }*/
930    
931    //      @Override
932    //      public boolean hasDatatypeSupport() {
933    //              return true;
934    //      }
935    
936        @Override
937        public Set<NamedClass> getInconsistentClassesImpl() {
938            Set<NamedClass> concepts = new HashSet<NamedClass>();
939    
940            for (OWLClass concept : reasoner.getUnsatisfiableClasses().getEntities()) {
941                concepts.add(new NamedClass(concept.toStringID()));
942            }
943    
944            return concepts;
945        }
946    
947    
948        public Set<OWLClass> getInconsistentOWLClasses() {
949            return reasoner.getUnsatisfiableClasses().getEntities();
950        }
951    
952        @Override
953        public Set<Constant> getLabelImpl(Entity entity) {
954            OWLEntity owlEntity = OWLAPIConverter.getOWLAPIEntity(entity);
955            Set<OWLAnnotation> labelAnnotations = owlEntity.getAnnotations(owlAPIOntologies.get(0), factory.getRDFSLabel());
956            Set<Constant> annotations = new HashSet<Constant>();
957            for (OWLAnnotation label : labelAnnotations) {
958                OWLLiteral c = (OWLLiteral) label.getValue();
959                annotations.add(OWLAPIConverter.convertConstant(c));
960            }
961            return annotations;
962        }
963    
964        /* (non-Javadoc)
965          * @see org.dllearner.core.BaseReasoner#remainsSatisfiable(org.dllearner.core.owl.Axiom)
966          */
967        @Override
968        public boolean remainsSatisfiableImpl(Axiom axiom) {
969            boolean consistent = true;
970            OWLAxiom axiomOWLAPI = OWLAPIAxiomConvertVisitor.convertAxiom(axiom);
971    
972            try {
973                manager.applyChange(new AddAxiom(ontology, axiomOWLAPI));
974            } catch (OWLOntologyChangeException e1) {
975                e1.printStackTrace();
976            }
977    
978            consistent = reasoner.isConsistent();
979    
980            try {
981                manager.applyChange(new RemoveAxiom(ontology, axiomOWLAPI));
982            } catch (OWLOntologyChangeException e) {
983                e.printStackTrace();
984            }
985    
986            return consistent;
987        }
988    
989        /**
990         * Returns asserted class definitions of given class
991         *
992         * @param nc the class
993         * @return the asserted class definitions
994         */
995        @Override
996        protected Set<Description> getAssertedDefinitionsImpl(NamedClass nc) {
997            OWLClass owlClass = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(nc).asOWLClass();
998            Set<OWLClassExpression> owlAPIDescriptions = owlClass.getEquivalentClasses(new HashSet<OWLOntology>(owlAPIOntologies.get(0).getImportsClosure()));
999            Set<Description> definitions = new HashSet<Description>();
1000            for (OWLClassExpression owlAPIDescription : owlAPIDescriptions) {
1001                definitions.add(DLLearnerDescriptionConvertVisitor.getDLLearnerDescription(owlAPIDescription));
1002            }
1003            return definitions;
1004        }
1005    
1006        /**
1007         * Gets the OWL API ontology manager. Use with great caution.
1008         *
1009         * @return The OWL API ontology manager.
1010         */
1011        public OWLOntologyManager getManager() {
1012            return manager;
1013        }
1014    
1015        /**
1016         * Gets the internal OWL API ontology. Use with great caution.
1017         *
1018         * @return The internal OWL API ontology.
1019         */
1020        public OWLOntology getOntology() {
1021            return ontology;
1022        }
1023    
1024        /**
1025         * Gets the internal OWL API reasoner. Use with great caution.
1026         *
1027         * @return The internal OWL API reasoner.
1028         */
1029        public OWLReasoner getReasoner() {
1030            return reasoner;
1031        }
1032    
1033    }