All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.semanticweb.HermiT.structural.OWLNormalization Maven / Gradle / Ivy

Go to download

HermiT is reasoner for ontologies written using the Web Ontology Language (OWL). Given an OWL file, HermiT can determine whether or not the ontology is consistent, identify subsumption relationships between classes, and much more. This is the maven build of HermiT and is designed for people who wish to use HermiT from within the OWL API. It is now versioned in the main HermiT version repository, although not officially supported by the HermiT developers. The version number of this package is a composite of the HermiT version and an value representing releases of this packaged version. So, 1.3.7.1 is the first release of the mavenized version of HermiT based on the 1.3.7 release of HermiT. This package includes the Jautomata library (http://jautomata.sourceforge.net/), and builds with it directly. This library appears to be no longer under active development, and so a "fork" seems appropriate. No development is intended or anticipated on this code base.

There is a newer version: 1.3.8.4
Show newest version
/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory

   This file is part of HermiT.

   HermiT is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   HermiT is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with HermiT.  If not, see .
 */
package org.semanticweb.HermiT.structural;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLAsymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLAxiomVisitor;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx;
import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
import org.semanticweb.owlapi.model.OWLDataComplementOf;
import org.semanticweb.owlapi.model.OWLDataExactCardinality;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataHasValue;
import org.semanticweb.owlapi.model.OWLDataIntersectionOf;
import org.semanticweb.owlapi.model.OWLDataMaxCardinality;
import org.semanticweb.owlapi.model.OWLDataMinCardinality;
import org.semanticweb.owlapi.model.OWLDataOneOf;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLDataPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLDataUnionOf;
import org.semanticweb.owlapi.model.OWLDataVisitorEx;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLDatatypeDefinitionAxiom;
import org.semanticweb.owlapi.model.OWLDatatypeRestriction;
import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
import org.semanticweb.owlapi.model.OWLDifferentIndividualsAxiom;
import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointDataPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointUnionAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentDataPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLFacetRestriction;
import org.semanticweb.owlapi.model.OWLFunctionalDataPropertyAxiom;
import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLHasKeyAxiom;
import org.semanticweb.owlapi.model.OWLImportsDeclaration;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLIndividualAxiom;
import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLIrreflexiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLNegativeDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLNegativeObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
import org.semanticweb.owlapi.model.OWLObjectHasSelf;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectOneOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLReflexiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLSameIndividualAxiom;
import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.OWLSubDataPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
import org.semanticweb.owlapi.model.OWLSymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.SWRLArgument;
import org.semanticweb.owlapi.model.SWRLAtom;
import org.semanticweb.owlapi.model.SWRLBuiltInAtom;
import org.semanticweb.owlapi.model.SWRLClassAtom;
import org.semanticweb.owlapi.model.SWRLDArgument;
import org.semanticweb.owlapi.model.SWRLDataPropertyAtom;
import org.semanticweb.owlapi.model.SWRLDataRangeAtom;
import org.semanticweb.owlapi.model.SWRLDifferentIndividualsAtom;
import org.semanticweb.owlapi.model.SWRLIArgument;
import org.semanticweb.owlapi.model.SWRLIndividualArgument;
import org.semanticweb.owlapi.model.SWRLLiteralArgument;
import org.semanticweb.owlapi.model.SWRLObjectPropertyAtom;
import org.semanticweb.owlapi.model.SWRLObjectVisitor;
import org.semanticweb.owlapi.model.SWRLRule;
import org.semanticweb.owlapi.model.SWRLSameIndividualAtom;
import org.semanticweb.owlapi.model.SWRLVariable;

/**
 * This class implements the structural transformation from our new tableau paper. This transformation departs in the following way from the paper: it keeps the concepts of the form \exists R.{ a_1, ..., a_n }, \forall R.{ a_1, ..., a_n }, and \forall R.\neg { a } intact. These concepts are then clausified in a more efficient way.
 */
public class OWLNormalization {
    protected final OWLDataFactory m_factory;
    protected final OWLAxioms m_axioms;
    protected final int m_firstReplacementIndex;
    protected final Map m_definitions;
    protected final Map m_definitionsForNegativeNominals;
    protected final ExpressionManager m_expressionManager;
    protected final PLVisitor m_plVisitor;
    protected final Map m_dataRangeDefinitions; // contains custom datatype definitions from DatatypeDefinition axioms

    public OWLNormalization(OWLDataFactory factory,OWLAxioms axioms,int firstReplacementIndex) {
        m_factory=factory;
        m_axioms=axioms;
        m_firstReplacementIndex=firstReplacementIndex;
        m_definitions=new HashMap();
        m_definitionsForNegativeNominals=new HashMap();
        m_expressionManager=new ExpressionManager(m_factory);
        m_plVisitor=new PLVisitor();
        m_dataRangeDefinitions=new HashMap();
    }
    public void processOntology(OWLOntology ontology) {
        // Each entry in the inclusions list represents a disjunction of
        // concepts -- that is, each OWLClassExpression in an entry contributes a
        // disjunct. It is thus not really inclusions, but rather a disjunction
        // of concepts that represents an inclusion axiom.
        m_axioms.m_classes.addAll(ontology.getClassesInSignature(true));
        m_axioms.m_objectProperties.addAll(ontology.getObjectPropertiesInSignature(true));
        m_axioms.m_dataProperties.addAll(ontology.getDataPropertiesInSignature(true));
        m_axioms.m_namedIndividuals.addAll(ontology.getIndividualsInSignature(true));
        processAxioms(ontology.getLogicalAxioms());
    }
    public void processAxioms(Collection axioms) {
        AxiomVisitor axiomVisitor=new AxiomVisitor();
        for (OWLAxiom axiom : axioms)
            axiom.accept(axiomVisitor);
        // now all axioms are in NNF and converted into disjunctions wherever possible
        // exact cardinalities are rewritten into at least and at most cardinalities etc
        // Rules with multiple head atoms are rewritten into several rules (Lloyd-Topor transformation)

        // normalize rules, this might add new concept and data range inclusions
        // in case a rule atom uses a complex concept or data range
        // we keep this inclusions separate because they are only applied to named individuals
        RuleNormalizer ruleNormalizer=new RuleNormalizer(m_axioms.m_rules,axiomVisitor.m_classExpressionInclusionsAsDisjunctions,axiomVisitor.m_dataRangeInclusionsAsDisjunctions);
        for (SWRLRule rule : axiomVisitor.m_rules)
            ruleNormalizer.visit(rule);

        // in normalization, we now simplify the disjuncts where possible (eliminate
        // unnecessary conjuncts/disjuncts) and introduce fresh atomic concepts for complex
        // concepts m_axioms.m_conceptInclusions contains the normalized axioms after the normalization
        normalizeInclusions(axiomVisitor.m_classExpressionInclusionsAsDisjunctions,axiomVisitor.m_dataRangeInclusionsAsDisjunctions);
    }
    protected void addFact(OWLIndividualAxiom axiom) {
        m_axioms.m_facts.add(axiom);
    }
    protected void addInclusion(OWLObjectPropertyExpression subObjectPropertyExpression,OWLObjectPropertyExpression superObjectPropertyExpression) {
        m_axioms.m_simpleObjectPropertyInclusions.add(new OWLObjectPropertyExpression[] { subObjectPropertyExpression.getSimplified(),superObjectPropertyExpression.getSimplified() });
    }
    protected void addInclusion(OWLObjectPropertyExpression[] subObjectPropertyExpressions,OWLObjectPropertyExpression superObjectPropertyExpression) {
        for (int index=subObjectPropertyExpressions.length-1;index>=0;--index)
            subObjectPropertyExpressions[index]=subObjectPropertyExpressions[index].getSimplified();
        m_axioms.m_complexObjectPropertyInclusions.add(new OWLAxioms.ComplexObjectPropertyInclusion(subObjectPropertyExpressions,superObjectPropertyExpression.getSimplified()));
    }
    protected void addInclusion(OWLDataPropertyExpression subDataPropertyExpression,OWLDataPropertyExpression superDataPropertyExpression) {
        m_axioms.m_dataPropertyInclusions.add(new OWLDataPropertyExpression[] { subDataPropertyExpression,superDataPropertyExpression });
    }
    protected void makeTransitive(OWLObjectPropertyExpression objectPropertyExpression) {
        m_axioms.m_complexObjectPropertyInclusions.add(new OWLAxioms.ComplexObjectPropertyInclusion(objectPropertyExpression.getSimplified()));
    }
    protected void makeReflexive(OWLObjectPropertyExpression objectPropertyExpression) {
        m_axioms.m_reflexiveObjectProperties.add(objectPropertyExpression.getSimplified());
    }
    protected void makeIrreflexive(OWLObjectPropertyExpression objectPropertyExpression) {
        m_axioms.m_irreflexiveObjectProperties.add(objectPropertyExpression.getSimplified());
    }
    protected void makeAsymmetric(OWLObjectPropertyExpression objectPropertyExpression) {
        m_axioms.m_asymmetricObjectProperties.add(objectPropertyExpression.getSimplified());
    }
    protected static boolean isSimple(OWLClassExpression description) {
        return description instanceof OWLClass || (description instanceof OWLObjectComplementOf && ((OWLObjectComplementOf)description).getOperand() instanceof OWLClass);
    }
    protected static boolean isLiteral(OWLDataRange dr) {
        return isAtomic(dr) || isNegatedAtomic(dr);
    }
    protected static boolean isAtomic(OWLDataRange dr) {
        return dr instanceof OWLDatatype || dr instanceof OWLDatatypeRestriction || dr instanceof OWLDataOneOf;
    }
    protected static boolean isNegatedAtomic(OWLDataRange dr) {
        return dr instanceof OWLDataComplementOf && isAtomic(((OWLDataComplementOf)dr).getDataRange());
    }
    protected static boolean isNominal(OWLClassExpression description) {
        return description instanceof OWLObjectOneOf;
    }
    protected static boolean isNegatedOneNominal(OWLClassExpression description) {
        if (!(description instanceof OWLObjectComplementOf))
            return false;
        OWLClassExpression operand=((OWLObjectComplementOf)description).getOperand();
        if (!(operand instanceof OWLObjectOneOf))
            return false;
        return ((OWLObjectOneOf)operand).getIndividuals().size()==1;
    }
    protected void normalizeInclusions(List inclusions,List dataRangeInclusions) {
        ClassExpressionNormalizer classExpressionNormalizer=new ClassExpressionNormalizer(inclusions,dataRangeInclusions);
        // normalize all class expression inclusions
        while (!inclusions.isEmpty()) {
            OWLClassExpression simplifiedDescription=m_expressionManager.getNNF(m_expressionManager.getSimplified(m_factory.getOWLObjectUnionOf(inclusions.remove(inclusions.size()-1))));
            if (!simplifiedDescription.isOWLThing()) {
                if (simplifiedDescription instanceof OWLObjectUnionOf) {
                    OWLObjectUnionOf objectOr=(OWLObjectUnionOf)simplifiedDescription;
                    OWLClassExpression[] descriptions=new OWLClassExpression[objectOr.getOperands().size()];
                    objectOr.getOperands().toArray(descriptions);
                    if (!distributeUnionOverAnd(descriptions,inclusions) && !optimizedNegativeOneOfTranslation(descriptions,m_axioms.m_facts)) {
                        for (int index=0;index inclusions) {
        int andIndex=-1;
        for (int index=0;index inclusions) {
        int andIndex=-1;
        for (int index=0;index facts) {
        if (descriptions.length==2) {
            OWLObjectOneOf nominal=null;
            OWLClassExpression other=null;
            if (descriptions[0] instanceof OWLObjectComplementOf && ((OWLObjectComplementOf)descriptions[0]).getOperand() instanceof OWLObjectOneOf) {
                nominal=(OWLObjectOneOf)((OWLObjectComplementOf)descriptions[0]).getOperand();
                other=descriptions[1];
            }
            else if (descriptions[1] instanceof OWLObjectComplementOf && ((OWLObjectComplementOf)descriptions[1]).getOperand() instanceof OWLObjectOneOf) {
                other=descriptions[0];
                nominal=(OWLObjectOneOf)((OWLObjectComplementOf)descriptions[1]).getOperand();
            }
            if (nominal!=null && (other instanceof OWLClass || (other instanceof OWLObjectComplementOf && ((OWLObjectComplementOf)other).getOperand() instanceof OWLClass))) {
                for (OWLIndividual individual : nominal.getIndividuals())
                    facts.add(m_factory.getOWLClassAssertionAxiom(other,individual));
                return true;
            }
        }
        return false;
    }
    protected OWLClassExpression getDefinitionFor(OWLClassExpression description,boolean[] alreadyExists,boolean forcePositive) {
        OWLClassExpression definition=m_definitions.get(description);
        if (definition==null || (forcePositive && !(definition instanceof OWLClass))) {
            definition=m_factory.getOWLClass(IRI.create("internal:def#"+(m_definitions.size()+m_firstReplacementIndex)));
            if (!forcePositive && !description.accept(m_plVisitor))
                definition=m_factory.getOWLObjectComplementOf(definition);
            m_definitions.put(description,definition);
            alreadyExists[0]=false;
        }
        else
            alreadyExists[0]=true;
        return definition;
    }
    protected OWLDatatype getDefinitionFor(OWLDataRange dr,boolean[] alreadyExists) {
        OWLDatatype definition=m_dataRangeDefinitions.get(dr);
        if (definition==null) {
            definition=m_factory.getOWLDatatype(IRI.create("internal:defdata#"+m_dataRangeDefinitions.size()));
            m_dataRangeDefinitions.put(dr,definition);
            alreadyExists[0]=false;
        }
        else {
            alreadyExists[0]=true;
        }
        return definition;
    }
    protected OWLClassExpression getDefinitionFor(OWLClassExpression description,boolean[] alreadyExists) {
        return getDefinitionFor(description,alreadyExists,false);
    }
    protected OWLClass getClassFor(OWLClassExpression description,boolean[] alreadyExists) {
        return (OWLClass)getDefinitionFor(description,alreadyExists,true);
    }
    protected OWLClass getDefinitionForNegativeNominal(OWLObjectOneOf nominal,boolean[] alreadyExists) {
        OWLClass definition=m_definitionsForNegativeNominals.get(nominal);
        if (definition==null) {
            definition=m_factory.getOWLClass(IRI.create("internal:nnq#"+m_definitionsForNegativeNominals.size()));
            m_definitionsForNegativeNominals.put(nominal,definition);
            alreadyExists[0]=false;
        }
        else
            alreadyExists[0]=true;
        return definition;
    }
    protected OWLClassExpression positive(OWLClassExpression description) {
        return m_expressionManager.getNNF(m_expressionManager.getSimplified(description));
    }
    protected OWLClassExpression negative(OWLClassExpression description) {
        return m_expressionManager.getComplementNNF(m_expressionManager.getSimplified(description));
    }
    protected OWLDataRange positive(OWLDataRange dataRange) {
        return m_expressionManager.getNNF(m_expressionManager.getSimplified(dataRange));
    }
    protected OWLDataRange negative(OWLDataRange dataRange) {
        return m_expressionManager.getComplementNNF(m_expressionManager.getSimplified(dataRange));
    }

    protected class AxiomVisitor implements OWLAxiomVisitor {
        protected final List m_classExpressionInclusionsAsDisjunctions;
        protected final List m_dataRangeInclusionsAsDisjunctions;
        protected final Collection m_rules;
        protected final boolean[] m_alreadyExists;

        public AxiomVisitor() {
            m_classExpressionInclusionsAsDisjunctions=new ArrayList();
            m_dataRangeInclusionsAsDisjunctions=new ArrayList();
            m_rules=new HashSet();
            m_alreadyExists=new boolean[1];
        }

        // Semantics-less axioms

        public void visit(OWLImportsDeclaration axiom) {
        }
        public void visit(OWLDeclarationAxiom axiom) {
//            if (axiom.getEntity().isOWLClass()) {
//                OWLClass cls=(OWLClass)axiom.getEntity(); 
//                if (!m_axioms.m_classes.contains(cls)) 
//                    m_axioms.m_classes.add(cls);
//            }
//            if (axiom.getEntity().isOWLObjectProperty()) {
//                OWLObjectProperty op=(OWLObjectProperty)axiom.getEntity(); 
//                if (!m_axioms.m_objectProperties.contains(op)) 
//                    m_axioms.m_objectProperties.add(op);
//            }
//            if (axiom.getEntity().isOWLDataProperty()) {
//                OWLDataProperty dp=(OWLDataProperty)axiom.getEntity(); 
//                if (!m_axioms.m_dataProperties.contains(dp)) 
//                    m_axioms.m_dataProperties.add(dp);
//            }
        }
        public void visit(OWLAnnotationAssertionAxiom axiom) {
        }
        public void visit(OWLSubAnnotationPropertyOfAxiom axiom) {
        }
        public void visit(OWLAnnotationPropertyDomainAxiom axiom) {
        }
        public void visit(OWLAnnotationPropertyRangeAxiom axiom) {
        }

        // Class axioms

        public void visit(OWLSubClassOfAxiom axiom) {
            m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { negative(axiom.getSubClass()),positive(axiom.getSuperClass()) });
        }
        public void visit(OWLEquivalentClassesAxiom axiom) {
            if (axiom.getClassExpressions().size()>1) {
                Iterator iterator=axiom.getClassExpressions().iterator();
                OWLClassExpression first=iterator.next();
                OWLClassExpression last=first;
                while (iterator.hasNext()) {
                    OWLClassExpression next=iterator.next();
                    m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { negative(last),positive(next) });
                    last=next;
                }
                m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { negative(last),positive(first) });
            }
        }
        public void visit(OWLDisjointClassesAxiom axiom) {
            if (axiom.getClassExpressions().size()<=1) {
                throw new IllegalArgumentException("Error: Parsed "+axiom.toString()+". A DisjointClasses axiom in OWL 2 DL must have at least two classes as parameters. ");
            }
            OWLClassExpression[] descriptions=new OWLClassExpression[axiom.getClassExpressions().size()];
            axiom.getClassExpressions().toArray(descriptions);
            for (int i=0;i inclusion=new HashSet(axiom.getClassExpressions());
            inclusion.add(m_expressionManager.getComplementNNF(axiom.getOWLClass()));
            OWLClassExpression[] inclusionArray=new OWLClassExpression[axiom.getClassExpressions().size()+1];
            inclusion.toArray(inclusionArray);
            m_classExpressionInclusionsAsDisjunctions.add(inclusionArray);
            // 2. add CEi implies C, which is { not CEi or C }
            for (OWLClassExpression description : axiom.getClassExpressions())
                m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { negative(description),axiom.getOWLClass() });
            // 3. add CEi and CEj implies bottom (not CEi or not CEj) for 1 <= i < j <= n
            OWLClassExpression[] descriptions=new OWLClassExpression[axiom.getClassExpressions().size()];
            axiom.getClassExpressions().toArray(descriptions);
            for (int i=0;i subPropertyChain=axiom.getPropertyChain();
            if (!containsBottomObjectProperty(subPropertyChain) && !axiom.getSuperProperty().isOWLTopObjectProperty()) {
                OWLObjectPropertyExpression superObjectPropertyExpression=axiom.getSuperProperty();
                if (subPropertyChain.size()==1)
                    addInclusion(subPropertyChain.get(0),superObjectPropertyExpression);
                else if (subPropertyChain.size()==2 && subPropertyChain.get(0).equals(superObjectPropertyExpression) && subPropertyChain.get(1).equals(superObjectPropertyExpression))
                    makeTransitive(axiom.getSuperProperty());
                else if (subPropertyChain.size()==0)
                    throw new IllegalArgumentException("Error: In OWL 2 DL, an empty property chain in property chain axioms is not allowd, but the ontology contains an axiom that the empty chain is a subproperty of "+superObjectPropertyExpression+".");
                else {
                    OWLObjectPropertyExpression[] subObjectProperties=new OWLObjectPropertyExpression[subPropertyChain.size()];
                    subPropertyChain.toArray(subObjectProperties);
                    addInclusion(subObjectProperties,superObjectPropertyExpression);
                }
            }
            for (OWLObjectPropertyExpression objectPropertyExpression : subPropertyChain)
                m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(objectPropertyExpression.getNamedProperty());
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(axiom.getSuperProperty().getNamedProperty());
        }
        protected boolean containsBottomObjectProperty(List properties) {
            for (OWLObjectPropertyExpression property : properties)
                if (property.isOWLBottomObjectProperty())
                    return true;
            return false;
        }
        public void visit(OWLEquivalentObjectPropertiesAxiom axiom) {
            Set objectPropertyExpressions=axiom.getProperties();
            if (objectPropertyExpressions.size()>1) {
                Iterator iterator=objectPropertyExpressions.iterator();
                OWLObjectPropertyExpression first=iterator.next();
                OWLObjectPropertyExpression last=first;
                while (iterator.hasNext()) {
                    OWLObjectPropertyExpression next=iterator.next();
                    addInclusion(last,next);
                    last=next;
                }
                addInclusion(last,first);
            }
            for (OWLObjectPropertyExpression objectPropertyExpression : objectPropertyExpressions)
                m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(objectPropertyExpression.getNamedProperty());
        }
        public void visit(OWLDisjointObjectPropertiesAxiom axiom) {
            OWLObjectPropertyExpression[] objectPropertyExpressions=new OWLObjectPropertyExpression[axiom.getProperties().size()];
            axiom.getProperties().toArray(objectPropertyExpressions);
            for (int i=0;i1) {
                Iterator iterator=axiom.getProperties().iterator();
                OWLDataPropertyExpression first=iterator.next();
                OWLDataPropertyExpression last=first;
                while (iterator.hasNext()) {
                    OWLDataPropertyExpression next=iterator.next();
                    addInclusion(last,next);
                    last=next;
                }
                addInclusion(last,first);
            }
        }
        public void visit(OWLDisjointDataPropertiesAxiom axiom) {
            OWLDataPropertyExpression[] dataProperties=new OWLDataPropertyExpression[axiom.getProperties().size()];
            axiom.getProperties().toArray(dataProperties);
            for (OWLDataPropertyExpression dataProperty : dataProperties)
                checkTopDataPropertyUse(dataProperty,axiom);
            m_axioms.m_disjointDataProperties.add(dataProperties);
        }
        public void visit(OWLDataPropertyDomainAxiom axiom) {
            OWLDataPropertyExpression dataProperty=axiom.getProperty();
            checkTopDataPropertyUse(dataProperty,axiom);
            OWLDataRange dataNothing=m_factory.getOWLDataComplementOf(m_factory.getTopDatatype());
            OWLDataAllValuesFrom allPropertyDataNothing=m_factory.getOWLDataAllValuesFrom(dataProperty,dataNothing);
            m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { positive(axiom.getDomain()),allPropertyDataNothing });
        }
        public void visit(OWLDataPropertyRangeAxiom axiom) {
            OWLDataPropertyExpression dataProperty=axiom.getProperty();
            checkTopDataPropertyUse(dataProperty,axiom);
            OWLDataAllValuesFrom allPropertyRange=m_factory.getOWLDataAllValuesFrom(dataProperty,positive(axiom.getRange()));
            m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { allPropertyRange });
        }
        public void visit(OWLFunctionalDataPropertyAxiom axiom) {
            OWLDataPropertyExpression dataProperty=axiom.getProperty();
            checkTopDataPropertyUse(dataProperty,axiom);
            m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { m_factory.getOWLDataMaxCardinality(1,dataProperty) });
        }
        protected void checkTopDataPropertyUse(OWLDataPropertyExpression dataPropertyExpression,OWLAxiom axiom) {
            if (dataPropertyExpression.isOWLTopDataProperty())
                throw new IllegalArgumentException("Error: In OWL 2 DL, owl:topDataProperty is only allowed to occur in the super property position of SubDataPropertyOf axioms, but the ontology contains an axiom "+axiom+" that violates this condition.");
        }

        // Assertions

        public void visit(OWLSameIndividualAxiom axiom) {
            if (axiom.containsAnonymousIndividuals())
                throw new IllegalArgumentException("The axiom "+axiom+" contains anonymous individuals, which is not allowed in OWL 2. ");
            addFact(axiom);
        }
        public void visit(OWLDifferentIndividualsAxiom axiom) {
            if (axiom.containsAnonymousIndividuals())
                throw new IllegalArgumentException("The axiom "+axiom+" contains anonymous individuals, which is not allowed in OWL 2. ");
            addFact(axiom);
        }
        public void visit(OWLClassAssertionAxiom axiom) {
            OWLClassExpression classExpression=axiom.getClassExpression();
            if (classExpression instanceof OWLDataHasValue) {
                OWLDataHasValue hasValue=(OWLDataHasValue)classExpression;
                addFact(m_factory.getOWLDataPropertyAssertionAxiom(hasValue.getProperty(), axiom.getIndividual(), hasValue.getValue()));
                return;
            }
            if (classExpression instanceof OWLDataSomeValuesFrom) {
                OWLDataSomeValuesFrom someValuesFrom=(OWLDataSomeValuesFrom)classExpression;
                OWLDataRange dataRange=someValuesFrom.getFiller();
                if (dataRange instanceof OWLDataOneOf) {
                    OWLDataOneOf oneOf=(OWLDataOneOf)dataRange;
                    if (oneOf.getValues().size()==1) {
                        addFact(m_factory.getOWLDataPropertyAssertionAxiom(someValuesFrom.getProperty(),axiom.getIndividual(),oneOf.getValues().iterator().next()));
                        return;
                    }
                }
            }
            classExpression=positive(classExpression);
            if (!isSimple(classExpression)) {
                OWLClassExpression definition=getDefinitionFor(classExpression,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { negative(definition),classExpression });
                classExpression=definition;
            }
            addFact(m_factory.getOWLClassAssertionAxiom(classExpression,axiom.getIndividual()));
        }
        public void visit(OWLObjectPropertyAssertionAxiom axiom) {
            addFact(m_factory.getOWLObjectPropertyAssertionAxiom(axiom.getProperty().getSimplified(),axiom.getSubject(),axiom.getObject()));
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(axiom.getProperty().getNamedProperty());
        }
        public void visit(OWLNegativeObjectPropertyAssertionAxiom axiom) {
            if (axiom.containsAnonymousIndividuals())
                throw new IllegalArgumentException("The axiom "+axiom+" contains anonymous individuals, which is not allowed in OWL 2 DL. ");
            addFact(m_factory.getOWLNegativeObjectPropertyAssertionAxiom(axiom.getProperty().getSimplified(),axiom.getSubject(),axiom.getObject()));
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(axiom.getProperty().getNamedProperty());
        }
        public void visit(OWLDataPropertyAssertionAxiom axiom) {
            checkTopDataPropertyUse(axiom.getProperty(),axiom);
            addFact(axiom);
        }
        public void visit(OWLNegativeDataPropertyAssertionAxiom axiom) {
            checkTopDataPropertyUse(axiom.getProperty(),axiom);
            if (axiom.containsAnonymousIndividuals())
                throw new IllegalArgumentException("The axiom "+axiom+" contains anonymous individuals, which is not allowed in OWL 2 DL. ");
            addFact(axiom);
        }

        // Datatype definitions

        public void visit(OWLDatatypeDefinitionAxiom axiom) {
            m_axioms.m_definedDatatypesIRIs.add(axiom.getDatatype().getIRI().toString());
            m_dataRangeInclusionsAsDisjunctions.add(new OWLDataRange[] { negative(axiom.getDatatype()),positive(axiom.getDataRange()) });
            m_dataRangeInclusionsAsDisjunctions.add(new OWLDataRange[] { negative(axiom.getDataRange()),positive(axiom.getDatatype()) });
        }

        // Keys

        public void visit(OWLHasKeyAxiom axiom) {
            for (OWLDataPropertyExpression dataPropertyExpression : axiom.getDataPropertyExpressions())
                checkTopDataPropertyUse(dataPropertyExpression,axiom);
            OWLClassExpression description=positive(axiom.getClassExpression());
            if (!isSimple(description)) {
                OWLClassExpression definition=getDefinitionFor(description,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_classExpressionInclusionsAsDisjunctions.add(new OWLClassExpression[] { negative(definition),description });
                description=definition;
            }
            m_axioms.m_hasKeys.add(m_factory.getOWLHasKeyAxiom(description,axiom.getPropertyExpressions()));
            for (OWLObjectPropertyExpression objectPropertyExpression : axiom.getObjectPropertyExpressions())
                m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(objectPropertyExpression.getNamedProperty());
        }

        // Rules

        public void visit(SWRLRule rule) {
            for (SWRLAtom atom : rule.getBody())
                if (atom instanceof SWRLDataPropertyAtom)
                    checkTopDataPropertyUse(((SWRLDataPropertyAtom)atom).getPredicate(),rule);
            for (SWRLAtom atom : rule.getHead())
                if (atom instanceof SWRLDataPropertyAtom)
                    checkTopDataPropertyUse(((SWRLDataPropertyAtom)atom).getPredicate(),rule);
            if (rule.getBody().isEmpty()) {
                // process as fact
                Rule2FactConverter r2fConverter=new Rule2FactConverter(m_classExpressionInclusionsAsDisjunctions);
                for (SWRLAtom at : rule.getHead())
                    at.accept(r2fConverter);
            }
            else
                m_rules.add(rule);
        }
    }

    protected class ClassExpressionNormalizer implements OWLClassExpressionVisitorEx {
        protected final Collection m_newInclusions;
        protected final Collection m_newDataRangeInclusions;
        protected final boolean[] m_alreadyExists;

        public ClassExpressionNormalizer(Collection newInclusions,Collection newDataRangeInclusions) {
            m_newInclusions=newInclusions;
            m_newDataRangeInclusions=newDataRangeInclusions;
            m_alreadyExists=new boolean[1];
        }
        public OWLClassExpression visit(OWLClass object) {
            return object;
        }
        public OWLClassExpression visit(OWLObjectIntersectionOf object) {
            OWLClassExpression definition=getDefinitionFor(object,m_alreadyExists);
            if (!m_alreadyExists[0])
                for (OWLClassExpression description : object.getOperands())
                    m_newInclusions.add(new OWLClassExpression[] { negative(definition),description });
            return definition;
        }
        public OWLClassExpression visit(OWLObjectUnionOf object) {
            throw new IllegalStateException("OR should be broken down at the outermost level");
        }
        public OWLClassExpression visit(OWLObjectComplementOf object) {
            if (isNominal(object.getOperand())) {
                OWLObjectOneOf objectOneOf=(OWLObjectOneOf)object.getOperand();
                OWLClass definition=getDefinitionForNegativeNominal(objectOneOf,m_alreadyExists);
                if (!m_alreadyExists[0])
                    for (OWLIndividual individual : objectOneOf.getIndividuals())
                        addFact(m_factory.getOWLClassAssertionAxiom(definition,individual));
                return m_factory.getOWLObjectComplementOf(definition);
            }
            else
                return object;
        }
        public OWLClassExpression visit(OWLObjectOneOf object) {
            for (OWLIndividual ind : object.getIndividuals())
                if (ind.isAnonymous())
                    throw new IllegalArgumentException("Error: The class expression "+object+" contains anonymous individuals, which is not allowed in OWL 2 (erratum in first OWL 2 spec, to be fixed with next publication of minor corrections). ");
            return object;
        }
        public OWLClassExpression visit(OWLObjectSomeValuesFrom object) {
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(object.getProperty().getNamedProperty());
            OWLClassExpression filler=object.getFiller();
            if (isSimple(filler) || isNominal(filler))
                // The ObjectOneof cases is an optimization.
                return object;
            else {
                OWLClassExpression definition=getDefinitionFor(filler,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newInclusions.add(new OWLClassExpression[] { negative(definition),filler });
                return m_factory.getOWLObjectSomeValuesFrom(object.getProperty(),definition);
            }
        }
        public OWLClassExpression visit(OWLObjectAllValuesFrom object) {
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(object.getProperty().getNamedProperty());
            OWLClassExpression filler=object.getFiller();
            if (isSimple(filler) || isNominal(filler) || isNegatedOneNominal(filler))
                // The nominal cases are optimizations.
                return object;
            else {
                OWLClassExpression definition=getDefinitionFor(filler,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newInclusions.add(new OWLClassExpression[] { negative(definition),filler });
                return m_factory.getOWLObjectAllValuesFrom(object.getProperty(),definition);
            }
        }
        public OWLClassExpression visit(OWLObjectHasValue object) {
            throw new IllegalStateException("Internal error: object value restrictions should have been simplified.");
        }
        public OWLClassExpression visit(OWLObjectHasSelf object) {
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(object.getProperty().getNamedProperty());
            return object;
        }
        public OWLClassExpression visit(OWLObjectMinCardinality object) {
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(object.getProperty().getNamedProperty());
            OWLClassExpression filler=object.getFiller();
            if (isSimple(filler))
                return object;
            else {
                OWLClassExpression definition=getDefinitionFor(filler,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newInclusions.add(new OWLClassExpression[] { negative(definition),filler });
                return m_factory.getOWLObjectMinCardinality(object.getCardinality(),object.getProperty(),definition);
            }
        }
        public OWLClassExpression visit(OWLObjectMaxCardinality object) {
            m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(object.getProperty().getNamedProperty());
            OWLClassExpression filler=object.getFiller();
            if (isSimple(filler))
                return object;
            else {
                OWLClassExpression complementDescription=m_expressionManager.getComplementNNF(filler);
                OWLClassExpression definition=getDefinitionFor(complementDescription,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newInclusions.add(new OWLClassExpression[] { negative(definition),complementDescription });
                return m_factory.getOWLObjectMaxCardinality(object.getCardinality(),object.getProperty(),m_expressionManager.getComplementNNF(definition));
            }
        }
        public OWLClassExpression visit(OWLObjectExactCardinality object) {
            throw new IllegalStateException("Internal error: exact object cardinality restrictions should have been simplified.");
        }
        public OWLClassExpression visit(OWLDataSomeValuesFrom object) {
            OWLDataRange filler=object.getFiller();
            OWLDataPropertyExpression prop=object.getProperty();
            if (prop.isOWLTopDataProperty())
                throwInvalidTopDPUseError(object);
            if (isLiteral(filler))
                return m_factory.getOWLDataSomeValuesFrom(object.getProperty(),filler);
            else {
                OWLDatatype definition=getDefinitionFor(filler,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newDataRangeInclusions.add(new OWLDataRange[] { negative(definition),filler });
                return m_factory.getOWLDataSomeValuesFrom(object.getProperty(),definition);
            }
        }
        public OWLClassExpression visit(OWLDataAllValuesFrom object) {
            OWLDataRange filler=object.getFiller();
            OWLDataPropertyExpression prop=object.getProperty();
            if (prop.isOWLTopDataProperty())
                throwInvalidTopDPUseError(object);
            if (isLiteral(filler))
                return m_factory.getOWLDataAllValuesFrom(prop,filler);
            else {
                OWLDatatype definition=getDefinitionFor(filler,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newDataRangeInclusions.add(new OWLDataRange[] { negative(definition),filler });
                return m_factory.getOWLDataAllValuesFrom(prop,definition);
            }
        }
        protected void throwInvalidTopDPUseError(OWLClassExpression ex) {
            throw new IllegalArgumentException("Error: In OWL 2 DL, owl:topDataProperty is only allowed to occur in the super property position of SubDataPropertyOf axioms, but the ontology contains an axiom with the class expression "+ex+" that violates this restriction.");
        }
        public OWLClassExpression visit(OWLDataHasValue object) {
            throw new IllegalStateException("Internal error: data value restrictions should have been simplified.");
        }
        public OWLClassExpression visit(OWLDataMinCardinality object) {
            OWLDataRange filler=object.getFiller();
            OWLDataPropertyExpression prop=object.getProperty();
            if (prop.isOWLTopDataProperty())
                throwInvalidTopDPUseError(object);
            if (isLiteral(filler))
                return m_factory.getOWLDataMinCardinality(object.getCardinality(),prop,filler);
            else {
                OWLDatatype definition=getDefinitionFor(filler,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newDataRangeInclusions.add(new OWLDataRange[] { negative(definition),filler });
                return m_factory.getOWLDataMinCardinality(object.getCardinality(),prop,definition);
            }
        }
        public OWLClassExpression visit(OWLDataMaxCardinality object) {
            OWLDataRange filler=object.getFiller();
            OWLDataPropertyExpression prop=object.getProperty();
            if (prop.isOWLTopDataProperty())
                throwInvalidTopDPUseError(object);
            if (isLiteral(filler))
                return m_factory.getOWLDataMaxCardinality(object.getCardinality(),prop,filler);
            else {
                OWLDataRange complementDescription=m_expressionManager.getComplementNNF(filler);
                OWLDatatype definition=getDefinitionFor(complementDescription,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newDataRangeInclusions.add(new OWLDataRange[] { negative(definition),filler });
                return m_factory.getOWLDataMaxCardinality(object.getCardinality(),prop,m_expressionManager.getComplementNNF(definition));
            }
        }
        public OWLClassExpression visit(OWLDataExactCardinality object) {
            throw new IllegalStateException("Internal error: exact data cardinality restrictions should have been simplified.");
        }
    }

    protected class DataRangeNormalizer implements OWLDataVisitorEx {
        protected final Collection m_newDataRangeInclusions;
        protected final boolean[] m_alreadyExists;

        public DataRangeNormalizer(Collection newDataRangeInclusions) {
            m_newDataRangeInclusions=newDataRangeInclusions;
            m_alreadyExists=new boolean[1];
        }
        public OWLDataRange visit(OWLDatatype node) {
            return node;
        }
        public OWLDataRange visit(OWLDataComplementOf node) {
            return node;
        }
        public OWLDataRange visit(OWLDataOneOf node) {
            return node;
        }
        public OWLDataRange visit(OWLDataIntersectionOf object) {
            OWLDataRange definition=getDefinitionFor(object,m_alreadyExists);
            if (!m_alreadyExists[0])
                for (OWLDataRange description : object.getOperands())
                    m_newDataRangeInclusions.add(new OWLDataRange[] { negative(definition),description });
            return definition;
        }
        public OWLDataRange visit(OWLDataUnionOf node) {
            throw new IllegalStateException("OR should be broken down at the outermost level");
        }
        public OWLDataRange visit(OWLDatatypeRestriction node) {
            return node;
        }
        public OWLDataRange visit(OWLFacetRestriction node) {
            throw new IllegalStateException("Internal error: We shouldn't visit facet restrictions during normalization. ");
        }
        public OWLDataRange visit(OWLLiteral node) {
            throw new IllegalStateException("Internal error: We shouldn't visit typed literals during normalization. ");
        }
    }

    protected class Rule2FactConverter implements SWRLObjectVisitor {

        protected final boolean[] m_alreadyExists;
        protected final Collection m_newInclusions;
        protected int freshDataProperties=0;
        protected int freshIndividuals=0;

        public Rule2FactConverter(Collection newInclusions) {
            m_alreadyExists=new boolean[1];
            m_newInclusions=newInclusions;
        }
        protected OWLNamedIndividual getFreshIndividual() {
            OWLNamedIndividual freshInd=m_factory.getOWLNamedIndividual(IRI.create("internal:nom#swrlfact"+freshIndividuals));
            freshIndividuals++;
            m_axioms.m_namedIndividuals.add(freshInd);
            return freshInd;
        }
        protected OWLDataProperty getFreshDataProperty() {
            freshDataProperties++;
            return m_factory.getOWLDataProperty(IRI.create("internal:freshDP#"+freshDataProperties));
        }
        public void visit(SWRLRule rule) {
        }
        public void visit(SWRLClassAtom atom) {
            if (!(atom.getArgument() instanceof SWRLIndividualArgument))
                throw new IllegalArgumentException("A SWRL rule contains a head atom "+atom+" with a variable that does not occur in the body. ");
            OWLIndividual ind=((SWRLIndividualArgument)atom.getArgument()).getIndividual();
            if (ind.isAnonymous())
                throwAnonIndError(atom);
            if (!isSimple(atom.getPredicate())) {
                OWLClassExpression definition=getDefinitionFor(atom.getPredicate(),m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_newInclusions.add(new OWLClassExpression[] { negative(definition),atom.getPredicate() });
                addFact(m_factory.getOWLClassAssertionAxiom(definition,ind.asOWLNamedIndividual()));
            }
            else
                addFact(m_factory.getOWLClassAssertionAxiom(atom.getPredicate(),ind.asOWLNamedIndividual()));
        }
        public void visit(SWRLDataRangeAtom atom) {
            if (atom.getArgument() instanceof SWRLVariable)
                throwVarError(atom);
            // dr(literal) :-
            // convert to: ClassAssertion(DataSomeValuesFrom(freshDP DataOneOf(literal)) freshIndividual)
            // and top -> \forall freshDP.dr
            OWLLiteral lit=((SWRLLiteralArgument)atom.getArgument()).getLiteral();
            OWLDataRange dr=atom.getPredicate();
            OWLNamedIndividual freshIndividual=getFreshIndividual();
            OWLDataProperty freshDP=getFreshDataProperty();
            OWLDataSomeValuesFrom some=m_factory.getOWLDataSomeValuesFrom(freshDP,m_factory.getOWLDataOneOf(lit));
            OWLClassExpression definition=getDefinitionFor(some,m_alreadyExists);
            if (!m_alreadyExists[0])
                m_newInclusions.add(new OWLClassExpression[] { negative(definition),some });
            addFact(m_factory.getOWLClassAssertionAxiom(definition,freshIndividual));
            m_newInclusions.add(new OWLClassExpression[] { m_factory.getOWLDataAllValuesFrom(freshDP,dr) });
        }

        public void visit(SWRLObjectPropertyAtom atom) {
            if (!(atom.getFirstArgument() instanceof SWRLIndividualArgument) || !(atom.getSecondArgument() instanceof SWRLIndividualArgument))
                throwVarError(atom);
            OWLObjectPropertyExpression ope=atom.getPredicate().getSimplified();
            OWLIndividual first=((SWRLIndividualArgument)atom.getFirstArgument()).getIndividual();
            OWLIndividual second=((SWRLIndividualArgument)atom.getSecondArgument()).getIndividual();
            if (first.isAnonymous() || second.isAnonymous())
                throwAnonIndError(atom);
            if (ope.isAnonymous())
                addFact(m_factory.getOWLObjectPropertyAssertionAxiom(ope.getNamedProperty(),second.asOWLNamedIndividual(),first.asOWLNamedIndividual()));
            else
                addFact(m_factory.getOWLObjectPropertyAssertionAxiom(ope.asOWLObjectProperty(),first.asOWLNamedIndividual(),second.asOWLNamedIndividual()));
        }
        public void visit(SWRLDataPropertyAtom atom) {
            if (!(atom.getSecondArgument() instanceof SWRLLiteralArgument))
                throwVarError(atom);
            if (!(atom.getFirstArgument() instanceof SWRLIndividualArgument))
                throwVarError(atom);
            OWLIndividual ind=((SWRLIndividualArgument)atom.getFirstArgument()).getIndividual();
            if (ind.isAnonymous())
                throwAnonIndError(atom);
            OWLLiteral lit=((SWRLLiteralArgument)atom.getSecondArgument()).getLiteral();
            addFact(m_factory.getOWLDataPropertyAssertionAxiom(atom.getPredicate().asOWLDataProperty(),ind.asOWLNamedIndividual(),lit));
        }
        public void visit(SWRLBuiltInAtom atom) {
            throw new IllegalArgumentException("Error: A rule uses built-in atoms ("+atom+"), but built-in atoms are not supported yet. ");
        }
        public void visit(SWRLSameIndividualAtom atom) {
            Set inds=new HashSet();
            for (SWRLArgument arg : atom.getAllArguments()) {
                if (!(arg instanceof SWRLIndividualArgument))
                    throwVarError(atom);
                OWLIndividual ind=((SWRLIndividualArgument)arg).getIndividual();
                if (ind.isAnonymous())
                    throwAnonIndError(atom);
                inds.add(ind.asOWLNamedIndividual());
            }
            addFact(m_factory.getOWLSameIndividualAxiom(inds));
        }
        public void visit(SWRLDifferentIndividualsAtom atom) {
            Set inds=new HashSet();
            for (SWRLArgument arg : atom.getAllArguments()) {
                if (!(arg instanceof SWRLIndividualArgument))
                    throwVarError(atom);
                OWLIndividual ind=((SWRLIndividualArgument)arg).getIndividual();
                if (ind.isAnonymous())
                    throwAnonIndError(atom);
                inds.add(ind.asOWLNamedIndividual());
            }
            addFact(m_factory.getOWLDifferentIndividualsAxiom(inds));
        }
        public void visit(SWRLVariable variable) {
        }
        public void visit(SWRLIndividualArgument argument) {
        }
        public void visit(SWRLLiteralArgument argument) {
        }
        protected void throwAnonIndError(SWRLAtom atom) {
            throw new IllegalArgumentException("A SWRL rule contains a fact ("+atom+") with an anonymous individual, which is not allowed. ");
        }
        protected void throwVarError(SWRLAtom atom) {
            throw new IllegalArgumentException("A SWRL rule contains a head atom ("+atom+") with a variable that does not occur in the body. ");
        }
    }

    protected final class RuleNormalizer implements SWRLObjectVisitor {
        protected final Collection m_rules;
        protected final Collection m_classExpressionInclusions;
        protected final Collection m_dataRangeInclusions;
        protected final boolean[] m_alreadyExists;
        protected final List m_bodyAtoms=new ArrayList();
        protected final List m_headAtoms=new ArrayList();
        protected final Set m_normalizedBodyAtoms=new HashSet();
        protected final Set m_normalizedHeadAtoms=new HashSet();
        protected final Map m_variableRepresentative=new HashMap();
        protected final Map m_individualsToVariables=new HashMap();
        protected final Set m_bodyDataRangeVariables=new HashSet();
        protected final Set m_headDataRangeVariables=new HashSet();
        protected int m_newVariableIndex=0;
        protected boolean m_isPositive;

        public RuleNormalizer(Collection rules,Collection classExpressionInclusionsFromRules,Collection newDataRangeInclusions) {
            m_rules=rules;
            m_classExpressionInclusions=classExpressionInclusionsFromRules;
            m_dataRangeInclusions=newDataRangeInclusions;
            m_alreadyExists=new boolean[1];
        }
        public void visit(SWRLRule rule) {
            // Process head one-by-one and thus break up the conjunction in the head.
            for (SWRLAtom headAtom : rule.getHead()) {
                m_individualsToVariables.clear();
                m_bodyAtoms.clear();
                m_headAtoms.clear();
                m_variableRepresentative.clear();
                m_normalizedBodyAtoms.clear();
                m_normalizedHeadAtoms.clear();
                m_bodyDataRangeVariables.clear();
                m_headDataRangeVariables.clear();

                // Initialize body with all atoms, and initialize head with just the atom we are processing.
                m_bodyAtoms.addAll(rule.getBody());
                m_headAtoms.add(headAtom);

                // First process sameIndividual in the body to set up variable normalizations.
                for (SWRLAtom atom : rule.getBody()) {
                    if (atom instanceof SWRLSameIndividualAtom) {
                        m_bodyAtoms.remove(atom);
                        SWRLSameIndividualAtom sameIndividualAtom=(SWRLSameIndividualAtom)atom;
                        SWRLVariable variable1=getVariableFor(sameIndividualAtom.getFirstArgument());
                        SWRLIArgument argument2=sameIndividualAtom.getSecondArgument();
                        if (argument2 instanceof SWRLVariable)
                            m_variableRepresentative.put((SWRLVariable)argument2,variable1);
                        else {
                            OWLIndividual individual=((SWRLIndividualArgument)argument2).getIndividual();
                            if (individual.isAnonymous())
                                throw new IllegalArgumentException("Internal error: Rules with anonymous individuals are not supported. ");
                            m_individualsToVariables.put(individual.asOWLNamedIndividual(),variable1);
                            m_bodyAtoms.add(m_factory.getSWRLClassAtom(m_factory.getOWLObjectOneOf(individual),variable1));
                        }
                    }
                }

                // Now process head atoms; this might increase the number of body atoms.
                m_isPositive=true;
                while (!m_headAtoms.isEmpty())
                    m_headAtoms.remove(0).accept(this);

                // Now process body atoms.
                m_isPositive=false;
                while (!m_bodyAtoms.isEmpty())
                    m_bodyAtoms.remove(0).accept(this);

                // Do some checking and return the rule.
                if (!m_bodyDataRangeVariables.containsAll(m_headDataRangeVariables))
                    throw new IllegalArgumentException("A SWRL rule contains data range variables in the head, but not in the body, and this is not supported.");
                m_rules.add(new OWLAxioms.DisjunctiveRule(m_normalizedBodyAtoms.toArray(new SWRLAtom[m_normalizedBodyAtoms.size()]),m_normalizedHeadAtoms.toArray(new SWRLAtom[m_normalizedHeadAtoms.size()])));
            }
        }
        public void visit(SWRLClassAtom at) {
            OWLClassExpression c=m_expressionManager.getSimplified(m_expressionManager.getNNF(at.getPredicate()));
            SWRLVariable variable=getVariableFor(at.getArgument());
            if (m_isPositive) {
                // head
                if (c instanceof OWLClass)
                    m_normalizedHeadAtoms.add(m_factory.getSWRLClassAtom(c,variable));
                else {
                    OWLClass definition=getClassFor(at.getPredicate(),m_alreadyExists);
                    if (!m_alreadyExists[0])
                        m_classExpressionInclusions.add(new OWLClassExpression[] { negative(definition),at.getPredicate() });
                    m_normalizedHeadAtoms.add(m_factory.getSWRLClassAtom(definition,variable));
                }
            }
            else {
                // body
                if (c instanceof OWLClass)
                    m_normalizedBodyAtoms.add(m_factory.getSWRLClassAtom(c,variable));
                else {
                    OWLClass definition=getClassFor(at.getPredicate(),m_alreadyExists);
                    if (!m_alreadyExists[0])
                        m_classExpressionInclusions.add(new OWLClassExpression[] { negative(at.getPredicate()),definition });
                    m_normalizedBodyAtoms.add(m_factory.getSWRLClassAtom(definition,variable));
                }
            }
        }
        public void visit(SWRLDataRangeAtom at) {
            OWLDataRange dr=at.getPredicate();
            SWRLDArgument argument=at.getArgument();
            if (!(argument instanceof SWRLVariable))
                throw new IllegalArgumentException("A SWRL rule contains a data range with an argument that is not a literal, and such rules are not supported.");
            if (!m_isPositive)
                dr=m_factory.getOWLDataComplementOf(dr);
            dr=m_expressionManager.getNNF(m_expressionManager.getSimplified(dr));
            if (dr instanceof OWLDataIntersectionOf || dr instanceof OWLDataUnionOf) {
                OWLDatatype definition=getDefinitionFor(dr,m_alreadyExists);
                if (!m_alreadyExists[0])
                    m_dataRangeInclusions.add(new OWLDataRange[] { negative(definition),dr });
                dr=definition;
            }
            SWRLAtom atom=m_factory.getSWRLDataRangeAtom(dr,argument);
            m_normalizedHeadAtoms.add(atom);
            m_headDataRangeVariables.add((SWRLVariable)argument);
        }
        public void visit(SWRLObjectPropertyAtom at) {
            OWLObjectPropertyExpression ope=at.getPredicate().getSimplified();
            OWLObjectProperty op=ope.getNamedProperty();
            SWRLVariable variable1;
            SWRLVariable variable2;
            if (ope.isAnonymous()) {
                variable1=getVariableFor(at.getSecondArgument());
                variable2=getVariableFor(at.getFirstArgument());
            }
            else {
                variable1=getVariableFor(at.getFirstArgument());
                variable2=getVariableFor(at.getSecondArgument());

            }
            SWRLAtom newAtom=m_factory.getSWRLObjectPropertyAtom(op,variable1,variable2);
            if (m_isPositive) {
                // head
                m_normalizedHeadAtoms.add(newAtom);
            }
            else {
                // body
                m_normalizedBodyAtoms.add(newAtom);
            }
        }
        public void visit(SWRLDataPropertyAtom at) {
            OWLDataProperty dp=at.getPredicate().asOWLDataProperty();
            SWRLVariable variable1=getVariableFor(at.getFirstArgument());
            SWRLDArgument argument2=at.getSecondArgument();
            if (argument2 instanceof SWRLVariable) {
                SWRLVariable variable2=getVariableFor((SWRLVariable)argument2);
                if (m_isPositive) {
                    m_normalizedHeadAtoms.add(m_factory.getSWRLDataPropertyAtom(dp,variable1,variable2));
                    m_headDataRangeVariables.add(variable2);
                }
                else {
                    if (m_bodyDataRangeVariables.add(variable2))
                        m_normalizedBodyAtoms.add(m_factory.getSWRLDataPropertyAtom(dp,variable1,variable2));
                    else {
                        SWRLVariable variable2Fresh=getFreshVariable();
                        m_normalizedBodyAtoms.add(m_factory.getSWRLDataPropertyAtom(dp,variable1,variable2Fresh));
                        m_normalizedHeadAtoms.add(m_factory.getSWRLDifferentIndividualsAtom(variable2,variable2Fresh));
                    }
                }
            }
            else {
                OWLLiteral literal=((SWRLLiteralArgument)argument2).getLiteral();
                SWRLAtom newAtom=m_factory.getSWRLClassAtom(m_factory.getOWLDataHasValue(dp,literal),variable1);
                if (m_isPositive)
                    m_headAtoms.add(newAtom);
                else
                    m_bodyAtoms.add(newAtom);
            }
        }
        public void visit(SWRLBuiltInAtom at) {
            throw new IllegalArgumentException("A SWRL rule uses a built-in atom, but built-in atoms are not supported yet.");
        }
        public void visit(SWRLSameIndividualAtom at) {
            if (m_isPositive)
                m_normalizedHeadAtoms.add(m_factory.getSWRLSameIndividualAtom(getVariableFor(at.getFirstArgument()),getVariableFor(at.getSecondArgument())));
            else
                throw new IllegalStateException("Internal error: this SWRLSameIndividualAtom should have been processed earlier.");
        }
        public void visit(SWRLDifferentIndividualsAtom at) {
            if (m_isPositive)
                m_normalizedHeadAtoms.add(m_factory.getSWRLDifferentIndividualsAtom(getVariableFor(at.getFirstArgument()),getVariableFor(at.getSecondArgument())));
            else
                m_normalizedHeadAtoms.add(m_factory.getSWRLSameIndividualAtom(getVariableFor(at.getFirstArgument()),getVariableFor(at.getSecondArgument())));
        }
        public void visit(SWRLVariable variable) {
            // nothing to do
        }
        public void visit(SWRLIndividualArgument argument) {
            // nothing to do
        }
        public void visit(SWRLLiteralArgument argument) {
            // nothing to do
        }
        protected SWRLVariable getVariableFor(SWRLIArgument term) {
            SWRLVariable variable;
            if (term instanceof SWRLIndividualArgument) {
                OWLIndividual individual=((SWRLIndividualArgument)term).getIndividual();
                if (individual.isAnonymous())
                    throw new IllegalArgumentException("Internal error: Rules with anonymous individuals are not supported. ");
                variable=m_individualsToVariables.get(individual.asOWLNamedIndividual());
                if (variable==null) {
                    variable=getFreshVariable();
                    m_individualsToVariables.put(individual.asOWLNamedIndividual(),variable);
                    m_bodyAtoms.add(m_factory.getSWRLClassAtom(m_factory.getOWLObjectOneOf(individual),variable));
                }
            }
            else
                variable=(SWRLVariable)term;
            SWRLVariable representative=m_variableRepresentative.get(variable);
            if (representative==null)
                return variable;
            else
                return representative;
        }
        protected SWRLVariable getFreshVariable() {
            SWRLVariable variable=m_factory.getSWRLVariable(IRI.create("internal:swrl#"+m_newVariableIndex));
            m_newVariableIndex++;
            return variable;
        }
    }

    /**
     * checks the polarity
     */
    protected class PLVisitor implements OWLClassExpressionVisitorEx {

        public Boolean visit(OWLClass object) {
            if (object.isOWLThing())
                return Boolean.FALSE;
            else if (object.isOWLNothing())
                return Boolean.FALSE;
            else
                return Boolean.TRUE;
        }
        public Boolean visit(OWLObjectIntersectionOf object) {
            for (OWLClassExpression desc : object.getOperands())
                if (desc.accept(this))
                    return Boolean.TRUE;
            return Boolean.FALSE;
        }
        public Boolean visit(OWLObjectUnionOf object) {
            for (OWLClassExpression desc : object.getOperands())
                if (desc.accept(this))
                    return Boolean.TRUE;
            return Boolean.FALSE;
        }
        public Boolean visit(OWLObjectComplementOf object) {
            return Boolean.FALSE;
        }
        public Boolean visit(OWLObjectOneOf object) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLObjectSomeValuesFrom object) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLObjectAllValuesFrom object) {
            return object.getFiller().accept(this);
        }
        public Boolean visit(OWLObjectHasValue object) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLObjectHasSelf object) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLObjectMinCardinality object) {
            return object.getCardinality()>0;
        }
        public Boolean visit(OWLObjectMaxCardinality object) {
            return object.getCardinality()>0 ? Boolean.TRUE : m_expressionManager.getComplementNNF(object.getFiller()).accept(this);
        }
        public Boolean visit(OWLObjectExactCardinality object) {
            return object.getCardinality()>0 ? Boolean.TRUE : m_expressionManager.getComplementNNF(object.getFiller()).accept(this);
        }
        public Boolean visit(OWLDataSomeValuesFrom desc) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLDataAllValuesFrom desc) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLDataHasValue desc) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLDataMinCardinality desc) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLDataMaxCardinality desc) {
            return Boolean.TRUE;
        }
        public Boolean visit(OWLDataExactCardinality desc) {
            return Boolean.TRUE;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy