001/**
002 * Copyright (C) 2007 - 2016, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.dllearner.core;
020
021import com.google.common.collect.HashMultimap;
022import com.google.common.collect.Lists;
023import com.google.common.collect.Multimap;
024import com.google.common.collect.Sets;
025import org.dllearner.core.annotations.NoConfigOption;
026import org.dllearner.core.config.ConfigOption;
027import org.dllearner.core.owl.ClassHierarchy;
028import org.dllearner.core.owl.DatatypePropertyHierarchy;
029import org.dllearner.core.owl.ObjectPropertyHierarchy;
030import org.dllearner.core.owl.fuzzydll.FuzzyIndividual;
031import org.dllearner.reasoning.ReasonerType;
032import org.dllearner.utilities.Helper;
033import org.dllearner.utilities.OWLAPIUtils;
034import org.dllearner.utilities.datastructures.SortedSetTuple;
035import org.semanticweb.owlapi.model.*;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038import org.springframework.beans.factory.annotation.Autowired;
039import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl;
040
041import java.text.NumberFormat;
042import java.text.ParseException;
043import java.util.*;
044import java.util.Map.Entry;
045import java.util.function.Function;
046import java.util.stream.Collectors;
047
048/**
049 * Abstract component representing a reasoner. Only a few reasoning operations
050 * are guaranteed to be implemented by the underlying reasoner, while a
051 * {@link ReasoningMethodUnsupportedException} is thrown for all other methods.
052 * In addition to calling the actual implementations of reasoning operations,
053 * the class also collects statistical information, which can be queried.
054 * 
055 * Guidelines for extending the class:
056 * <ul>
057 * <li>add the needed method to the corresponding interface (currenty
058 * {@link BaseReasoner}, {@link SchemaReasoner}, {@link IndividualReasoner}
059 * exist)</li>
060 * <li>reasoning methods which need to be supported by all reasoners: create
061 * method() and methodImpl() here, where the former is an overridden, final
062 * method delegating to the latter abstract, protected method</li>
063 * <li>reasoning method, which do not need to be supported by all reasoners:
064 * create method() and methodImpl() as before, but this time methodImpl() is not
065 * abstract and throws a {@link ReasoningMethodUnsupportedException} </li>
066 * <li>a few very basic methods (where we do not care about statistics) do not
067 * have an "Impl" variant, e.g. getting all named classes of a KB; those are
068 * directly inherited from the reasoner interface</li>
069 * </ul>
070 * Note, that the method delegation is done to collect statistical information
071 * about reasoning performance, e.g. count how often certain methods were called
072 * and how long it took to execute them.
073 * 
074 * @author Jens Lehmann
075 * 
076 */
077public abstract class AbstractReasonerComponent extends AbstractComponent implements Reasoner, ReasonerComponent {
078
079        public static Logger logger = LoggerFactory.getLogger(AbstractReasonerComponent.class);
080        
081        private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.ROOT);
082        @ConfigOption(description = "whether to use single instance checks", defaultValue = "false")
083        protected boolean useInstanceChecks = false;
084
085        // statistical data for particular reasoning operations
086        private long instanceCheckReasoningTimeNs = 0;
087        private int nrOfInstanceChecks = 0;
088        private int nrOfMultiInstanceChecks = 0;
089        private long retrievalReasoningTimeNs = 0;
090        private int nrOfRetrievals = 0;
091        private long subsumptionReasoningTimeNs = 0;
092        private int nrOfSubsumptionChecks = 0;
093        private int nrOfMultiSubsumptionChecks = 0;
094        private int nrOfSubsumptionHierarchyQueries = 0;
095
096        // rest of reasoning time
097        private long otherReasoningTimeNs = 0;
098
099        // time for all reasoning requests (usually longer than the sum of all
100        // above)
101        private long overallReasoningTimeNs = 0;
102
103        // temporary variables (moved here for performance reasons)
104        private long reasoningStartTimeTmp;
105        private long reasoningDurationTmp;
106
107        // list view
108        private List<OWLClass> atomicConceptsList;
109        private List<OWLObjectProperty> atomicRolesList;
110
111        // hierarchies (they are computed the first time they are needed)
112        @NoConfigOption
113        protected ClassHierarchy subsumptionHierarchy = null;
114        @NoConfigOption
115        protected ObjectPropertyHierarchy roleHierarchy = null;
116        @NoConfigOption
117        protected DatatypePropertyHierarchy datatypePropertyHierarchy = null;
118
119        @ConfigOption(description = "if class hierarchy should be precomputed", defaultValue = "true")
120        protected boolean precomputeClassHierarchy = true;
121        @ConfigOption(defaultValue = "true")
122        protected boolean precomputeObjectPropertyHierarchy = true;
123        @ConfigOption(defaultValue = "true")
124        protected boolean precomputeDataPropertyHierarchy = true;
125        
126        protected OWLDataFactory df = new OWLDataFactoryImpl();
127        
128        protected Multimap<OWLDatatype, OWLDataProperty> datatype2Properties = HashMultimap.create();
129        protected Map<OWLDataProperty, OWLDatatype> dataproperty2datatype = new HashMap<>();
130
131        @ConfigOption(description = "if property domains should be precomputed", defaultValue = "true")
132        protected boolean precomputePropertyDomains = true;
133        protected Map<OWLProperty, OWLClassExpression> propertyDomains = new HashMap<>();
134
135        @ConfigOption(description = "if object property ranges should be precomputed", defaultValue = "true")
136        protected boolean precomputeObjectPropertyRanges = true;
137        protected Map<OWLObjectProperty, OWLClassExpression> objectPropertyRanges = new HashMap<>();
138
139        /**
140         * The underlying knowledge sources.
141         */
142        @ConfigOption(description = "the underlying knowledge sources", required = true)
143        protected Set<KnowledgeSource> sources;
144
145    public AbstractReasonerComponent(){
146
147    }
148        /**
149         * Constructs a new reasoner component.
150         * 
151         * @param sources
152         *            The underlying knowledge sources.
153         */
154        public AbstractReasonerComponent(Set<KnowledgeSource> sources) {
155                this.sources = sources;
156        }
157        
158        public AbstractReasonerComponent(KnowledgeSource source) {
159                this(Collections.singleton(source));
160        }
161
162        /**
163         * Gets the knowledge sources used by this reasoner.
164         * 
165         * @return The underlying knowledge sources.
166         */
167        public Set<KnowledgeSource> getSources() {
168                return sources;
169        }
170
171        @Autowired
172    public void setSources(Set<KnowledgeSource> sources){
173        this.sources = sources;
174    }
175    
176        @Autowired
177    public void setSources(KnowledgeSource... sources) {
178        this.sources = new HashSet<>(Arrays.asList(sources));
179    }
180
181        /**
182         * Method to exchange the reasoner underlying the learning problem.
183         * Implementations, which do not only use the provided sources class
184         * variable, must make sure that a call to this method indeed changes them.
185         * 
186         * @param sources
187         *            The new knowledge sources.
188         */
189        public void changeSources(Set<KnowledgeSource> sources) {
190                this.sources = sources;
191        }
192
193        /**
194         * Gets the type of the underlying reasoner. Although rarely necessary,
195         * applications can use this to adapt their behaviour to the reasoner.
196         * 
197         * @return The reasoner type.
198         */
199        public abstract ReasonerType getReasonerType();
200
201        /**
202         * Reset all statistics. Usually, you do not need to call this. However, if
203         * you e.g. perform benchmarks of learning algorithms and performing
204         * reasoning operations, such as a consistency check, before starting the
205         * algorithm, you can use this method to reset all statistical values.
206         */
207        public void resetStatistics() {
208                instanceCheckReasoningTimeNs = 0;
209                nrOfInstanceChecks = 0;
210                retrievalReasoningTimeNs = 0;
211                nrOfRetrievals = 0;
212                subsumptionReasoningTimeNs = 0;
213                nrOfSubsumptionChecks = 0;
214                // subsumptionHierarchyTimeNs = 0;
215                nrOfSubsumptionHierarchyQueries = 0;
216                otherReasoningTimeNs = 0;
217                overallReasoningTimeNs = 0;
218        }
219
220        /**
221         * Notify the reasoner component that the underlying knowledge base has
222         * changed and all caches (for named classes, subsumption hierarchies, etc.)
223         * should be invalidaded. TODO Currently, nothing is done to behave
224         * correctly after updates.
225         */
226        @NoConfigOption
227        public void setUpdated() {
228                // TODO currently, nothing is done to behave correctly after updates
229        }
230
231        /**
232         * Call this method to release the knowledge base. Not calling the method
233         * may (depending on the underlying reasoner) result in resources for this
234         * knowledge base not being freed, which can cause memory leaks.
235         */
236        public abstract void releaseKB();
237
238        // we cannot expect callers of reasoning methods to reliably recover if
239        // certain reasoning methods are not implemented by the backend; we also
240        // should not require callers to build catch clauses each time they make
241        // a reasoner request => for this reasoner, we throw a runtime exception
242        // here
243        private void handleExceptions(ReasoningMethodUnsupportedException e) {
244                e.printStackTrace();
245                throw new RuntimeException("Reasoning method not supported.", e);
246        }
247
248        @Override
249        public final Set<OWLClass> getTypes(OWLIndividual individual) {
250                Set<OWLClass> types = null;
251                try {
252                        types = getTypesImpl(individual);
253                } catch (ReasoningMethodUnsupportedException e) {
254                        handleExceptions(e);
255                }
256                return types;
257        }
258
259        protected Set<OWLClass> getTypesImpl(OWLIndividual individual)
260                        throws ReasoningMethodUnsupportedException {
261                throw new ReasoningMethodUnsupportedException(
262                                "Reasoner does not support to determine type of individual.");
263        }
264
265        @Override
266        public final boolean isSuperClassOf(OWLClassExpression superClass, OWLClassExpression subClass) {
267                reasoningStartTimeTmp = System.nanoTime();
268                boolean result = false;
269                if(precomputeClassHierarchy) {
270                        if(superClass.isAnonymous() || subClass.isAnonymous()) {
271                                try {
272                                        result = isSuperClassOfImpl(superClass, subClass);
273                                } catch (ReasoningMethodUnsupportedException e) {
274                                        e.printStackTrace();
275                                }
276                        } else {
277                                return getClassHierarchy().isSubclassOf(subClass, superClass);
278                        }
279                } else {
280                        try {
281                                result = isSuperClassOfImpl(superClass, subClass);
282                        } catch (ReasoningMethodUnsupportedException e) {
283                                e.printStackTrace();
284                        }
285                }
286                nrOfSubsumptionChecks++;
287                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
288                subsumptionReasoningTimeNs += reasoningDurationTmp;
289                overallReasoningTimeNs += reasoningDurationTmp;
290                if(logger.isTraceEnabled()) {
291                        logger.trace("reasoner query isSuperClassOf: " + superClass + " " + subClass + " " + result);
292                }
293                return result;
294        }
295
296        protected boolean isSuperClassOfImpl(OWLClassExpression superConcept, OWLClassExpression subConcept)
297                        throws ReasoningMethodUnsupportedException {
298                throw new ReasoningMethodUnsupportedException();
299        }
300
301        @Override
302        public final boolean isEquivalentClass(OWLClassExpression class1, OWLClassExpression class2) {
303                reasoningStartTimeTmp = System.nanoTime();
304                boolean result = false;
305                try {
306                        result = isEquivalentClassImpl(class1, class2);
307                } catch (ReasoningMethodUnsupportedException e) {
308                        handleExceptions(e);
309                }
310                nrOfSubsumptionChecks+=2;
311                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
312                subsumptionReasoningTimeNs += reasoningDurationTmp;
313                overallReasoningTimeNs += reasoningDurationTmp;
314                if(logger.isTraceEnabled()) {
315                        logger.trace("reasoner query isEquivalentClass: " + class1 + " " + class2 + " " + result);
316                }
317                return result;
318        }
319
320        protected boolean isEquivalentClassImpl(OWLClassExpression class1, OWLClassExpression class2) throws ReasoningMethodUnsupportedException {
321                return isSuperClassOfImpl(class1,class2) && isSuperClassOfImpl(class2,class1);
322        }       
323        
324        @Override
325        public final boolean isDisjoint(OWLClass class1, OWLClass class2) {
326                reasoningStartTimeTmp = System.nanoTime();
327                boolean result = false;
328                try {
329                        result = isDisjointImpl(class1, class2);
330                } catch (ReasoningMethodUnsupportedException e) {
331                        handleExceptions(e);
332                }
333                nrOfSubsumptionChecks++;
334                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
335                subsumptionReasoningTimeNs += reasoningDurationTmp;
336                overallReasoningTimeNs += reasoningDurationTmp;
337                if(logger.isTraceEnabled()) {
338                        logger.trace("reasoner query isDisjoint: " + class1 + " " + class2 + " " + result);
339                }
340                return result;
341        }
342
343        protected boolean isDisjointImpl(OWLClass superConcept, OWLClass subConcept)
344                        throws ReasoningMethodUnsupportedException {
345                throw new ReasoningMethodUnsupportedException();
346        }
347        
348        @Override
349        public Set<OWLClassExpression> getAssertedDefinitions(OWLClass namedClass) {
350                try {
351                        return getAssertedDefinitionsImpl(namedClass);
352                } catch (ReasoningMethodUnsupportedException e) {
353                        handleExceptions(e);
354                        return null;
355                }
356        }
357        
358        protected Set<OWLClassExpression> getAssertedDefinitionsImpl(OWLClass namedClass)
359                throws ReasoningMethodUnsupportedException {
360                throw new ReasoningMethodUnsupportedException();
361        }       
362        
363        @Override
364        public final Set<OWLClassExpression> isSuperClassOf(Set<OWLClassExpression> superConcepts,
365                        OWLClassExpression subConcept) {
366                reasoningStartTimeTmp = System.nanoTime();
367                Set<OWLClassExpression> result = null;
368                try {
369                        result = isSuperClassOfImpl(superConcepts, subConcept);
370                } catch (ReasoningMethodUnsupportedException e) {
371                        handleExceptions(e);
372                }
373                nrOfSubsumptionChecks += superConcepts.size();
374                nrOfMultiSubsumptionChecks++;
375                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
376                subsumptionReasoningTimeNs += reasoningDurationTmp;
377                overallReasoningTimeNs += reasoningDurationTmp;
378                return result;
379        }
380
381        protected Set<OWLClassExpression> isSuperClassOfImpl(Set<OWLClassExpression> superConcepts,
382                        OWLClassExpression subConcept) throws ReasoningMethodUnsupportedException {
383                Set<OWLClassExpression> returnSet = superConcepts.stream()
384                                .filter(superConcept -> isSuperClassOf(superConcept, subConcept))
385                                .collect(Collectors.toSet());
386                return returnSet;
387        }
388
389        @Override
390        public final SortedSetTuple<OWLIndividual> doubleRetrieval(OWLClassExpression concept) {
391                reasoningStartTimeTmp = System.nanoTime();
392                SortedSetTuple<OWLIndividual> result;
393                try {
394                        result = doubleRetrievalImpl(concept);
395                } catch (ReasoningMethodUnsupportedException e) {
396                        handleExceptions(e);
397                        return null;
398                }
399                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
400                otherReasoningTimeNs += reasoningDurationTmp;
401                overallReasoningTimeNs += reasoningDurationTmp;
402                return result;
403        }
404
405        protected SortedSetTuple<OWLIndividual> doubleRetrievalImpl(OWLClassExpression concept)
406                        throws ReasoningMethodUnsupportedException {
407                throw new ReasoningMethodUnsupportedException();
408        }
409
410        @Override
411        public final SortedSet<OWLIndividual> getIndividuals(OWLClassExpression concept) {
412                reasoningStartTimeTmp = System.nanoTime();
413                SortedSet<OWLIndividual> result;
414                try {
415                        result = getIndividualsImpl(concept);
416                } catch (ReasoningMethodUnsupportedException e) {
417                        handleExceptions(e);
418                        return null;
419                }
420                nrOfRetrievals++;
421                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
422                retrievalReasoningTimeNs += reasoningDurationTmp;
423                overallReasoningTimeNs += reasoningDurationTmp;
424                if(logger.isTraceEnabled()) {
425                        logger.trace("reasoner query getIndividuals: " + concept + " " + result);
426                }
427                return result;
428        }
429
430        protected SortedSet<OWLIndividual> getIndividualsImpl(OWLClassExpression concept)
431                        throws ReasoningMethodUnsupportedException {
432                throw new ReasoningMethodUnsupportedException();
433        }
434        
435        @Override
436        public final SortedSet<FuzzyIndividual> getFuzzyIndividuals(OWLClassExpression concept) {
437                reasoningStartTimeTmp = System.nanoTime();
438                SortedSet<FuzzyIndividual> result;
439                try {
440                        result = getFuzzyIndividualsImpl(concept);
441                } catch (ReasoningMethodUnsupportedException e) {
442                        handleExceptions(e);
443                        return null;
444                }
445                nrOfRetrievals++;
446                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
447                retrievalReasoningTimeNs += reasoningDurationTmp;
448                overallReasoningTimeNs += reasoningDurationTmp;
449                if(logger.isTraceEnabled()) {
450                        logger.trace("reasoner query getIndividuals: " + concept + " " + result);
451                }
452                return result;
453        }
454
455        protected SortedSet<FuzzyIndividual> getFuzzyIndividualsImpl(OWLClassExpression concept)
456                        throws ReasoningMethodUnsupportedException {
457                throw new ReasoningMethodUnsupportedException();
458        }
459
460        @Override
461        public final boolean hasType(OWLClassExpression concept, OWLIndividual s) {
462                reasoningStartTimeTmp = System.nanoTime();
463                boolean result = false;
464                try {
465                        result = hasTypeImpl(concept, s);
466                } catch (ReasoningMethodUnsupportedException e) {
467                        handleExceptions(e);
468                }
469                nrOfInstanceChecks++;
470                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
471                instanceCheckReasoningTimeNs += reasoningDurationTmp;
472                overallReasoningTimeNs += reasoningDurationTmp;
473                return result;
474        }
475
476        protected boolean hasTypeImpl(OWLClassExpression concept, OWLIndividual individual)
477                        throws ReasoningMethodUnsupportedException {
478                throw new ReasoningMethodUnsupportedException();
479        }
480
481        @Override
482        public final SortedSet<OWLIndividual> hasType(OWLClassExpression concept, Set<OWLIndividual> s) {
483                // logger.debug("instanceCheck "+concept.toKBSyntaxString());
484                reasoningStartTimeTmp = System.nanoTime();
485                SortedSet<OWLIndividual> result = null;
486                try {
487                        result = hasTypeImpl(concept, s);
488                } catch (ReasoningMethodUnsupportedException e) {
489                        handleExceptions(e);
490                }
491                nrOfInstanceChecks += s.size();
492                nrOfMultiInstanceChecks++;
493                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
494                instanceCheckReasoningTimeNs += reasoningDurationTmp;
495                overallReasoningTimeNs += reasoningDurationTmp;
496                // logger.debug("instanceCheck done");
497                return result;
498        }
499
500        protected SortedSet<OWLIndividual> hasTypeImpl(OWLClassExpression concept, Set<OWLIndividual> individuals) throws ReasoningMethodUnsupportedException {
501                SortedSet<OWLIndividual> returnSet = individuals.stream()
502                                .filter(individual -> hasType(concept, individual))
503                                .collect(Collectors.toCollection(TreeSet::new));
504                return returnSet;
505        }
506
507        @Override
508        public final Set<OWLClass> getInconsistentClasses() {
509                try {
510                        return getInconsistentClassesImpl();
511                } catch (ReasoningMethodUnsupportedException e) {
512                        handleExceptions(e);
513                        return null;
514                }
515        }
516
517        protected Set<OWLClass> getInconsistentClassesImpl()
518                        throws ReasoningMethodUnsupportedException {
519                throw new ReasoningMethodUnsupportedException();
520        }
521
522        @Override
523        public final boolean isSatisfiable() {
524                reasoningStartTimeTmp = System.nanoTime();
525                boolean result;
526                try {
527                        result = isSatisfiableImpl();
528                } catch (ReasoningMethodUnsupportedException e) {
529                        handleExceptions(e);
530                        return false;
531                }
532                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
533                otherReasoningTimeNs += reasoningDurationTmp;
534                overallReasoningTimeNs += reasoningDurationTmp;
535                return result;
536        }
537
538        protected boolean isSatisfiableImpl() throws ReasoningMethodUnsupportedException {
539                throw new ReasoningMethodUnsupportedException();
540        }
541
542        @Override
543        public final boolean remainsSatisfiable(OWLAxiom axiom) {
544                reasoningStartTimeTmp = System.nanoTime();
545                boolean result;
546                try {
547                        result = remainsSatisfiableImpl(axiom);
548                } catch (ReasoningMethodUnsupportedException e) {
549                        handleExceptions(e);
550                        return false;
551                }
552                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
553                otherReasoningTimeNs += reasoningDurationTmp;
554                overallReasoningTimeNs += reasoningDurationTmp;
555                return result;
556        }
557
558        protected boolean remainsSatisfiableImpl(OWLAxiom axiom) throws ReasoningMethodUnsupportedException {
559                throw new ReasoningMethodUnsupportedException();
560        }       
561        
562        @Override
563        public final Map<OWLObjectProperty,Set<OWLIndividual>> getObjectPropertyRelationships(OWLIndividual individual) {
564                try {
565                        return getObjectPropertyRelationshipsImpl(individual);
566                } catch (ReasoningMethodUnsupportedException e) {
567                        handleExceptions(e);
568                        return null;
569                }               
570        }
571        
572        protected Map<OWLObjectProperty,Set<OWLIndividual>> getObjectPropertyRelationshipsImpl(OWLIndividual individual) throws ReasoningMethodUnsupportedException {
573                throw new ReasoningMethodUnsupportedException();
574        }
575        
576        @Override
577        public final Map<OWLDataProperty, Set<OWLLiteral>> getDataPropertyRelationships(OWLIndividual individual) {
578                try {
579                        return getDataPropertyRelationshipsImpl(individual);
580                } catch (ReasoningMethodUnsupportedException e) {
581                        handleExceptions(e);
582                        return null;
583                }
584        }
585
586        protected Map<OWLDataProperty, Set<OWLLiteral>> getDataPropertyRelationshipsImpl(OWLIndividual individual)
587                        throws ReasoningMethodUnsupportedException {
588                throw new ReasoningMethodUnsupportedException();
589        }
590                        
591        
592        @Override
593        public final Set<OWLIndividual> getRelatedIndividuals(OWLIndividual individual,
594                        OWLObjectProperty objectProperty) {
595                try {
596                        return getRelatedIndividualsImpl(individual, objectProperty);
597                } catch (ReasoningMethodUnsupportedException e) {
598                        handleExceptions(e);
599                        return null;
600                }
601        }
602
603        protected Set<OWLIndividual> getRelatedIndividualsImpl(OWLIndividual individual,
604                        OWLObjectProperty objectProperty) throws ReasoningMethodUnsupportedException {
605                throw new ReasoningMethodUnsupportedException();
606        }
607
608        @Override
609        public final Set<OWLLiteral> getRelatedValues(OWLIndividual individual,
610                        OWLDataProperty datatypeProperty) {
611                try {
612                        return getRelatedValuesImpl(individual, datatypeProperty);
613                } catch (ReasoningMethodUnsupportedException e) {
614                        handleExceptions(e);
615                        return null;
616                }
617        }
618
619        protected Set<OWLLiteral> getRelatedValuesImpl(OWLIndividual individual,
620                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
621                throw new ReasoningMethodUnsupportedException();
622        }
623
624        @Override
625        public final Set<OWLLiteral> getLabel(OWLEntity entity) {
626                try {
627                        return getLabelImpl(entity);
628                } catch (ReasoningMethodUnsupportedException e) {
629                        handleExceptions(e);
630                        return null;
631                }
632        }
633
634        protected Set<OWLLiteral> getLabelImpl(OWLEntity entity) throws ReasoningMethodUnsupportedException {
635                throw new ReasoningMethodUnsupportedException();
636        }
637
638        @Override
639        public final Map<OWLIndividual, SortedSet<OWLIndividual>> getPropertyMembers(OWLObjectProperty atomicRole) {
640                reasoningStartTimeTmp = System.nanoTime();
641                Map<OWLIndividual, SortedSet<OWLIndividual>> result;
642                try {
643                        result = getPropertyMembersImpl(atomicRole);
644                } catch (ReasoningMethodUnsupportedException e) {
645                        handleExceptions(e);
646                        return null;
647                }
648                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
649                otherReasoningTimeNs += reasoningDurationTmp;
650                overallReasoningTimeNs += reasoningDurationTmp;
651                return result;
652        }
653
654        protected Map<OWLIndividual, SortedSet<OWLIndividual>> getPropertyMembersImpl(
655                        OWLObjectProperty atomicRole) throws ReasoningMethodUnsupportedException {
656                throw new ReasoningMethodUnsupportedException();
657        }
658
659        @Override
660        public final Map<OWLIndividual, SortedSet<OWLLiteral>> getDatatypeMembers(
661                        OWLDataProperty datatypeProperty) {
662                try {
663                        return getDatatypeMembersImpl(datatypeProperty);
664                } catch (ReasoningMethodUnsupportedException e) {
665                        handleExceptions(e);
666                        return null;
667                }
668        }
669
670        protected Map<OWLIndividual, SortedSet<OWLLiteral>> getDatatypeMembersImpl(
671                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
672                throw new ReasoningMethodUnsupportedException();
673        }
674
675        @Override
676        public final Map<OWLIndividual, SortedSet<Double>> getDoubleDatatypeMembers(
677                        OWLDataProperty datatypeProperty) {
678                try {
679                        return getDoubleDatatypeMembersImpl(datatypeProperty);
680                } catch (ReasoningMethodUnsupportedException e) {
681                        handleExceptions(e);
682                        return null;
683                }
684        }
685
686        protected Map<OWLIndividual, SortedSet<Double>> getDoubleDatatypeMembersImpl(
687                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
688                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
689                Map<OWLIndividual, SortedSet<Double>> ret = new TreeMap<>();
690                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
691                        SortedSet<OWLLiteral> values = e.getValue();
692                        SortedSet<Double> valuesDouble = values.stream()
693                                        .filter(lit -> OWLAPIUtils.floatDatatypes.contains(lit.getDatatype()))
694                                        .map(lit -> Double.parseDouble(lit.getLiteral()))
695                                        .collect(Collectors.toCollection(TreeSet::new));
696                        ret.put(e.getKey(), valuesDouble);
697                }
698                return ret;
699        }
700        
701        @Override
702        public final <T extends Number> Map<OWLIndividual, SortedSet<T>> getNumericDatatypeMembers(
703                        OWLDataProperty datatypeProperty, Class<T> clazz) {
704                try {
705                        return getNumericDatatypeMembersImpl(datatypeProperty, clazz);
706                } catch (ReasoningMethodUnsupportedException e) {
707                        handleExceptions(e);
708                        return null;
709                }
710        }
711        
712        protected <T extends Number> Map<OWLIndividual, SortedSet<T>> getNumericDatatypeMembersImpl(
713                        OWLDataProperty datatypeProperty, Class<T> clazz) throws ReasoningMethodUnsupportedException {
714                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
715                Map<OWLIndividual, SortedSet<T>> ret = new TreeMap<>();
716                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
717                        SortedSet<OWLLiteral> values = e.getValue();
718                        SortedSet<T> numericValues = new TreeSet<>();
719                        for (OWLLiteral lit : values) {
720                                try {
721                                        numericValues.add((T) numberFormat.parse(lit.getLiteral()));
722                                } catch (ParseException e1) {
723                                        e1.printStackTrace();
724                                }
725                        }
726                        ret.put(e.getKey(), numericValues);
727                }
728                return ret;
729        }
730        
731        @Override
732        public final <T extends Number & Comparable<T>> Map<OWLIndividual, SortedSet<T>> getNumericDatatypeMembers(
733                        OWLDataProperty datatypeProperty) {
734                try {
735                        return getNumericDatatypeMembersImpl(datatypeProperty);
736                } catch (ReasoningMethodUnsupportedException e) {
737                        handleExceptions(e);
738                        return null;
739                }
740        }
741        
742        protected <T extends Number & Comparable<T>> Map<OWLIndividual, SortedSet<T>> getNumericDatatypeMembersImpl(
743                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
744                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
745                Map<OWLIndividual, SortedSet<T>> ret = new TreeMap<>();
746                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> entry : mapping.entrySet()) {
747                        OWLIndividual ind = entry.getKey();
748                        SortedSet<OWLLiteral> values = entry.getValue();
749                        SortedSet<T> numericValues = new TreeSet<>();
750                        for (OWLLiteral lit : values) {
751                                if(OWLAPIUtils.isIntegerDatatype(lit)) {
752                                        numericValues.add((T) Integer.valueOf(lit.parseInteger()));
753                                } else {
754                                        try {
755                                                Number number;
756                                                String litStr = lit.getLiteral();
757                                                if(litStr.equalsIgnoreCase("NAN")) {
758                                                        number = Double.NaN;
759                                                } else {
760                                                        number = numberFormat.parse(litStr);
761                                                        if(number instanceof Long) {
762                                                                number = Double.valueOf(number.toString());
763                                                        }
764                                                }
765                                                numericValues.add((T) (number) );
766                                        } catch (ParseException e) {
767                                                e.printStackTrace();
768                                        }
769                                }
770                                
771                        }
772                        ret.put(ind, numericValues);
773                }
774                return ret;
775        }
776
777        @Override
778        public final Map<OWLIndividual, SortedSet<Integer>> getIntDatatypeMembers(
779                        OWLDataProperty datatypeProperty) {
780                try {
781                        return getIntDatatypeMembersImpl(datatypeProperty);
782                } catch (ReasoningMethodUnsupportedException e) {
783                        handleExceptions(e);
784                        return null;
785                }
786        }
787
788        protected Map<OWLIndividual, SortedSet<Integer>> getIntDatatypeMembersImpl(
789                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
790                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
791                Map<OWLIndividual, SortedSet<Integer>> ret = new TreeMap<>();
792                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
793                        SortedSet<OWLLiteral> values = e.getValue();
794                        SortedSet<Integer> valuesInt = values.stream()
795                                        .filter(lit -> OWLAPIUtils.isIntegerDatatype(lit))
796                                        .map((Function<OWLLiteral, Integer>) OWLLiteral::parseInteger)
797                                        .collect(Collectors.toCollection(TreeSet::new));
798                        ret.put(e.getKey(), valuesInt);
799                }
800                return ret;
801        }
802
803        @Override
804        public final Map<OWLIndividual, SortedSet<Boolean>> getBooleanDatatypeMembers(
805                        OWLDataProperty datatypeProperty) {
806                try {
807                        return getBooleanDatatypeMembersImpl(datatypeProperty);
808                } catch (ReasoningMethodUnsupportedException e) {
809                        handleExceptions(e);
810                        return null;
811                }
812        }
813
814        protected Map<OWLIndividual, SortedSet<Boolean>> getBooleanDatatypeMembersImpl(
815                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
816                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
817                Map<OWLIndividual, SortedSet<Boolean>> ret = new TreeMap<>();
818                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
819                        SortedSet<OWLLiteral> values = e.getValue();
820                        SortedSet<Boolean> valuesBoolean = new TreeSet<>();
821                        for (OWLLiteral c : values) {
822                                String s = c.getLiteral();
823                                if (s.equalsIgnoreCase("true")) {
824                                        valuesBoolean.add(true);
825                                } else if (s.equalsIgnoreCase("false")) {
826                                        valuesBoolean.add(false);
827                                } else {
828                                        logger.warn("Requested to parse boolean value of property " + datatypeProperty
829                                                        + ", but " + c + " could not be parsed successfully.");
830                                }
831                        }
832                        ret.put(e.getKey(), valuesBoolean);
833                }
834                return ret;
835        }
836
837        @Override
838        public final SortedSet<OWLIndividual> getTrueDatatypeMembers(OWLDataProperty datatypeProperty) {
839                try {
840                        return getTrueDatatypeMembersImpl(datatypeProperty);
841                } catch (ReasoningMethodUnsupportedException e) {
842                        handleExceptions(e);
843                        return null;
844                }
845        }
846
847        protected SortedSet<OWLIndividual> getTrueDatatypeMembersImpl(OWLDataProperty datatypeProperty)
848                        throws ReasoningMethodUnsupportedException {
849                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
850                SortedSet<OWLIndividual> ret = new TreeSet<>();
851                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
852                        SortedSet<OWLLiteral> values = e.getValue();
853                        if (values.size() > 1) {
854                                logger.warn("Property " + datatypeProperty + " has more than one value " + e.getValue()
855                                                + " for individual " + e.getKey() + ". We ignore the value.");                  
856                        } else {
857                                if (values.first().getLiteral().equalsIgnoreCase("true")) {
858                                        ret.add(e.getKey());
859                                }
860                        }
861                }
862                return ret;
863        }
864
865        @Override
866        public final SortedSet<OWLIndividual> getFalseDatatypeMembers(OWLDataProperty datatypeProperty) {
867                try {
868                        return getFalseDatatypeMembersImpl(datatypeProperty);
869                } catch (ReasoningMethodUnsupportedException e) {
870                        handleExceptions(e);
871                        return null;
872                }
873        }
874
875        protected SortedSet<OWLIndividual> getFalseDatatypeMembersImpl(OWLDataProperty datatypeProperty)
876                        throws ReasoningMethodUnsupportedException {
877                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
878                SortedSet<OWLIndividual> ret = new TreeSet<>();
879                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
880                        SortedSet<OWLLiteral> values = e.getValue();
881                        if (values.size() > 1) {
882                                logger.warn("Property " + datatypeProperty + " has value " + e.getValue()
883                                                + ". Cannot determine whether it is false.");
884                        } else {
885                                if (values.first().getLiteral().equalsIgnoreCase("false")) {
886                                        ret.add(e.getKey());
887                                }
888                        }
889                }
890                return ret;
891        }
892
893        @Override
894        public final Map<OWLIndividual, SortedSet<String>> getStringDatatypeMembers(
895                        OWLDataProperty datatypeProperty) {
896                try {
897                        return getStringDatatypeMembersImpl(datatypeProperty);
898                } catch (ReasoningMethodUnsupportedException e) {
899                        handleExceptions(e);
900                        return null;
901                }
902        }
903
904        protected Map<OWLIndividual, SortedSet<String>> getStringDatatypeMembersImpl(
905                        OWLDataProperty datatypeProperty) throws ReasoningMethodUnsupportedException {
906                Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = getDatatypeMembersImpl(datatypeProperty);
907                Map<OWLIndividual, SortedSet<String>> ret = new TreeMap<>();
908                for (Entry<OWLIndividual, SortedSet<OWLLiteral>> e : mapping.entrySet()) {
909                        SortedSet<OWLLiteral> values = e.getValue();
910                        SortedSet<String> valuesString = values.stream()
911                                        .map(OWLLiteral::getLiteral)
912                                        .collect(Collectors.toCollection(TreeSet::new));
913                        ret.put(e.getKey(), valuesString);
914                }
915                return ret;
916        }
917        
918        @Override
919        public final Set<OWLObjectProperty> getObjectProperties() {
920                try {
921                        return getObjectPropertiesImpl();
922                } catch (ReasoningMethodUnsupportedException e) {
923                        handleExceptions(e);
924                        return null;
925                }
926        }
927
928        protected Set<OWLObjectProperty> getObjectPropertiesImpl()
929                        throws ReasoningMethodUnsupportedException {
930                throw new ReasoningMethodUnsupportedException();
931        }
932        
933        @Override
934        public final Set<OWLDataProperty> getDatatypeProperties() {
935                try {
936                        return getDatatypePropertiesImpl();
937                } catch (ReasoningMethodUnsupportedException e) {
938                        handleExceptions(e);
939                        return null;
940                }
941        }
942
943        protected Set<OWLDataProperty> getDatatypePropertiesImpl()
944                        throws ReasoningMethodUnsupportedException {
945                throw new ReasoningMethodUnsupportedException();
946        }
947
948        @Override
949        public final Set<OWLDataProperty> getBooleanDatatypeProperties() {
950                try {
951                        return getBooleanDatatypePropertiesImpl();
952                } catch (ReasoningMethodUnsupportedException e) {
953                        handleExceptions(e);
954                        return null;
955                }
956        }
957
958        // TODO Even if there is a small performance penalty, we could implement
959        // the method right here by iterating over all data properties and
960        // querying their ranges. At least, this should be done once we have a
961        // reasoner independent of OWL API with datatype support.
962        protected Set<OWLDataProperty> getBooleanDatatypePropertiesImpl()
963                        throws ReasoningMethodUnsupportedException {
964                throw new ReasoningMethodUnsupportedException();
965        }
966        
967        @Override
968        public final Set<OWLDataProperty> getNumericDataProperties() {
969                try {
970                        return getNumericDataPropertiesImpl();
971                } catch (ReasoningMethodUnsupportedException e) {
972                        handleExceptions(e);
973                        return null;
974                }
975        }
976
977        protected Set<OWLDataProperty> getNumericDataPropertiesImpl()
978                        throws ReasoningMethodUnsupportedException {
979                return Sets.union(getIntDatatypePropertiesImpl(), getDoubleDatatypePropertiesImpl());
980        }
981
982        @Override
983        public final Set<OWLDataProperty> getIntDatatypeProperties() {
984                try {
985                        return getIntDatatypePropertiesImpl();
986                } catch (ReasoningMethodUnsupportedException e) {
987                        handleExceptions(e);
988                        return null;
989                }
990        }
991
992        protected Set<OWLDataProperty> getIntDatatypePropertiesImpl()
993                        throws ReasoningMethodUnsupportedException {
994                throw new ReasoningMethodUnsupportedException();
995        }
996
997        @Override
998        public final Set<OWLDataProperty> getDoubleDatatypeProperties() {
999                try {
1000                        return getDoubleDatatypePropertiesImpl();
1001                } catch (ReasoningMethodUnsupportedException e) {
1002                        handleExceptions(e);
1003                        return null;
1004                }
1005        }
1006
1007        protected Set<OWLDataProperty> getDoubleDatatypePropertiesImpl()
1008                        throws ReasoningMethodUnsupportedException {
1009                throw new ReasoningMethodUnsupportedException();
1010        }
1011
1012        @Override
1013        public final Set<OWLDataProperty> getStringDatatypeProperties() {
1014                try {
1015                        return getStringDatatypePropertiesImpl();
1016                } catch (ReasoningMethodUnsupportedException e) {
1017                        handleExceptions(e);
1018                        return null;
1019                }
1020        }
1021
1022        protected Set<OWLDataProperty> getStringDatatypePropertiesImpl()
1023                        throws ReasoningMethodUnsupportedException {
1024                throw new ReasoningMethodUnsupportedException();
1025        }       
1026        
1027        @Override
1028        public final OWLClassExpression getDomain(OWLObjectProperty objectProperty) {
1029                try {
1030                        return getDomainImpl(objectProperty);
1031                } catch (ReasoningMethodUnsupportedException e) {
1032                        handleExceptions(e);
1033                        return null;
1034                }
1035        }
1036
1037        protected OWLClassExpression getDomainImpl(OWLObjectProperty objectProperty)
1038                        throws ReasoningMethodUnsupportedException {
1039                throw new ReasoningMethodUnsupportedException();
1040        }
1041
1042        @Override
1043        public final OWLClassExpression getDomain(OWLDataProperty datatypeProperty) {
1044                try {
1045                        return getDomainImpl(datatypeProperty);
1046                } catch (ReasoningMethodUnsupportedException e) {
1047                        handleExceptions(e);
1048                        return null;
1049                }
1050        }
1051
1052        protected OWLClassExpression getDomainImpl(OWLDataProperty datatypeProperty)
1053                        throws ReasoningMethodUnsupportedException {
1054                throw new ReasoningMethodUnsupportedException();
1055        }
1056
1057        @Override
1058        public final OWLClassExpression getRange(OWLObjectProperty objectProperty) {
1059                try {
1060                        return getRangeImpl(objectProperty);
1061                } catch (ReasoningMethodUnsupportedException e) {
1062                        handleExceptions(e);
1063                        return null;
1064                }
1065        }
1066
1067        protected OWLClassExpression getRangeImpl(OWLObjectProperty objectProperty)
1068                        throws ReasoningMethodUnsupportedException {
1069                throw new ReasoningMethodUnsupportedException();
1070        }
1071
1072        @Override
1073        public final OWLDataRange getRange(OWLDataProperty datatypeProperty) {
1074                try {
1075                        return getRangeImpl(datatypeProperty);
1076                } catch (ReasoningMethodUnsupportedException e) {
1077                        handleExceptions(e);
1078                        return null;
1079                }
1080        }
1081
1082        protected OWLDataRange getRangeImpl(OWLDataProperty datatypeProperty)
1083                        throws ReasoningMethodUnsupportedException {
1084                throw new ReasoningMethodUnsupportedException();
1085        }
1086
1087        @Override
1088        public final SortedSet<OWLClassExpression> getSuperClasses(OWLClassExpression concept) {
1089                if(precomputeClassHierarchy) {
1090                        return getClassHierarchy().getSuperClasses(concept, true);
1091                } else {
1092                        try {
1093                                return getSuperClassesImpl(concept);
1094                        } catch (ReasoningMethodUnsupportedException e) {
1095                                e.printStackTrace();
1096                        }
1097                }
1098                return null;
1099        }
1100
1101        protected SortedSet<OWLClassExpression> getSuperClassesImpl(OWLClassExpression concept) throws ReasoningMethodUnsupportedException {
1102                throw new ReasoningMethodUnsupportedException();
1103        }
1104        
1105        @Override
1106        public final SortedSet<OWLClassExpression> getSubClasses(OWLClassExpression concept) {
1107                if(precomputeClassHierarchy) {
1108                        return getClassHierarchy().getSubClasses(concept, true);
1109                } else {
1110                        try {
1111                                return getSubClassesImpl(concept);
1112                        } catch (ReasoningMethodUnsupportedException e) {
1113                                e.printStackTrace();
1114                        }
1115                }
1116                return null;
1117        }
1118
1119        protected SortedSet<OWLClassExpression> getSubClassesImpl(OWLClassExpression concept) throws ReasoningMethodUnsupportedException {
1120                throw new ReasoningMethodUnsupportedException();
1121        }
1122        
1123        public final SortedSet<OWLClassExpression> getEquivalentClasses(OWLClassExpression concept) {
1124                return new TreeSet<>(Sets.intersection(getClassHierarchy().getSubClasses(concept), getClassHierarchy().getSuperClasses(concept)));
1125        }
1126        
1127        @Override
1128        public final <T extends OWLProperty> SortedSet<T> getSuperProperties(T role) {
1129                if(OWLObjectProperty.class.isInstance(role) && precomputeObjectPropertyHierarchy) {
1130                        return (SortedSet<T>) getObjectPropertyHierarchy().getMoreGeneralRoles((OWLObjectProperty) role);
1131                } else if(OWLDataProperty.class.isInstance(role) && precomputeDataPropertyHierarchy) {
1132                        return (SortedSet<T>) getDatatypePropertyHierarchy().getMoreGeneralRoles((OWLDataProperty) role);
1133                } else {
1134                        try {
1135                                return getSuperPropertiesImpl(role);
1136                        } catch (ReasoningMethodUnsupportedException e) {
1137                                e.printStackTrace();
1138                        }
1139                }
1140                return null;
1141        }
1142        
1143        protected <T extends OWLProperty> SortedSet<T> getSuperPropertiesImpl(T role) throws ReasoningMethodUnsupportedException {
1144                if(OWLObjectProperty.class.isInstance(role)) {
1145                        return (SortedSet<T>) getSuperPropertiesImpl((OWLObjectProperty) role);
1146                } else if(OWLDataProperty.class.isInstance(role)) {
1147                        return (SortedSet<T>) getSuperPropertiesImpl((OWLDataProperty) role);
1148                }
1149                throw new ReasoningMethodUnsupportedException();
1150        }
1151        
1152        @Override
1153        public final <T extends OWLProperty> SortedSet<T> getSubProperties(T role) {
1154                if(OWLObjectProperty.class.isInstance(role) && precomputeObjectPropertyHierarchy) {
1155                        return (SortedSet<T>) getObjectPropertyHierarchy().getMoreSpecialRoles((OWLObjectProperty) role);
1156                } else if(OWLDataProperty.class.isInstance(role) && precomputeDataPropertyHierarchy) {
1157                        return (SortedSet<T>) getDatatypePropertyHierarchy().getMoreSpecialRoles((OWLDataProperty) role);
1158                } else {
1159                        try {
1160                                return getSubPropertiesImpl(role);
1161                        } catch (ReasoningMethodUnsupportedException e) {
1162                                e.printStackTrace();
1163                        }
1164                }
1165                return null;
1166        }
1167        
1168        protected <T extends OWLProperty> SortedSet<T> getSubPropertiesImpl(T role) throws ReasoningMethodUnsupportedException {
1169                if(OWLObjectProperty.class.isInstance(role)) {
1170                        return (SortedSet<T>) getSubPropertiesImpl((OWLObjectProperty) role);
1171                } else if(OWLDataProperty.class.isInstance(role)) {
1172                        return (SortedSet<T>) getSubPropertiesImpl((OWLDataProperty) role);
1173                }
1174                throw new ReasoningMethodUnsupportedException();
1175        }
1176
1177        protected <T extends OWLProperty> OWLClassExpression getDomain(T role) {
1178                if(precomputePropertyDomains) {
1179                        return propertyDomains.get(role);
1180                } else {
1181                        try {
1182                                return getDomainImpl(role);
1183                        } catch (ReasoningMethodUnsupportedException e) {
1184                                e.printStackTrace();
1185                        }
1186                }
1187                throw null;
1188        }
1189
1190        protected <T extends OWLProperty> OWLClassExpression getDomainImpl(T role) throws ReasoningMethodUnsupportedException {
1191                if(OWLObjectProperty.class.isInstance(role)) {
1192                        return getDomainImpl((OWLObjectProperty) role);
1193                } else if(OWLDataProperty.class.isInstance(role)) {
1194                        return getDomainImpl((OWLDataProperty) role);
1195                }
1196                throw new ReasoningMethodUnsupportedException();
1197        }
1198        
1199        
1200        @Override
1201        public final SortedSet<OWLObjectProperty> getSuperProperties(OWLObjectProperty role) {
1202                if(precomputeObjectPropertyHierarchy) {
1203                        return getObjectPropertyHierarchy().getMoreGeneralRoles(role);
1204                } else {
1205                        try {
1206                                return getSuperPropertiesImpl(role);
1207                        } catch (ReasoningMethodUnsupportedException e) {
1208                                e.printStackTrace();
1209                        }
1210                }
1211                return null;
1212        }
1213        
1214        protected SortedSet<OWLObjectProperty> getSuperPropertiesImpl(OWLObjectProperty role) throws ReasoningMethodUnsupportedException {
1215                throw new ReasoningMethodUnsupportedException();
1216        }       
1217        
1218        @Override
1219        public final SortedSet<OWLObjectProperty> getSubProperties(OWLObjectProperty role) {
1220                if(precomputeObjectPropertyHierarchy) {
1221                        return getObjectPropertyHierarchy().getMoreSpecialRoles(role);
1222                } else {
1223                        try {
1224                                return getSuperPropertiesImpl(role);
1225                        } catch (ReasoningMethodUnsupportedException e) {
1226                                e.printStackTrace();
1227                        }
1228                }
1229                return null;
1230        }
1231
1232        protected SortedSet<OWLObjectProperty> getSubPropertiesImpl(OWLObjectProperty role) throws ReasoningMethodUnsupportedException {
1233                throw new ReasoningMethodUnsupportedException();
1234        }       
1235        
1236        @Override
1237        public final SortedSet<OWLObjectProperty> getMostGeneralProperties() {
1238                return getObjectPropertyHierarchy().getMostGeneralRoles();
1239        }
1240
1241//      protected SortedSet<OWLObjectProperty> getMostGeneralPropertiesImpl(OWLOWLObjectProperty role) throws ReasoningMethodUnsupportedException {
1242//              throw new ReasoningMethodUnsupportedException();
1243//      }       
1244        
1245        @Override
1246        public final SortedSet<OWLObjectProperty> getMostSpecialProperties() {
1247                return getObjectPropertyHierarchy().getMostSpecialRoles();
1248        }
1249
1250//      protected SortedSet<OWLObjectProperty> getMostSpecialPropertiesImpl(OWLOWLObjectProperty role) throws ReasoningMethodUnsupportedException {
1251//              throw new ReasoningMethodUnsupportedException();
1252//      }
1253        
1254        @Override
1255        public final SortedSet<OWLDataProperty> getSuperProperties(OWLDataProperty role) {
1256                return getDatatypePropertyHierarchy().getMoreGeneralRoles(role);
1257        }
1258
1259        protected SortedSet<OWLDataProperty> getSuperPropertiesImpl(OWLDataProperty role) throws ReasoningMethodUnsupportedException {
1260                throw new ReasoningMethodUnsupportedException();
1261        }               
1262        
1263        @Override
1264        public final SortedSet<OWLDataProperty> getSubProperties(OWLDataProperty role) {
1265                return getDatatypePropertyHierarchy().getMoreSpecialRoles(role);
1266        }
1267
1268        protected SortedSet<OWLDataProperty> getSubPropertiesImpl(OWLDataProperty role) throws ReasoningMethodUnsupportedException {
1269                throw new ReasoningMethodUnsupportedException();
1270        }               
1271        
1272        @Override
1273        public final SortedSet<OWLDataProperty> getMostGeneralDatatypeProperties() {
1274                return getDatatypePropertyHierarchy().getMostGeneralRoles();
1275        }
1276
1277        @Override
1278        public final SortedSet<OWLDataProperty> getMostSpecialDatatypeProperties() {
1279                return getDatatypePropertyHierarchy().getMostSpecialRoles();
1280        }
1281
1282        /**
1283         * Creates the class hierarchy. Invoking this method is optional (if not
1284         * called explicitly, it is called the first time, it is needed).
1285         * 
1286         * @return The class hierarchy.
1287         * @throws ReasoningMethodUnsupportedException If any method needed to
1288         * create the hierarchy is not supported by the underlying reasoner.
1289         */
1290        public ClassHierarchy prepareSubsumptionHierarchy() throws ReasoningMethodUnsupportedException {
1291                TreeMap<OWLClassExpression, SortedSet<OWLClassExpression>> subsumptionHierarchyUp = new TreeMap<>(
1292                );
1293                TreeMap<OWLClassExpression, SortedSet<OWLClassExpression>> subsumptionHierarchyDown = new TreeMap<>(
1294                );
1295
1296                // parents/children of top ...
1297                SortedSet<OWLClassExpression> tmp = getSubClassesImpl(df.getOWLThing());
1298                subsumptionHierarchyUp.put(df.getOWLThing(), new TreeSet<>());
1299                subsumptionHierarchyDown.put(df.getOWLThing(), tmp);
1300
1301                // ... bottom ...
1302                tmp = getSuperClassesImpl(df.getOWLNothing());
1303                subsumptionHierarchyUp.put(df.getOWLNothing(), tmp);
1304                subsumptionHierarchyDown.put(df.getOWLNothing(), new TreeSet<>());
1305                
1306                // ... and named classes
1307                Set<OWLClass> atomicConcepts = getClasses();
1308                for (OWLClass atom : atomicConcepts) {
1309                        tmp = getSubClassesImpl(atom);
1310                        // quality control: we explicitly check that no reasoner implementation returns null here
1311                        if(tmp == null) {
1312                                logger.error("Class hierarchy: getSubClasses returned null instead of empty set."); 
1313                        }                       
1314                        subsumptionHierarchyDown.put(atom, tmp);
1315
1316                        tmp = getSuperClassesImpl(atom);
1317                        // quality control: we explicitly check that no reasoner implementation returns null here
1318                        if(tmp == null) {
1319                                logger.error("Class hierarchy: getSuperClasses returned null instead of empty set."); 
1320                        }                       
1321                        subsumptionHierarchyUp.put(atom, tmp);
1322                }               
1323
1324                return new ClassHierarchy(subsumptionHierarchyUp, subsumptionHierarchyDown);
1325        }
1326
1327        @Override
1328        public final ClassHierarchy getClassHierarchy() {
1329                // class hierarchy is created on first invocation
1330                if (subsumptionHierarchy == null) {
1331                        try {
1332                                subsumptionHierarchy = prepareSubsumptionHierarchy();
1333                        } catch (ReasoningMethodUnsupportedException e) {
1334                                handleExceptions(e);
1335                        }
1336                }
1337                return subsumptionHierarchy;
1338        }
1339
1340        /**
1341         * Creates the object property hierarchy. Invoking this method is optional
1342         * (if not called explicitly, it is called the first time, it is needed).
1343         * 
1344         * @return The object property hierarchy.
1345         * @throws ReasoningMethodUnsupportedException
1346         *             Thrown if a reasoning method for object property 
1347         *             hierarchy creation is not supported by the reasoner.
1348         */
1349        public ObjectPropertyHierarchy prepareObjectPropertyHierarchy()
1350                        throws ReasoningMethodUnsupportedException {
1351                
1352                TreeMap<OWLObjectProperty, SortedSet<OWLObjectProperty>> roleHierarchyUp = new TreeMap<>(
1353                );
1354                TreeMap<OWLObjectProperty, SortedSet<OWLObjectProperty>> roleHierarchyDown = new TreeMap<>(
1355                );
1356 
1357                Set<OWLObjectProperty> atomicRoles = getObjectProperties();
1358                for (OWLObjectProperty role : atomicRoles) {
1359                        roleHierarchyDown.put(role, getSubPropertiesImpl(role));
1360                        roleHierarchyUp.put(role, getSuperPropertiesImpl(role));
1361                }
1362
1363                roleHierarchy = new ObjectPropertyHierarchy(roleHierarchyUp, roleHierarchyDown);
1364                return roleHierarchy;           
1365        }
1366
1367        @Override
1368        public final ObjectPropertyHierarchy getObjectPropertyHierarchy() {
1369                try {
1370                        if (roleHierarchy == null) {
1371                                roleHierarchy = prepareObjectPropertyHierarchy();
1372                        }
1373                } catch (ReasoningMethodUnsupportedException e) {
1374                        handleExceptions(e);
1375                }
1376
1377                return roleHierarchy;
1378        }
1379        
1380        public boolean isSubPropertyOf(OWLProperty subProperty, OWLProperty superProperty){
1381                if(subProperty.isOWLObjectProperty() && superProperty.isOWLObjectProperty()){
1382                        return getObjectPropertyHierarchy().isSubpropertyOf((OWLObjectProperty)subProperty, (OWLObjectProperty)superProperty);
1383                } else if(subProperty.isOWLDataProperty() && superProperty.isOWLDataProperty()){
1384                        return getDatatypePropertyHierarchy().isSubpropertyOf((OWLDataProperty)subProperty, (OWLDataProperty)superProperty);
1385                }
1386                return false;
1387        }
1388
1389        /**
1390         * Creates the data property hierarchy. Invoking this method is optional (if
1391         * not called explicitly, it is called the first time, it is needed).
1392         * 
1393         * @return The data property hierarchy.
1394         * @throws ReasoningMethodUnsupportedException
1395         *             Thrown if data property hierarchy creation is not supported
1396         *             by the reasoner.
1397         */
1398        public DatatypePropertyHierarchy prepareDatatypePropertyHierarchy()
1399                        throws ReasoningMethodUnsupportedException {
1400        
1401                TreeMap<OWLDataProperty, SortedSet<OWLDataProperty>> datatypePropertyHierarchyUp = new TreeMap<>(
1402                );
1403                TreeMap<OWLDataProperty, SortedSet<OWLDataProperty>> datatypePropertyHierarchyDown = new TreeMap<>(
1404                );
1405 
1406                Set<OWLDataProperty> datatypeProperties = getDatatypeProperties();
1407                for (OWLDataProperty role : datatypeProperties) {
1408                        datatypePropertyHierarchyDown.put(role, getSubPropertiesImpl(role));
1409                        datatypePropertyHierarchyUp.put(role, getSuperPropertiesImpl(role));
1410                }
1411
1412                return new DatatypePropertyHierarchy(datatypePropertyHierarchyUp, datatypePropertyHierarchyDown);               
1413        }
1414
1415        @Override
1416        public final DatatypePropertyHierarchy getDatatypePropertyHierarchy() {
1417        
1418                try {
1419                        if (datatypePropertyHierarchy == null) {
1420                                datatypePropertyHierarchy = prepareDatatypePropertyHierarchy();
1421                        }
1422                } catch (ReasoningMethodUnsupportedException e) {
1423                        handleExceptions(e);
1424                }
1425
1426                return datatypePropertyHierarchy;
1427        }
1428
1429        public List<OWLClass> getAtomicConceptsList() {
1430                if (atomicConceptsList == null)
1431                        atomicConceptsList = new LinkedList<>(getClasses());
1432                return atomicConceptsList;
1433        }
1434
1435        public List<OWLClass> getAtomicConceptsList(boolean removeOWLThing) {
1436                List<OWLClass> classes = Lists.newArrayList(getAtomicConceptsList());
1437                if (removeOWLThing) {
1438                        classes.remove(df.getOWLThing());
1439                        classes.remove(df.getOWLNothing());
1440                }
1441                return classes;
1442        }
1443        
1444        public void setSubsumptionHierarchy(ClassHierarchy subsumptionHierarchy) {
1445                this.subsumptionHierarchy = subsumptionHierarchy;
1446        }
1447
1448        public List<OWLObjectProperty> getAtomicRolesList() {
1449                if (atomicRolesList == null)
1450                        atomicRolesList = new LinkedList<>(getObjectProperties());
1451                return atomicRolesList;
1452        }
1453
1454        public long getInstanceCheckReasoningTimeNs() {
1455                return instanceCheckReasoningTimeNs;
1456        }
1457
1458        public long getRetrievalReasoningTimeNs() {
1459                return retrievalReasoningTimeNs;
1460        }
1461
1462        public int getNrOfInstanceChecks() {
1463                return nrOfInstanceChecks;
1464        }
1465
1466        public int getNrOfRetrievals() {
1467                return nrOfRetrievals;
1468        }
1469
1470        public int getNrOfSubsumptionChecks() {
1471                return nrOfSubsumptionChecks;
1472        }
1473
1474        public long getSubsumptionReasoningTimeNs() {
1475                return subsumptionReasoningTimeNs;
1476        }
1477
1478        public int getNrOfSubsumptionHierarchyQueries() {
1479                return nrOfSubsumptionHierarchyQueries;
1480        }
1481
1482        public long getOverallReasoningTimeNs() {
1483                return overallReasoningTimeNs;
1484        }
1485
1486        public long getTimePerRetrievalNs() {
1487                return retrievalReasoningTimeNs / nrOfRetrievals;
1488        }
1489
1490        public long getTimePerInstanceCheckNs() {
1491                return instanceCheckReasoningTimeNs / nrOfInstanceChecks;
1492        }
1493
1494        public long getTimePerSubsumptionCheckNs() {
1495                return subsumptionReasoningTimeNs / nrOfSubsumptionChecks;
1496        }
1497
1498        public int getNrOfMultiSubsumptionChecks() {
1499                return nrOfMultiSubsumptionChecks;
1500        }
1501
1502        public int getNrOfMultiInstanceChecks() {
1503                return nrOfMultiInstanceChecks;
1504        }
1505        
1506        /**
1507         * @param precomputeClassHierarchy the precomputeClassHierarchy to set
1508         */
1509        public void setPrecomputeClassHierarchy(boolean precomputeClassHierarchy) {
1510                this.precomputeClassHierarchy = precomputeClassHierarchy;
1511        }
1512        
1513        /**
1514         * @param precomputeObjectPropertyHierarchy the precomputeObjectPropertyHierarchy to set
1515         */
1516        public void setPrecomputeObjectPropertyHierarchy(boolean precomputeObjectPropertyHierarchy) {
1517                this.precomputeObjectPropertyHierarchy = precomputeObjectPropertyHierarchy;
1518        }
1519        
1520        /**
1521         * @param precomputeDataPropertyHierarchy the precomputeDataPropertyHierarchy to set
1522         */
1523        public void setPrecomputeDataPropertyHierarchy(boolean precomputeDataPropertyHierarchy) {
1524                this.precomputeDataPropertyHierarchy = precomputeDataPropertyHierarchy;
1525        }
1526        
1527        /**
1528         * @return all object properties with its domains.
1529         */
1530        public Map<OWLObjectProperty, OWLClassExpression> getObjectPropertyDomains() {
1531                Map<OWLObjectProperty, OWLClassExpression> result = new HashMap<>();
1532                
1533                for (OWLObjectProperty op : getObjectProperties()) {
1534                        OWLClassExpression domain = getDomain(op);
1535                        result.put(op, domain);
1536                }
1537                
1538                return result;
1539        }
1540        
1541        /**
1542         * @return all object properties with its range.
1543         */
1544        public Map<OWLObjectProperty, OWLClassExpression> getObjectPropertyRanges() {
1545                Map<OWLObjectProperty, OWLClassExpression> result = new HashMap<>();
1546                
1547                for (OWLObjectProperty op : getObjectProperties()) {
1548                        OWLClassExpression range = getRange(op);
1549                        result.put(op, range);
1550                }
1551                
1552                return result;
1553        }
1554        
1555        /**
1556         * @return all data properties with its domains.
1557         */
1558        public Map<OWLDataProperty, OWLClassExpression> getDataPropertyDomains() {
1559                Map<OWLDataProperty, OWLClassExpression> result = new HashMap<>();
1560                
1561                for (OWLDataProperty dp : getDatatypeProperties()) {
1562                        OWLClassExpression domain = getDomain(dp);
1563                        result.put(dp, domain);
1564                }
1565                
1566                return result;
1567        }
1568        
1569        @Override
1570        public String toString() {
1571                String str = "";
1572                if (nrOfRetrievals > 0) {
1573                        str += "number of retrievals: " + nrOfRetrievals + "\n";
1574                        str += "retrieval reasoning time: "
1575                                                        + Helper.prettyPrintNanoSeconds(retrievalReasoningTimeNs)
1576                                                        + " ( " + Helper.prettyPrintNanoSeconds(getTimePerRetrievalNs())
1577                                                        + " per retrieval)" + "\n";
1578                }
1579                if (nrOfInstanceChecks > 0) {
1580                        str += "number of instance checks: " + nrOfInstanceChecks + " ("
1581                                        + nrOfMultiInstanceChecks + " multiple)\n";
1582                        str += "instance check reasoning time: "
1583                                        + Helper.prettyPrintNanoSeconds(instanceCheckReasoningTimeNs) + " ( "
1584                                        + Helper.prettyPrintNanoSeconds(getTimePerInstanceCheckNs())
1585                                        + " per instance check)\n";
1586                }
1587                if (nrOfSubsumptionHierarchyQueries > 0) {
1588                        str += "subsumption hierarchy queries: "
1589                                        + nrOfSubsumptionHierarchyQueries + "\n";
1590                }
1591                if (nrOfSubsumptionChecks > 0) {
1592                        str += "(complex) subsumption checks: " + nrOfSubsumptionChecks
1593                                        + " (" + nrOfMultiSubsumptionChecks + " multiple)\n";
1594                        str += "subsumption reasoning time: "
1595                                        + Helper.prettyPrintNanoSeconds(subsumptionReasoningTimeNs) + " ( "
1596                                        + Helper.prettyPrintNanoSeconds(getTimePerSubsumptionCheckNs())
1597                                        + " per subsumption check)\n";
1598                }
1599                str += "overall reasoning time: "
1600                                + Helper.prettyPrintNanoSeconds(overallReasoningTimeNs) + "\n"; 
1601                return str;
1602        }
1603        
1604        /**************************************************************
1605         * FUZZY EXTENSIONS
1606         **************************************************************/
1607        
1608        @Override
1609        public double hasTypeFuzzyMembership(OWLClassExpression description, FuzzyIndividual individual) {
1610                reasoningStartTimeTmp = System.nanoTime();
1611                double result = -1;
1612                try {
1613                        result = hasTypeFuzzyMembershipImpl(description, individual);
1614                } catch (ReasoningMethodUnsupportedException e) {
1615                        handleExceptions(e);
1616                }
1617                nrOfInstanceChecks++;
1618                reasoningDurationTmp = System.nanoTime() - reasoningStartTimeTmp;
1619                instanceCheckReasoningTimeNs += reasoningDurationTmp;
1620                overallReasoningTimeNs += reasoningDurationTmp;
1621                return result;          
1622        }
1623
1624        protected double hasTypeFuzzyMembershipImpl(OWLClassExpression concept, FuzzyIndividual individual)
1625        throws ReasoningMethodUnsupportedException {
1626                throw new ReasoningMethodUnsupportedException();
1627        }
1628        
1629        /**
1630         * Returns the datatype of the data property, i.e. the range if it is a datatype.
1631         * @param dp the data property
1632         * @return the datatype of the data property
1633         */
1634        public abstract OWLDatatype getDatatype(OWLDataProperty dp);
1635        
1636        /**
1637         * Enabled a synchronized mode such that all reasoner methods are supposed
1638         * to be thread safe.
1639         */
1640        public abstract void setSynchronized();
1641
1642        public boolean isUseInstanceChecks() {
1643                return useInstanceChecks;
1644        }
1645
1646        public void setUseInstanceChecks(boolean useInstanceChecks) {
1647                this.useInstanceChecks = useInstanceChecks;
1648        }
1649}