/******************************************************************************* * Copyright 2012 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.core.tree; import java.util.List; import au.gov.ga.earthsci.common.util.ITreePropertyChangeBean; /** * Represents a tree node, with children and a parent (unless root). * * @author Michael de Hoog (michael.dehoog@ga.gov.au) * * @param <E> * Type of this tree node. All nodes in the tree hierarchy must be * instances of this type, as well as instances of ITreeNode. */ public interface ITreeNode<E extends ITreeNode<E>> extends ITreePropertyChangeBean { /** * Genericised value of <code>this</code>. * <p/> * To get this value, either the generic class must be passed to an * implementor's constructor so that <code>this</code> can be cast using the * {@link Class#cast(Object)} method, or an unchecked cast must be used. * This is unfortunate but unavoidable due to the CRTP nature of ITreeNode. * <p/> * Example constructor implementation: * * <pre> * public class TreeNode<E extends ITreeNode<E>> implements ITreeNode<E> * { * protected final E me; * ... * protected TreeNode(Class<E> genericClass) * { * if (!genericClass.isInstance(this)) * { * throw new IllegalStateException(); * } * me = genericClass.cast(this); * } * } * </pre> * * @return <code>this</code> */ E me(); /** * @return Is this node the root node (has no parent)? */ boolean isRoot(); /** * @return Parent of this node (returns null if this node is the root). */ @Override E getParent(); /** * @return True if this element has the given parent somewhere in it's path * to root. */ boolean hasParentInPathToRoot(ITreeNode<?> parent); /** * Set the parent of this node. * <p/> * DO NOT CALL THIS METHOD. Should only be called by the {@link ITreeNode} * implementation, when added/removing children. * * @param parent * @param indexInParent */ void setParent(E parent, int indexInParent); /** * @return Does this node have children? */ boolean hasChildren(); /** * @return This node's children. */ List<E> getChildren(); /** * @return Number of children of this node. */ int getChildCount(); /** * @param index * @return This node's child at <code>index</code>. */ E getChild(int index); /** * @return Index of this node in it's parent (-1 if this node is the root). */ int index(); /** * @return Depth of this node in the tree hierarchy (0 if this node is the * root). */ int depth(); /** * Add a child to this node. If the child is already a child of this node, * it is moved to the end of the child array. * * @param child * Child to add. */ void addChild(E child); /** * Add a child to this node at the specified index. If the specified child * is already a child of this node, it is moved to the given index. * * @param index * Index at which to add the child. * @param child * Child to add. */ void addChild(int index, E child); /** * Remove the specified child from this node. * * @param child * Child to remove. * @return True if the child was found and removed, false otherwise. */ boolean removeChild(E child); /** * Remove the child at the specified index. * * @param index * Index of the child to remove. * @return Child removed. */ E removeChild(int index); /** * Remove all children from this node */ void clearChildren(); /** * Remove this node from its parent (no-op if this node is the root). */ void removeFromParent(); /** * Move the child node from the given old index to the new index and trigger * a single children changed property event. * * @param child * The child to move * @param newIndex * The new index of the child */ void moveChild(E child, int newIndex); /** * Replace the child node with a new child node at the same index. * * @param child * Child node to replace * @param newChild * New child node to insert * @return True if the child was found and replaced, false otherwise. */ boolean replaceChild(E child, E newChild); /** * @return List containing all nodes from the root (at index 0) to this * node. */ List<E> pathToRoot(); /** * @return Array containing the index of each node from the root to this * node (not including the root). */ int[] indicesToRoot(); /** * @return The root node of this node. */ E getRoot(); }