fr.lirmm.graphik.graal.io.owl.OWLAxiomParser.java Source code

Java tutorial

Introduction

Here is the source code for fr.lirmm.graphik.graal.io.owl.OWLAxiomParser.java

Source

/*
 * Copyright (C) Inria Sophia Antipolis - Mditerrane / LIRMM
 * (Universit de Montpellier & CNRS) (2014 - 2015)
 *
 * Contributors :
 *
 * Clment SIPIETER <clement.sipieter@inria.fr>
 * Mlanie KNIG
 * Swan ROCHER
 * Jean-Franois BAGET
 * Michel LECLRE
 * Marie-Laure MUGNIER <mugnier@lirmm.fr>
 *
 *
 * This file is part of Graal <https://graphik-team.github.io/graal/>.
 *
 * This software is governed by the CeCILL  license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 */
/**
* 
*/
package fr.lirmm.graphik.graal.io.owl;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang3.tuple.Pair;
import org.semanticweb.owlapi.model.OWLAnnotation;
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.OWLAxiomVisitorEx;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
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.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.OWLDatatypeDefinitionAxiom;
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.OWLFunctionalDataPropertyAxiom;
import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLHasKeyAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLIrreflexiveObjectPropertyAxiom;
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.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.OWLPropertyExpression;
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.SWRLRule;
import org.semanticweb.owlapi.util.ShortFormProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLDataMaxCardinalityImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLDataMinCardinalityImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLDataSomeValuesFromImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectIntersectionOfImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectMaxCardinalityImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectMinCardinalityImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectOneOfImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectSomeValuesFromImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLSubClassOfAxiomImpl;
import fr.lirmm.graphik.graal.api.core.Atom;
import fr.lirmm.graphik.graal.api.core.AtomSet;
import fr.lirmm.graphik.graal.api.core.InMemoryAtomSet;
import fr.lirmm.graphik.graal.api.core.Predicate;
import fr.lirmm.graphik.graal.api.core.Rule;
import fr.lirmm.graphik.graal.api.core.Term;
import fr.lirmm.graphik.graal.api.core.Variable;
import fr.lirmm.graphik.graal.api.core.VariableGenerator;
import fr.lirmm.graphik.graal.core.DefaultAtom;
import fr.lirmm.graphik.graal.core.DefaultNegativeConstraint;
import fr.lirmm.graphik.graal.core.atomset.LinkedListAtomSet;
import fr.lirmm.graphik.graal.core.factory.RuleFactory;
import fr.lirmm.graphik.graal.core.term.DefaultTermFactory;
import fr.lirmm.graphik.util.MathUtils;
import fr.lirmm.graphik.util.collections.CollectionsUtils;

/**
 * @author Clment Sipieter (INRIA) {@literal <clement@6pi.fr>}
 *
 */
class OWLAxiomParser implements OWLAxiomVisitorEx<Iterable<? extends Object>> {

    private static final Logger LOGGER = LoggerFactory.getLogger(OWLAxiomParser.class);

    private SpecificFreeVarGen freeVarGen = new SpecificFreeVarGen();
    private static final OWLDataFactory DF = new OWLDataFactoryImpl();
    private static final OWLClassExpression NOTHING = DF.getOWLNothing();

    private Variable glueVarX;
    private Variable glueVarY;
    private Variable glueVarZ;

    private ShortFormProvider prefixManager;
    private Predicate equalityPredicate;
    private OWLEquivalentClassExpressionVisitorImpl classVisitorX;
    private OWLEquivalentClassExpressionVisitorImpl classVisitorY;
    private OWLEquivalentClassExpressionVisitorImpl classVisitorZ;

    private OWLEquivalentDataRangeVisitorImpl dataRangeVisitorX;
    private OWLEquivalentDataRangeVisitorImpl dataRangeVisitorY;
    private OWLEquivalentDataRangeVisitorImpl dataRangeVisitorZ;

    private OWLPropertyExpressionVisitorImpl propertyVisiotrXX;
    private OWLPropertyExpressionVisitorImpl propertyVisitorXY;
    private OWLPropertyExpressionVisitorImpl propertyVisitorYX;
    private OWLPropertyExpressionVisitorImpl propertyVisitorXZ;
    private OWLPropertyExpressionVisitorImpl propertyVisitorYZ;

    private Collection<OWLAnnotation> emptyAnno = Collections.<OWLAnnotation>emptyList();

    public OWLAxiomParser(ShortFormProvider prefixManager) {
        this.prefixManager = prefixManager;
        this.glueVarX = freeVarGen.getFreshVar();
        this.glueVarY = freeVarGen.getFreshVar();
        this.glueVarZ = freeVarGen.getFreshVar();

        this.equalityPredicate = new Predicate("=", 2);
        this.classVisitorX = new OWLEquivalentClassExpressionVisitorImpl(this.prefixManager, freeVarGen, glueVarX);
        this.classVisitorY = new OWLEquivalentClassExpressionVisitorImpl(this.prefixManager, freeVarGen, glueVarY);
        this.classVisitorZ = new OWLEquivalentClassExpressionVisitorImpl(this.prefixManager, freeVarGen, glueVarZ);

        this.dataRangeVisitorX = new OWLEquivalentDataRangeVisitorImpl(glueVarX);
        this.dataRangeVisitorY = new OWLEquivalentDataRangeVisitorImpl(glueVarY);
        this.dataRangeVisitorZ = new OWLEquivalentDataRangeVisitorImpl(glueVarZ);

        this.propertyVisiotrXX = new OWLPropertyExpressionVisitorImpl(glueVarX, glueVarX);
        this.propertyVisitorXY = new OWLPropertyExpressionVisitorImpl(glueVarX, glueVarY);
        this.propertyVisitorYX = new OWLPropertyExpressionVisitorImpl(glueVarY, glueVarX);
        this.propertyVisitorXZ = new OWLPropertyExpressionVisitorImpl(glueVarX, glueVarZ);
        this.propertyVisitorYZ = new OWLPropertyExpressionVisitorImpl(glueVarY, glueVarZ);
    }

    // /////////////////////////////////////////////////////////////////////////
    // Declaration
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLDeclarationAxiom arg) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Visit OWLDeclarationAxiom: " + arg);
        }
        return Collections.emptyList();
    }

    // /////////////////////////////////////////////////////////////////////////
    // ClassAxiom
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLSubClassOfAxiom arg) {
        Collection<Object> objects = new LinkedList<Object>();

        freeVarGen.setIndex(3);
        OWLClassExpression superClass = OWLAPIUtils.classExpressionDisjunctiveNormalForm(arg.getSuperClass());
        OWLClassExpression subClass = OWLAPIUtils.classExpressionDisjunctiveNormalForm(arg.getSubClass());

        if (OWLAPIUtils.isIntersection(superClass)) {
            for (OWLClassExpression c : OWLAPIUtils.getObjectIntersectionOperands(superClass)) {
                CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, c, emptyAnno).accept(this));
            }
        } else if (superClass instanceof OWLObjectComplementOf) {
            TreeSet<OWLClassExpression> operands = new TreeSet<>();
            operands.add(subClass);
            operands.add(((OWLObjectComplementOf) superClass).getOperand());
            subClass = new OWLObjectIntersectionOfImpl(operands);
            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, NOTHING, emptyAnno).accept(this));
        } else if (superClass instanceof OWLObjectAllValuesFrom) {
            OWLObjectAllValuesFrom allValuesFrom = (OWLObjectAllValuesFrom) superClass;
            subClass = new OWLObjectSomeValuesFromImpl(allValuesFrom.getProperty().getInverseProperty(), subClass);
            superClass = allValuesFrom.getFiller();
            CollectionsUtils.addAll(objects,
                    new OWLSubClassOfAxiomImpl(subClass, superClass, emptyAnno).accept(this));
        } else if (superClass instanceof OWLObjectMaxCardinality
                && ((OWLObjectMaxCardinality) superClass).getCardinality() == 0) {
            TreeSet<OWLClassExpression> operands = new TreeSet<>();
            operands.add(subClass);
            OWLObjectMaxCardinality maxCard = (OWLObjectMaxCardinality) superClass;
            operands.add(new OWLObjectSomeValuesFromImpl(maxCard.getProperty(), maxCard.getFiller()));
            subClass = new OWLObjectIntersectionOfImpl(operands);
            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, NOTHING, emptyAnno).accept(this));
        } else if (superClass instanceof OWLDataMaxCardinality
                && ((OWLDataMaxCardinality) superClass).getCardinality() == 0) {
            TreeSet<OWLClassExpression> operands = new TreeSet<>();
            operands.add(subClass);
            OWLDataMaxCardinality maxCard = (OWLDataMaxCardinality) superClass;
            operands.add(new OWLDataSomeValuesFromImpl(maxCard.getProperty(), maxCard.getFiller()));
            subClass = new OWLObjectIntersectionOfImpl(operands);
            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, NOTHING, emptyAnno).accept(this));
        } else if (superClass instanceof OWLObjectExactCardinality
                && ((OWLObjectExactCardinality) superClass).getCardinality() <= 1) {
            OWLObjectExactCardinality exactCard = (OWLObjectExactCardinality) superClass;
            OWLObjectMaxCardinality maxCard = new OWLObjectMaxCardinalityImpl(exactCard.getProperty(),
                    exactCard.getCardinality(), exactCard.getFiller());
            OWLObjectMinCardinality minCard = new OWLObjectMinCardinalityImpl(exactCard.getProperty(),
                    exactCard.getCardinality(), exactCard.getFiller());

            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, maxCard, emptyAnno).accept(this));
            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, minCard, emptyAnno).accept(this));
        } else if (superClass instanceof OWLDataExactCardinality
                && ((OWLDataExactCardinality) superClass).getCardinality() <= 1) {
            OWLDataExactCardinality exactCard = (OWLDataExactCardinality) superClass;
            OWLDataMaxCardinality maxCard = new OWLDataMaxCardinalityImpl(exactCard.getProperty(),
                    exactCard.getCardinality(), exactCard.getFiller());
            OWLDataMinCardinality minCard = new OWLDataMinCardinalityImpl(exactCard.getProperty(),
                    exactCard.getCardinality(), exactCard.getFiller());

            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, maxCard, emptyAnno).accept(this));
            CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(subClass, minCard, emptyAnno).accept(this));
        } else if (isSuperClass(superClass)) {
            if (subClass instanceof OWLObjectUnionOf) {
                for (OWLClassExpression c : OWLAPIUtils.getObjectUnionOperands(subClass)) {
                    CollectionsUtils.addAll(objects,
                            new OWLSubClassOfAxiomImpl(c, superClass, emptyAnno).accept(this));
                }
            } else if (isEquivClass(subClass)) {
                CollectionsUtils.addAll(objects, mainProcess(arg));
            } else {
                if (LOGGER.isWarnEnabled()) {
                    LOGGER.warn(
                            "[ " + subClass + "] is not supported as subClass. This axioms was skipped : " + arg);
                }
            }
        } else {
            if (LOGGER.isWarnEnabled()) {
                LOGGER.warn(
                        "[ " + superClass + "] is not supported as superClass. This axioms was skipped : " + arg);
            }
        }

        return objects;
    }

    @Override
    public Iterable<? extends Object> visit(OWLEquivalentClassesAxiom arg) {
        Collection<Object> objects = new LinkedList<Object>();
        List<OWLClassExpression> classes = new LinkedList<OWLClassExpression>(arg.getClassExpressionsAsList());

        Iterator<OWLClassExpression> it1, it2;
        it1 = classes.iterator();
        while (it1.hasNext()) {
            OWLClassExpression classExpr = it1.next();
            it1.remove();

            it2 = classes.iterator();
            while (it2.hasNext()) {
                OWLClassExpression next = it2.next();
                CollectionsUtils.addAll(objects,
                        new OWLSubClassOfAxiomImpl(classExpr, next, emptyAnno).accept(this));
                CollectionsUtils.addAll(objects,
                        new OWLSubClassOfAxiomImpl(next, classExpr, emptyAnno).accept(this));
            }
        }
        return objects;
    }

    @Override
    public Iterable<? extends Object> visit(OWLDisjointClassesAxiom arg) {
        Collection<Object> objects = new LinkedList<Object>();

        List<OWLClassExpression> classes = new LinkedList<OWLClassExpression>(arg.getClassExpressionsAsList());

        Iterator<OWLClassExpression> it1, it2;
        it1 = classes.iterator();
        while (it1.hasNext()) {
            OWLClassExpression classExpr = it1.next();
            it1.remove();

            it2 = classes.iterator();
            while (it2.hasNext()) {
                OWLClassExpression next = it2.next();
                Set<OWLClassExpression> operands = new TreeSet<>();
                operands.add(classExpr);
                operands.add(next);
                OWLClassExpression newExpr = new OWLObjectIntersectionOfImpl(operands);
                CollectionsUtils.addAll(objects,
                        new OWLSubClassOfAxiomImpl(newExpr, NOTHING, emptyAnno).accept(this));
            }
        }

        return objects;
    }

    @Override
    public Iterable<? extends Object> visit(OWLDisjointUnionAxiom arg) {
        if (LOGGER.isWarnEnabled()) {
            LOGGER.warn("OWLDisjointUnionAxion is not supported. This axioms was skipped : " + arg);
        }
        return Collections.emptyList();
    }

    // /////////////////////////////////////////////////////////////////////////
    // ObjectPropertyAxiom
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLSubObjectPropertyOfAxiom arg) {
        InMemoryAtomSet a1, a2;
        a1 = arg.getSubProperty().accept(propertyVisitorXY);
        a2 = arg.getSuperProperty().accept(propertyVisitorXY);

        return Collections.singleton(RuleFactory.instance().create(a1, a2));
    }

    @Override
    public Iterable<? extends Object> visit(OWLObjectPropertyDomainAxiom arg) {
        OWLClassExpression subClass = new OWLObjectSomeValuesFromImpl(arg.getProperty(), DF.getOWLThing());
        OWLClassExpression superClass = arg.getDomain();
        return new OWLSubClassOfAxiomImpl(subClass, superClass, emptyAnno).accept(this);
    }

    @Override
    public Iterable<? extends Object> visit(OWLObjectPropertyRangeAxiom arg) {
        OWLClassExpression subClass = new OWLObjectSomeValuesFromImpl(arg.getProperty().getInverseProperty(),
                DF.getOWLThing());
        OWLClassExpression superClass = arg.getRange();
        return new OWLSubClassOfAxiomImpl(subClass, superClass, emptyAnno).accept(this);
    }

    @Override
    public Iterable<? extends Object> visit(OWLAsymmetricObjectPropertyAxiom arg) {
        InMemoryAtomSet atomset = arg.getProperty().accept(propertyVisitorXY);
        atomset.addAll(arg.getProperty().accept(propertyVisitorYX));
        return Collections.singleton(new DefaultNegativeConstraint(atomset));
    }

    @Override
    public Iterable<? extends Object> visit(OWLReflexiveObjectPropertyAxiom arg) {

        InMemoryAtomSet head = arg.getProperty().accept(propertyVisiotrXX);
        InMemoryAtomSet body = GraalUtils.createAtomSet(new DefaultAtom(Predicate.TOP, glueVarX));

        return Collections.singleton(RuleFactory.instance().create(body, head));
    }

    @Override
    public Iterable<? extends Object> visit(OWLIrreflexiveObjectPropertyAxiom arg) {
        InMemoryAtomSet body = arg.getProperty().accept(propertyVisiotrXX);

        return Collections.singleton(new DefaultNegativeConstraint(body));
    }

    @Override
    public Iterable<? extends Object> visit(OWLEquivalentObjectPropertiesAxiom arg) {
        return this.equivalentPropertiesAxiom(arg.getProperties());
    }

    @Override
    public Iterable<? extends Object> visit(OWLTransitiveObjectPropertyAxiom arg) {
        InMemoryAtomSet body = arg.getProperty().accept(propertyVisitorXY);
        body.addAll(arg.getProperty().accept(propertyVisitorYZ));
        InMemoryAtomSet head = arg.getProperty().accept(propertyVisitorXZ);

        return Collections.singleton(RuleFactory.instance().create(body, head));
    }

    @Override
    public Iterable<? extends Object> visit(OWLDisjointObjectPropertiesAxiom arg) {
        return this.disjointPropertiesAxiom(arg.getProperties());
    }

    @Override
    public Iterable<? extends Object> visit(OWLSymmetricObjectPropertyAxiom arg) {

        InMemoryAtomSet body = arg.getProperty().accept(propertyVisitorXY);
        InMemoryAtomSet head = arg.getProperty().accept(propertyVisitorYX);

        return Collections.singleton(RuleFactory.instance().create(body, head));
    }

    @Override
    public Iterable<? extends Object> visit(OWLFunctionalObjectPropertyAxiom arg) {
        return this.functionalPropertyAxiom(arg.getProperty());
    }

    @Override
    public Iterable<? extends Object> visit(OWLInverseFunctionalObjectPropertyAxiom arg) {
        InMemoryAtomSet body = arg.getProperty().accept(propertyVisitorXZ);
        body.addAll(arg.getProperty().accept(propertyVisitorYZ));

        InMemoryAtomSet head = GraalUtils.createAtomSet(new DefaultAtom(equalityPredicate, glueVarX, glueVarY));

        return Collections.<Rule>singleton(RuleFactory.instance().create(body, head));
    }

    @Override
    public Iterable<? extends Object> visit(OWLInverseObjectPropertiesAxiom arg) {
        Collection<Object> rules = new LinkedList<Object>();
        InMemoryAtomSet a1, a2;
        Iterator<OWLObjectPropertyExpression> it = arg.getProperties().iterator();
        a1 = it.next().accept(propertyVisitorXY);
        a2 = it.next().accept(propertyVisitorYX);

        rules.add(RuleFactory.instance().create(a1, a2));
        rules.add(RuleFactory.instance().create(a2, a1));

        return rules;
    }

    // /////////////////////////////////////////////////////////////////////////
    // DataPropertyAxiom
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLSubDataPropertyOfAxiom arg) {
        InMemoryAtomSet a1, a2;
        a1 = arg.getSubProperty().accept(propertyVisitorXY);
        a2 = arg.getSuperProperty().accept(propertyVisitorXY);

        return Collections.singleton(RuleFactory.instance().create(a1, a2));
    }

    @Override
    public Iterable<? extends Object> visit(OWLDataPropertyDomainAxiom arg) {
        OWLClassExpression subClass = new OWLDataSomeValuesFromImpl(arg.getProperty(), DF.getTopDatatype());
        OWLClassExpression superClass = arg.getDomain();
        return new OWLSubClassOfAxiomImpl(subClass, superClass, emptyAnno).accept(this);
    }

    @Override
    public Iterable<? extends Object> visit(OWLDataPropertyRangeAxiom arg) {
        InMemoryAtomSet body = arg.getProperty().accept(propertyVisitorYX);
        InMemoryAtomSet head = null;
        try {
            head = arg.getRange().accept(dataRangeVisitorX);
        } catch (UnsupportedConstructor e) {
            if (LOGGER.isWarnEnabled()) {
                LOGGER.warn(
                        "[ " + e.getConstructor() + "] is not supported here. This axioms was skipped : " + arg);
            }
            return Collections.emptyList();
        }
        return Collections.singleton(RuleFactory.instance().create(body, head));
    }

    @Override
    public Iterable<? extends Object> visit(OWLFunctionalDataPropertyAxiom arg) {
        return this.functionalPropertyAxiom(arg.getProperty());
    }

    @Override
    public Iterable<? extends Object> visit(OWLEquivalentDataPropertiesAxiom arg) {
        return this.equivalentPropertiesAxiom(arg.getProperties());
    }

    @Override
    public Iterable<? extends Object> visit(OWLDisjointDataPropertiesAxiom arg) {
        return this.disjointPropertiesAxiom(arg.getProperties());
    }

    // /////////////////////////////////////////////////////////////////////////
    // PropertyChain
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLSubPropertyChainOfAxiom arg) {
        freeVarGen.setIndex(0);
        InMemoryAtomSet body = GraalUtils.createAtomSet();
        Term varX, varY, firstVarInChain;
        firstVarInChain = varX = freeVarGen.getFreshVar();
        for (OWLPropertyExpression pe : arg.getPropertyChain()) {
            varY = freeVarGen.getFreshVar();
            body.addAll(pe.accept(new OWLPropertyExpressionVisitorImpl(varX, varY)));
            varX = varY;
        }

        InMemoryAtomSet head = arg.getSuperProperty()
                .accept(new OWLPropertyExpressionVisitorImpl(firstVarInChain, varX));

        return Collections.singleton(RuleFactory.instance().create(body, head));

    }

    // /////////////////////////////////////////////////////////////////////////
    // DatatypeDefinition
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLDatatypeDefinitionAxiom arg) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Visit OWLDatatypeDefinitionAxiom is not implemented: " + arg);
        }
        return Collections.emptyList();
    }

    // /////////////////////////////////////////////////////////////////////////
    // HasKey
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLHasKeyAxiom arg) {
        // =(Y, Z) :- C(Y), C(Z), p1(Y, X1), p1(Z, X1), ..., pn(Y, Xn), pn(Z,
        // Xn).
        Collection<Rule> rules = GraalUtils.<Rule>createCollection();

        freeVarGen.setIndex(2);
        InMemoryAtomSet head = GraalUtils
                .createAtomSet(GraalUtils.createAtom(equalityPredicate, glueVarX, glueVarY));

        OWLClassExpression classExpression = OWLAPIUtils
                .classExpressionDisjunctiveNormalForm(arg.getClassExpression());
        for (Pair<OWLClassExpression, OWLClassExpression> pair : MathUtils
                .selfCartesianProduct(OWLAPIUtils.getObjectUnionOperands(classExpression))) {
            InMemoryAtomSet body = pair.getLeft().accept(classVisitorX);
            body.addAll(pair.getRight().accept(classVisitorY));

            for (OWLObjectPropertyExpression pe : arg.getObjectPropertyExpressions()) {
                Term var = freeVarGen.getFreshVar();

                body.addAll(pe.accept(new OWLPropertyExpressionVisitorImpl(glueVarX, var)));
                body.addAll(pe.accept(new OWLPropertyExpressionVisitorImpl(glueVarY, var)));
            }

            for (OWLDataPropertyExpression pe : arg.getDataPropertyExpressions()) {
                Term var = freeVarGen.getFreshVar();

                body.add(GraalUtils.createAtom(GraalUtils.createPredicate(pe), glueVarX, var));
                body.add(GraalUtils.createAtom(GraalUtils.createPredicate(pe), glueVarY, var));
            }

            rules.add(RuleFactory.instance().create(body, head));
        }

        return rules;
    }

    // /////////////////////////////////////////////////////////////////////////
    // Assertion
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLClassAssertionAxiom arg) {
        Collection<Object> objects = GraalUtils.createCollection();
        OWLClassExpression sub = new OWLObjectOneOfImpl(Collections.singleton(arg.getIndividual()));
        OWLClassExpression sup = arg.getClassExpression();
        CollectionsUtils.addAll(objects, new OWLSubClassOfAxiomImpl(sub, sup, emptyAnno).accept(this));
        return objects;
    }

    @Override
    public Iterable<? extends Object> visit(OWLObjectPropertyAssertionAxiom arg) {

        freeVarGen.setIndex(0);
        Term a = GraalUtils.createTerm(arg.getSubject());
        Term b = GraalUtils.createTerm(arg.getObject());
        AtomSet atomset = arg.getProperty().accept(new OWLPropertyExpressionVisitorImpl(a, b));
        return Collections.singleton(atomset);
    }

    @Override
    public Iterable<? extends Object> visit(OWLNegativeObjectPropertyAssertionAxiom arg) {
        freeVarGen.setIndex(0);
        Term a = GraalUtils.createTerm(arg.getSubject());
        Term b = GraalUtils.createTerm(arg.getObject());
        InMemoryAtomSet atomset = arg.getProperty().accept(new OWLPropertyExpressionVisitorImpl(a, b));
        return Collections.singleton(new DefaultNegativeConstraint(atomset));
    }

    @Override
    public Iterable<? extends Object> visit(OWLDataPropertyAssertionAxiom arg) {
        freeVarGen.setIndex(0);
        Term a = GraalUtils.createTerm(arg.getSubject());
        Term b = GraalUtils.createLiteral(arg.getObject());
        InMemoryAtomSet atomset = arg.getProperty().accept(new OWLPropertyExpressionVisitorImpl(a, b));
        return Collections.singleton(atomset);
    }

    @Override
    public Iterable<? extends Object> visit(OWLNegativeDataPropertyAssertionAxiom arg) {
        freeVarGen.setIndex(0);
        Term a = GraalUtils.createTerm(arg.getSubject());
        Term b = GraalUtils.createLiteral(arg.getObject());
        InMemoryAtomSet atomset = arg.getProperty().accept(new OWLPropertyExpressionVisitorImpl(a, b));
        return Collections.singleton(new DefaultNegativeConstraint(atomset));
    }

    @Override
    public Iterable<? extends Object> visit(OWLSameIndividualAxiom arg) {
        Collection<Atom> c = GraalUtils.<Atom>createCollection();
        LinkedList<OWLIndividual> list = new LinkedList<OWLIndividual>(arg.getIndividualsAsList());

        Iterator<OWLIndividual> it1, it2;
        it1 = list.iterator();
        while (it1.hasNext()) {
            OWLIndividual individu1 = it1.next();
            it1.remove();

            Term t1 = GraalUtils.createTerm(individu1);

            it2 = list.iterator();
            while (it2.hasNext()) {
                OWLIndividual individu2 = it2.next();

                Term t2 = GraalUtils.createTerm(individu2);
                Atom a = new DefaultAtom(equalityPredicate, t1, t2);
                c.add(a);
            }
        }
        return c;
    }

    @Override
    public Iterable<? extends Object> visit(OWLDifferentIndividualsAxiom arg) {
        Collection<Object> c = GraalUtils.<Object>createCollection();
        LinkedList<OWLIndividual> list = new LinkedList<OWLIndividual>(arg.getIndividualsAsList());

        Iterator<OWLIndividual> it1, it2;
        it1 = list.iterator();
        while (it1.hasNext()) {
            OWLIndividual individu1 = it1.next();
            it1.remove();

            Term t1 = GraalUtils.createTerm(individu1);

            it2 = list.iterator();
            while (it2.hasNext()) {
                OWLIndividual individu2 = it2.next();

                Term t2 = GraalUtils.createTerm(individu2);
                Atom a = new DefaultAtom(equalityPredicate, t1, t2);
                c.add(new DefaultNegativeConstraint(new LinkedListAtomSet(a)));
            }
        }
        return c;
    }

    // /////////////////////////////////////////////////////////////////////////
    // SWRLRules
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(SWRLRule arg) {
        if (LOGGER.isWarnEnabled()) {
            LOGGER.warn("Visit SWRLRule is not implemented: " + arg);
        }
        return Collections.emptyList();
    }

    // /////////////////////////////////////////////////////////////////////////
    // AnnotationAxiom
    // /////////////////////////////////////////////////////////////////////////

    @Override
    public Iterable<? extends Object> visit(OWLAnnotationAssertionAxiom arg) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Visit OWLAnnotationAssertionAxiom is not implemented: " + arg);
        }
        return Collections.emptyList();
    }

    @Override
    public Iterable<? extends Object> visit(OWLSubAnnotationPropertyOfAxiom arg) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Visit OWLSubAnnotationPropertyOfAxiom is not implemented: " + arg);
        }
        return Collections.emptyList();
    }

    @Override
    public Iterable<? extends Object> visit(OWLAnnotationPropertyDomainAxiom arg) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Visit OWLAnnotationPropertyDomainAxiom is not implemented: " + arg);
        }
        return Collections.emptyList();
    }

    @Override
    public Iterable<? extends Object> visit(OWLAnnotationPropertyRangeAxiom arg) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Visit OWLAnnotationPropertyRangeAxiom is not implemented: " + arg);
        }
        return Collections.emptyList();
    }

    // /////////////////////////////////////////////////////////////////////////
    // PRIVATE METHODS
    // /////////////////////////////////////////////////////////////////////////

    private Iterable<? extends Object> functionalPropertyAxiom(OWLPropertyExpression property) {
        InMemoryAtomSet body = property.accept(propertyVisitorXY);
        body.addAll(property.accept(propertyVisitorXZ));

        InMemoryAtomSet head = GraalUtils.createAtomSet(new DefaultAtom(equalityPredicate, glueVarY, glueVarZ));

        return Collections.<Rule>singleton(RuleFactory.instance().create(body, head));
    }

    private Iterable<? extends Object> equivalentPropertiesAxiom(
            Iterable<? extends OWLPropertyExpression> properties) {
        Collection<Rule> rules = GraalUtils.<Rule>createCollection();
        InMemoryAtomSet a1, a2;

        Iterator<? extends OWLPropertyExpression> it1, it2;
        it1 = properties.iterator();
        while (it1.hasNext()) {
            OWLPropertyExpression propExpr = (OWLPropertyExpression) it1.next();
            a1 = propExpr.accept(propertyVisitorXY);
            it1.remove();

            it2 = properties.iterator();
            while (it2.hasNext()) {
                OWLPropertyExpression next = (OWLPropertyExpression) it2.next();
                a2 = next.accept(propertyVisitorXY);

                rules.add(RuleFactory.instance().create(a1, a2));
                rules.add(RuleFactory.instance().create(a2, a1));
            }
        }
        return rules;
    }

    private Iterable<? extends Object> disjointPropertiesAxiom(
            Iterable<? extends OWLPropertyExpression> properties) {

        Collection<Rule> rules = GraalUtils.<Rule>createCollection();
        InMemoryAtomSet a, a1, a2;

        Iterator<? extends OWLPropertyExpression> it1, it2;
        it1 = properties.iterator();
        while (it1.hasNext()) {
            OWLPropertyExpression propExpr = (OWLPropertyExpression) it1.next();
            a1 = propExpr.accept(propertyVisitorXY);
            it1.remove();

            it2 = properties.iterator();
            while (it2.hasNext()) {
                OWLPropertyExpression next = (OWLPropertyExpression) it2.next();
                a2 = next.accept(propertyVisitorXY);
                a = GraalUtils.createAtomSet();
                a.addAll(a1);
                a.addAll(a2);
                rules.add(new DefaultNegativeConstraint(a));
            }
        }
        return rules;

    }

    /**
     * @param expression
     * @return
     */
    private boolean isEquivClass(OWLClassExpression expression) {
        return expression instanceof OWLClass || expression instanceof OWLObjectIntersectionOf
                || expression instanceof OWLDataIntersectionOf || expression instanceof OWLObjectSomeValuesFrom
                || expression instanceof OWLDataSomeValuesFrom || expression instanceof OWLObjectHasValue
                || expression instanceof OWLDataHasValue || expression instanceof OWLObjectHasSelf
                || (expression instanceof OWLObjectMinCardinality
                        && ((OWLObjectMinCardinality) expression).getCardinality() <= 1)
                || (expression instanceof OWLDataMinCardinality
                        && ((OWLDataMinCardinality) expression).getCardinality() <= 1)
                || (expression instanceof OWLObjectOneOf
                        && ((OWLObjectOneOf) expression).getIndividuals().size() == 1)
                || (expression instanceof OWLDataOneOf && ((OWLDataOneOf) expression).getValues().size() == 1);
    }

    private boolean isSuperClass(OWLClassExpression expression) {
        return isEquivClass(expression)
                || (expression instanceof OWLObjectMaxCardinality
                        && ((OWLObjectMaxCardinality) expression).getCardinality() <= 1)
                || (expression instanceof OWLDataMaxCardinality
                        && ((OWLDataMaxCardinality) expression).getCardinality() <= 1)
                || (expression instanceof OWLDataAllValuesFrom);
    }

    private Iterable<? extends Rule> mainProcess(OWLSubClassOfAxiom arg) {
        Collection<Rule> objects = new LinkedList<Rule>();
        InMemoryAtomSet body = null;
        try {
            body = arg.getSubClass().accept(this.classVisitorX);
        } catch (UnsupportedConstructor e) {
            if (LOGGER.isWarnEnabled()) {
                LOGGER.warn("[ " + arg.getSubClass() + "] is not supported as subClass. This axioms was skipped : "
                        + arg);
            }
            return Collections.emptyList();
        }

        // RULES
        InMemoryAtomSet head = null;
        try {
            if (arg.getSuperClass() instanceof OWLObjectMaxCardinality) {
                OWLObjectMaxCardinality maxCard = (OWLObjectMaxCardinality) arg.getSuperClass();

                body.addAll(maxCard.getProperty().accept(this.propertyVisitorXY));
                body.addAll(maxCard.getProperty().accept(this.propertyVisitorXZ));

                AtomSet bodyTemplate = body;
                head = GraalUtils.createAtomSet(GraalUtils.createAtom(Predicate.EQUALITY, glueVarY, glueVarZ));
                OWLClassExpression expr = OWLAPIUtils.classExpressionDisjunctiveNormalForm(maxCard.getFiller());
                for (Pair<OWLClassExpression, OWLClassExpression> pair : MathUtils
                        .selfCartesianProduct(OWLAPIUtils.getObjectUnionOperands(expr))) {
                    body = new LinkedListAtomSet(bodyTemplate);
                    body.addAll(pair.getLeft().accept(classVisitorY));
                    body.addAll(pair.getRight().accept(classVisitorZ));
                    objects.add(RuleFactory.instance().create(body, head));
                }

            } else if (arg.getSuperClass() instanceof OWLDataMaxCardinality) {
                OWLDataMaxCardinality maxCard = (OWLDataMaxCardinality) arg.getSuperClass();

                Predicate p = GraalUtils.createPredicate(maxCard.getProperty());
                body.add(GraalUtils.createAtom(p, glueVarX, glueVarY));
                body.add(GraalUtils.createAtom(p, glueVarX, glueVarZ));
                AtomSet bodyTemplate = body;
                head = GraalUtils.createAtomSet(GraalUtils.createAtom(Predicate.EQUALITY, glueVarY, glueVarZ));
                OWLDataRange expr = OWLAPIUtils.dataRangeDisjunctiveNormalForm(maxCard.getFiller());
                for (Pair<OWLDataRange, OWLDataRange> pair : MathUtils
                        .selfCartesianProduct(OWLAPIUtils.getDataUnionOperands(expr))) {
                    body = new LinkedListAtomSet(bodyTemplate);
                    body.addAll(pair.getLeft().accept(dataRangeVisitorY));
                    body.addAll(pair.getRight().accept(dataRangeVisitorZ));
                    objects.add(RuleFactory.instance().create(body, head));
                }
            } else if (arg.getSuperClass() instanceof OWLDataAllValuesFrom) {
                OWLDataAllValuesFrom allvalues = (OWLDataAllValuesFrom) arg.getSuperClass();

                Predicate p = GraalUtils.createPredicate(allvalues.getProperty());
                body.add(GraalUtils.createAtom(p, glueVarX, glueVarY));
                head = allvalues.getFiller().accept(dataRangeVisitorY);
                objects.add(RuleFactory.instance().create(body, head));
            } else {
                head = arg.getSuperClass().accept(this.classVisitorX);
                objects.add(RuleFactory.instance().create(body, head));
            }
        } catch (UnsupportedConstructor e) {
            if (LOGGER.isWarnEnabled()) {
                LOGGER.warn(
                        "[ " + e.getConstructor() + "] is not supported here. This axioms was skipped : " + arg);
            }
            objects = Collections.emptyList();
        }

        return objects;
    }

    // /////////////////////////////////////////////////////////////////////////
    // PRIVATE CLASSES
    // /////////////////////////////////////////////////////////////////////////

    private static class SpecificFreeVarGen implements VariableGenerator {

        private int index = 0;

        @Override
        public Variable getFreshVar() {
            return DefaultTermFactory.instance().createVariable("X" + index++);
        }

        public void setIndex(int index) {
            this.index = index;
        }
    };
}