de.uniba.wiai.kinf.pw.projects.lillytab.reasoner.tbox.TBox.java Source code

Java tutorial

Introduction

Here is the source code for de.uniba.wiai.kinf.pw.projects.lillytab.reasoner.tbox.TBox.java

Source

/**
 * (c) 2009-2014 Otto-Friedrich-University Bamberg
 *
 * $Id$
 *
 * Use, modification and restribution of this file are covered by the
 * terms of the Artistic License 2.0.
 *
 * You should have received a copy of the license terms in a file named
 * "LICENSE" together with this software package.
 *
 * Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
 * HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
 * A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE
 * EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO
 * COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT
 * OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 **/
package de.uniba.wiai.kinf.pw.projects.lillytab.reasoner.tbox;

import de.dhke.projects.cutil.collections.aspect.CollectionEvent;
import de.dhke.projects.cutil.collections.aspect.CollectionItemEvent;
import de.dhke.projects.cutil.collections.aspect.CollectionItemReplacedEvent;
import de.uniba.wiai.kinf.pw.projects.lillytab.reasoner.abox.TermSet;
import de.uniba.wiai.kinf.pw.projects.lillytab.tbox.IAssertedRBox;
import de.uniba.wiai.kinf.pw.projects.lillytab.tbox.IRBox;
import de.uniba.wiai.kinf.pw.projects.lillytab.tbox.ITBox;
import de.uniba.wiai.kinf.pw.projects.lillytab.terms.*;
import de.uniba.wiai.kinf.pw.projects.lillytab.terms.util.TermUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.collections15.MultiMap;
import org.apache.commons.collections15.multimap.MultiHashMap;

/**
 *  Represents an DL TBox. A TBox is a set of global terms that define restrictions on the ABox models, for example
 * role hierachies, domain and range restrictions for properties as well as more complex axioms. <p /> The current
 * TBox implementation only supports concept restriction axioms, and most importantly concept inclusions and general
 * concept inclusions (GCIs).
 * <p /> Concept restrictions are a set of axioms that are required to hold globally, i.e. that need to hold for every
 * instance in a tableaux. <p />
 * The global axioms may be split into an unfoldable and a non-unfoldable set. Descriptions of the form
 * {@literal (CN subClassOf C)}, whereas {@literal CN} is a primitive concept name and {@literal C} is an arbitrary
 * concept may be unfolded <emph>lazily</emph>, that is {@literal C} must only be added to a node's term set if
 * {@literal CN} is already present in the node's concept set. Descriptions in other formats need to be added
 * regardlessly. Since unfoldable descriptions are quite common, lazy unfolding significantly improves performance. 
 *
 * @param <I> The type for individuals/nominals
 * @param <L> The type for literals
 * @param <K> The type for DL classes
 * @param <R> The type for properties (roles)
 *
 * @author Peter Wullinger <peter.wullinger@uni-bamberg.de>
 */
public class TBox<I extends Comparable<? super I>, L extends Comparable<? super L>, K extends Comparable<? super K>, R extends Comparable<? super R>>
        extends TermSet<I, L, K, R> implements ITBox<I, L, K, R> {
    private final IDLTermFactory<I, L, K, R> _termFactory;
    /**
     * The set of non-unfoldable global descriptions
     *
     */
    private final Set<IDLClassExpression<I, L, K, R>> _globalDescriptionSet = new HashSet<>();
    /**
     * A map of unfoldable descriptions. The key is usually a named class reference and the value is the set of
     * unfoldings associated with that class. The class reference itself is not included in the mapped set.
     */
    private final MultiMap<IDLClassExpression<I, L, K, R>, IDLClassExpression<I, L, K, R>> _unfolding = new MultiHashMap<>();
    private boolean _needRecalculate = true;
    /**
     * The generation number of the current TBox. Incremented every time, a recalculation has been performed.
     *
     */
    private int _generation = 0;
    // private final Set<
    /**
     * The RBox associated with this TBox.
     */
    private final IRBox<I, L, K, R> _rbox;

    public TBox(final IDLTermFactory<I, L, K, R> termFactory) {
        super(TermTypes.CLASS_ONLY);
        final AssertedRBox<I, L, K, R> assertedRBox = new AssertedRBox<>(this);
        _rbox = assertedRBox.getRBox();
        _termFactory = termFactory;
    }

    /**
     * @return The set of non-unfoldable descriptions.
     */
    @Override
    public Set<IDLClassExpression<I, L, K, R>> getGlobalDescriptions() {
        recalculateIfNeeded();
        return Collections.unmodifiableSet(_globalDescriptionSet);
    }

    /**
     * @param unfoldee The description to unfold.
     * @return The unfolding for {@literal unfoldee}.
     */
    @Override
    public Collection<IDLClassExpression<I, L, K, R>> getUnfolding(final IDLClassExpression<I, L, K, R> unfoldee) {
        recalculateIfNeeded();
        if (_unfolding.containsKey(unfoldee)) {
            return _unfolding.get(unfoldee);
        } else {
            return Collections.emptySet();
        }
    }

    public int getGeneration() {
        recalculateIfNeeded();
        return _generation;
    }

    @Override
    public IRBox<I, L, K, R> getRBox() {
        return _rbox;
    }

    @Override
    public IAssertedRBox<I, L, K, R> getAssertedRBox() {
        return _rbox.getAssertedRBox();
    }

    @Override
    public String toString(String prefix) {
        // XXX - rewrite
        return toString();
    }

    /**
     *
     * @return {@literal true} if the current TBox needs to be recalculated before the next access.
     */
    public boolean isNeedRecalculate() {
        return _needRecalculate;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void notifyAfterElementAdded(
            CollectionItemEvent<IDLTerm<I, L, K, R>, Collection<IDLTerm<I, L, K, R>>> e) {
        setNeedRecalculate();
        super.notifyAfterElementAdded(e);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void notifyAfterElementRemoved(
            CollectionItemEvent<IDLTerm<I, L, K, R>, Collection<IDLTerm<I, L, K, R>>> e) {
        setNeedRecalculate();
        super.notifyAfterElementRemoved(e);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void notifyAfterElementReplaced(
            CollectionItemReplacedEvent<IDLTerm<I, L, K, R>, Collection<IDLTerm<I, L, K, R>>> e) {
        setNeedRecalculate();
        super.notifyAfterElementReplaced(e);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void notifyAfterCollectionCleared(
            CollectionEvent<IDLTerm<I, L, K, R>, Collection<IDLTerm<I, L, K, R>>> e) {
        setNeedRecalculate();
        super.notifyAfterCollectionCleared(e);
    }

    @Override
    public TBox<I, L, K, R> clone() {
        /* XXX - TBox is not cloned, yet */
        return this;
    }

    @Override
    public ITBox<I, L, K, R> getImmutable() {
        return new ImmutableTBox<>(this);
    }

    /**
     *  Recalculate the internal state from the term set. <p /> Should only be called, when needed, i.e. when the
     * term set was changed since the last access. 
     */
    private void recalculateIfNeeded() {
        if (_needRecalculate) {
            _unfolding.clear();
            _globalDescriptionSet.clear();

            /* first, we unfold any top level intersections recursively */
            Set<IDLTerm<I, L, K, R>> termSet = TermUtil.unfoldIntersections(this, _termFactory);

            Iterator<IDLTerm<I, L, K, R>> iter = termSet.iterator();

            while (iter.hasNext()) {
                IDLTerm<I, L, K, R> term = iter.next();
                if (term instanceof IDLClassExpression) {
                    /* pick up descriptions only */
                    IDLClassExpression<I, L, K, R> desc = (IDLClassExpression<I, L, K, R>) term;
                    /* simplify description */
                    desc = TermUtil.simplify(desc, _termFactory);
                    if (desc instanceof IDLImplies) {
                        handleImplication(desc);
                    } else if (desc instanceof IDLObjectIntersection) {
                        /**
                         * if the description is an intersection, look at it's parts and treat them individually.
                         *
                         */
                        IDLObjectIntersection<I, L, K, R> intersection = (IDLObjectIntersection<I, L, K, R>) desc;
                        for (IDLClassExpression<I, L, K, R> subTerm : intersection) {
                            if (subTerm instanceof IDLImplies) {
                                handleImplication(subTerm);
                            } else {
                                _globalDescriptionSet.add(TermUtil.toNNF(subTerm, _termFactory));
                            }
                        }
                    } else {
                        _globalDescriptionSet.add(TermUtil.toNNF(desc, _termFactory));
                    }
                }
            }
            /* don't forget to add _Thing_ */
            _globalDescriptionSet.add(_termFactory.getDLThing());
            /* increment generation counter */
            ++_generation;
            _needRecalculate = false;
        }
    }

    private void handleImplication(IDLClassExpression<I, L, K, R> desc) {
        /**
         * if description is an implication AND the left hand side is a simple class or nominal reference, update the
         * map of unfoldings, otherwise add the description to the global term set.
         *
         */
        @SuppressWarnings("unchecked")
        IDLImplies<I, L, K, R> implies = (IDLImplies<I, L, K, R>) desc;
        IDLClassExpression<I, L, K, R> subDesc = TermUtil.toNNF(implies.getSubDescription(), _termFactory);

        if ((subDesc instanceof IDLClassReference) || (subDesc instanceof IDLIndividualReference)) {
            if (!subDesc.equals(implies.getSuperDescription())) {
                _unfolding.put(implies.getSubDescription(),
                        TermUtil.toNNF(implies.getSuperDescription(), _termFactory));
            }
        } else {
            _globalDescriptionSet.add(TermUtil.toNNF(desc, _termFactory));
        }
    }

    /**
     * signal that the current termset needs to be recalculated.
     */
    private void setNeedRecalculate() {
        _needRecalculate = true;
    }
}