/* ********************************************************************** ** ** Copyright notice ** ** ** ** (c) 2005-2009 RSSOwl Development Team ** ** http://www.rssowl.org/ ** ** ** ** All rights reserved ** ** ** ** This program and the accompanying materials are made available under ** ** the terms of the Eclipse Public License v1.0 which accompanies this ** ** distribution, and is available at: ** ** http://www.rssowl.org/legal/epl-v10.html ** ** ** ** A copy is found in the file epl-v10.html and important notices to the ** ** license from the team is found in the textfile LICENSE.txt distributed ** ** in this package. ** ** ** ** This copyright notice MUST APPEAR in all copies of the file! ** ** ** ** Contributors: ** ** RSSOwl Development Team - initial API and implementation ** ** ** ** ********************************************************************** */ package org.rssowl.core.util; import org.eclipse.core.runtime.Assert; /** * An abstract helper-class to perform navigation in a Tree, specified by a * <code>ITreeNode</code> as starting point. Implementors have to override the * <code>select(ITreeNode)</code>-Method allowing to filter certain Nodes * from the navigation. * * @author bpasero */ public abstract class TreeTraversal { private ITreeNode fNode; /** * @param startingNode The entry-node of this traversal. */ protected TreeTraversal(ITreeNode startingNode) { Assert.isNotNull(startingNode); fNode = startingNode; } /** * This method is called during navigation and allows to define, wether a * certain Node should be returned as a result or not. * * @param node The current Node in the navigation. * @return Implementors should return <code>TRUE</code> to respect this Node * as a result and <code>FALSE</code> otherwise. */ public abstract boolean select(ITreeNode node); /** * Returns the next Node starting from the initially given Node using a * depth-first-Search or <code>NULL</code> if no next Node. * * @return the next Node starting from the initially given Node using a * depth-first-Search or <code>NULL</code> if no next Node. */ public ITreeNode nextNode() { /* Perform Navigation until finished */ do { /* Branch - Directly take first Child */ if (fNode.hasChildren()) { fNode = fNode.getFirstChild(); } /* Leaf - Find the next sibling */ else { /* Walk up until next sibling found */ while (fNode != null && fNode.getNextSibling() == null) fNode = fNode.getParent(); /* Go to next Sibling */ if (fNode != null) fNode = fNode.getNextSibling(); } /* Navigation complete */ if (fNode != null && select(fNode)) return fNode; } /* Traverse the Tree */ while (fNode != null); /* No next Node */ return null; } /** * Returns the previous Node starting from the initially given Node using a * depth-first-Search or <code>NULL</code> if no previous Node. * * @return the previous Node starting from the initially given Node using a * depth-first-Search or <code>NULL</code> if no previous Node. */ public ITreeNode previousNode() { /* Perform Navigation until finished */ do { /* Walk up until previous sibling found */ while (fNode != null && fNode.getPreviousSibling() == null) fNode = fNode.getParent(); /* Go to previous Sibling */ if (fNode != null) { fNode = fNode.getPreviousSibling(); /* Take last Child of previous Sibling */ if (fNode != null && fNode.hasChildren()) { while (fNode.getLastChild().hasChildren()) fNode = fNode.getLastChild(); fNode = fNode.getLastChild(); } /* Navigation complete */ if (fNode != null && select(fNode)) return fNode; } } /* Traverse the Tree */ while (fNode != null); /* No previous Node */ return null; } }