package uk.ac.manchester.cs.jfact.helpers; /* This file is part of the JFact DL reasoner Copyright 2011-2013 by Ignazio Palmisano, Dmitry Tsarkov, University of Manchester This library 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 2.1 of the License, or (at your option) any later version. This library 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 this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/ import static uk.ac.manchester.cs.jfact.kernel.Token.*; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.semanticweb.owlapi.reasoner.ReasonerInternalException; import uk.ac.manchester.cs.jfact.kernel.Lexeme; import uk.ac.manchester.cs.jfact.kernel.Token; import conformance.Original; import conformance.PortedFrom; /** * DLTree class * * @author ignazio */ @PortedFrom(file = "dltree.h", name = "TsTTree") public abstract class DLTree implements Serializable { private static final long serialVersionUID = 11000L; private static final CloningVisitor cloner = new CloningVisitor(); /** element in the tree node */ protected Lexeme elem; /** children collection */ protected List<DLTree> children; protected DLTree ancestor; /** * @param l * element */ protected DLTree(Lexeme l) { elem = l; } /** @return the element token */ public Token token() { return elem.getToken(); } /** @return true if the token is top */ public boolean isTOP() { return elem.getToken() == TOP; } /** @return true if the token is not */ public boolean isNOT() { return elem.getToken() == NOT; } /** @return true if the token is bottom */ public boolean isBOTTOM() { return elem.getToken() == BOTTOM; } /** @return true if the token is and */ public boolean isAND() { return elem.getToken() == AND; } /** @return element */ public Lexeme elem() { return elem; } /** @return the chind node for nodes with a single child */ public abstract DLTree getChild(); /** @return the first child for a node with two children */ public abstract DLTree getLeft(); /** @return the second child for a node with two children */ public abstract DLTree getRight(); /** @return the ancestor */ public DLTree getAncestor() { return ancestor; } /** * @param r * ancestor */ public void setAncestor(DLTree r) { ancestor = r; } /** * @param d * child to add */ public void addChild(DLTree d) { if (d != null) { children.add(d); d.ancestor = this; } } /** * @param d * child to add in first position */ public void addFirstChild(DLTree d) { if (d != null) { children.add(0, d); d.ancestor = this; } } /** * @param d * children to add in first position */ public void addFirstChildren(Collection<DLTree> d) { if (d != null) { children.addAll(0, d); for (DLTree t : d) { t.ancestor = this; } } } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (obj instanceof DLTree) { DLTree t2 = (DLTree) obj; return equalTrees(this, t2); } return false; } @Override public String toString() { if (getChildren().size() > 0) { StringBuilder b = new StringBuilder(); b.append('('); b.append(elem); for (DLTree d : getChildren()) { b.append(' '); b.append(d); } b.append(')'); return b.toString(); } else { return elem.toString(); } } @Override public int hashCode() { return elem.hashCode() + (children == null ? 0 : children.hashCode()); } /** * @param v * v */ public abstract void accept(DLTreeVisitor v); /** * @param v * v * @param <O> * visitor type * @return visitor value */ public abstract <O> O accept(DLTreeVisitorEx<O> v); /** * @param toReplace * toReplace * @param replacement * replacement */ public abstract void replace(DLTree toReplace, DLTree replacement); /** @return list of children */ public List<DLTree> getChildren() { return children; } /** * @param t1 * t1 * @param t2 * t2 * @return true if arguments are equal */ public static boolean equalTrees(DLTree t1, DLTree t2) { if (t1 == null && t2 == null) { return true; } if (t1 == null || t2 == null) { return false; } if (t1.elem.equals(t2.elem)) { if (t1 instanceof LEAFDLTree) { return true; } if (t1 instanceof ONEDLTree) { return t1.getChild().equals(t2.getChild()); } Collection<DLTree> c1 = t1.getChildren(); Collection<DLTree> c2 = t2.getChildren(); return c1.size() == c2.size() && c1.containsAll(c2) && c2.containsAll(c1); } return false; } /** @return copy of this tree */ public DLTree copy() { return this.accept(cloner); } /** * check if DL tree is a concept-like name * * @return true if conceptlike name */ public boolean isCN() { return isConst() || isName(); } // check if DL tree is a concept constant /** @return true if constant */ public boolean isConst() { return isTOP() || isBOTTOM(); } // check if DL tree is a concept/individual name /** @return true if token is a cname or iname */ public boolean isName() { return token() == CNAME || token() == INAME; } } @Original interface DLTreeVisitor { void visit(LEAFDLTree t); void visit(ONEDLTree t); void visit(TWODLTree t); void visit(NDLTree t); } @Original interface DLTreeVisitorEx<O> { O visit(LEAFDLTree t); O visit(ONEDLTree t); O visit(TWODLTree t); O visit(NDLTree t); } @Original class CloningVisitor implements DLTreeVisitorEx<DLTree>, Serializable { private static final long serialVersionUID = 11000L; @Override public DLTree visit(LEAFDLTree t) { return new LEAFDLTree(new Lexeme(t.elem)); } @Override public DLTree visit(ONEDLTree t) { return new ONEDLTree(new Lexeme(t.elem), t.getChild().accept(this)); } @Override public DLTree visit(TWODLTree t) { return new TWODLTree(new Lexeme(t.elem), t.getLeft().accept(this), t .getRight().accept(this)); } @Override public DLTree visit(NDLTree t) { List<DLTree> l = new ArrayList<DLTree>(); for (DLTree tree : t.children) { l.add(tree.accept(this)); } return new NDLTree(new Lexeme(t.elem), l); } } @Original class ReverseCloningVisitor implements DLTreeVisitorEx<DLTree>, Serializable { private static final long serialVersionUID = 11000L; @Override public DLTree visit(LEAFDLTree t) { return DLTreeFactory.inverseComposition(t); } @Override public DLTree visit(ONEDLTree t) { return new ONEDLTree(new Lexeme(t.elem), t.getChild().accept(this)); } @Override public DLTree visit(TWODLTree t) { return new TWODLTree(new Lexeme(t.elem), t.getRight().accept(this), t .getLeft().accept(this)); } @Override public DLTree visit(NDLTree t) { List<DLTree> l = new ArrayList<DLTree>(t.children); List<DLTree> actual = new ArrayList<DLTree>(); Collections.reverse(l); for (DLTree tree : l) { actual.add(tree.accept(this)); } return new NDLTree(new Lexeme(t.elem), actual); } } /** things that have no children */ @Original class LEAFDLTree extends DLTree { private static final long serialVersionUID = 11000L; LEAFDLTree(Lexeme l) { super(l); } @Override public DLTree getChild() { throw new UnsupportedOperationException(); } @Override public DLTree getLeft() { throw new UnsupportedOperationException(); } @Override public DLTree getRight() { throw new UnsupportedOperationException(); } @Override public List<DLTree> getChildren() { return Collections.emptyList(); } @Override public void accept(DLTreeVisitor v) { v.visit(this); } @Override public <O> O accept(DLTreeVisitorEx<O> v) { return v.visit(this); } @Override public void replace(DLTree toReplace, DLTree replacement) { throw new UnsupportedOperationException(); } } /** covers trees with only one child, i.e., inverse, not */ @Original class ONEDLTree extends DLTree { private static final long serialVersionUID = 11000L; private DLTree child; ONEDLTree(Lexeme l, DLTree t) { super(l); child = t; if (t != null) { t.ancestor = this; } } @Override public DLTree getLeft() { throw new UnsupportedOperationException(); } @Override public DLTree getChild() { return child; } @Override public DLTree getRight() { throw new UnsupportedOperationException(); } @Override public List<DLTree> getChildren() { return Collections.singletonList(child); } @Override public void accept(DLTreeVisitor v) { v.visit(this); } @Override public <O> O accept(DLTreeVisitorEx<O> v) { return v.visit(this); } @Override public void replace(DLTree toReplace, DLTree replacement) { if (child.equals(toReplace)) { child = replacement; if (replacement != null) { replacement.ancestor = this; } } } } /** covers trees with two and only two children */ @Original class TWODLTree extends DLTree { private static final long serialVersionUID = 11000L; TWODLTree(Lexeme l, DLTree t1, DLTree t2) { super(l); children = new ArrayList<DLTree>(2); addChild(t1); addChild(t2); } @Override public DLTree getChild() { throw new UnsupportedOperationException(); } @Override public DLTree getLeft() { return children.get(0); } @Override public DLTree getRight() { return children.get(1); } @Override public void accept(DLTreeVisitor v) { v.visit(this); } @Override public <O> O accept(DLTreeVisitorEx<O> v) { return v.visit(this); } @Override public void replace(DLTree toReplace, DLTree replacement) { int p = children.indexOf(toReplace); if (p > -1) { children.set(p, replacement); if (replacement != null) { replacement.ancestor = this; } } } } @Original class NDLTree extends DLTree { private static final long serialVersionUID = 11000L; public NDLTree(Lexeme l, Collection<DLTree> trees) { super(l); children = new ArrayList<DLTree>(); if (trees.size() < 2) { throw new ReasonerInternalException( "not enough elements in the n-ary element"); } for (DLTree d : trees) { addChild(d); } } public NDLTree(Lexeme l, DLTree C, DLTree D) { super(l); children = new ArrayList<DLTree>(); if (C == null || D == null) { throw new ReasonerInternalException( "not enough elements in the n-ary element"); } addChild(C); addChild(D); } @Override public DLTree getChild() { throw new UnsupportedOperationException(); } @Override public DLTree getLeft() { throw new UnsupportedOperationException(); } @Override public DLTree getRight() { throw new UnsupportedOperationException(); } @Override public void accept(DLTreeVisitor v) { v.visit(this); } @Override public <O> O accept(DLTreeVisitorEx<O> v) { return v.visit(this); } @Override public void replace(DLTree toReplace, DLTree replacement) { if (children.contains(toReplace)) { children.remove(toReplace); if (replacement != null) { children.add(replacement); replacement.ancestor = this; } } } }