/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.utility.iterators; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import org.eclipse.persistence.tools.workbench.utility.ClassTools; /** * A <code>TreeIterator</code> simplifies the traversal of a * tree of objects, where the objects' protocol(s) provides * a method for getting the immediate children of the given * node but does not provide a method for getting all the * descendants (children, grandchildren, etc.) of the given node. * <p> * To use, supply:<ul> * <li> either the root element of the tree or, if the tree has * multiple roots, an <code>Iterator</code> over the set of roots * <li> a <code>Midwife</code> that delivers the children * of each child * (alternatively, subclass <code>TreeIterator</code> * and override the <code>children(Object)</code> method) * </ul> * <p> */ public class TreeIterator implements Iterator { private Iterator currentIterator; private Collection iterators; private Midwife midwife; /** * Construct an iterator with the specified collection of roots * and a midwife that simply returns an empty iterator * for each of the roots. * Use this constructor if you want to override the * <code>children(Object)</code> method instead of building * a <code>Midwife</code>. */ public TreeIterator(Iterator roots) { this(roots, Midwife.NULL_INSTANCE); } /** * Construct an iterator with the specified root * and a midwife that simply returns an empty iterator * for the root. * Use this constructor if you want to override the * <code>children(Object)</code> method instead of building * a <code>Midwife</code>. */ public TreeIterator(Object root) { this(root, Midwife.NULL_INSTANCE); } /** * Construct an iterator with the specified root * and midwife. */ public TreeIterator(Object root, Midwife midwife) { this(new SingleElementIterator(root), midwife); } /** * Construct an iterator with the specified roots * and midwife. */ public TreeIterator(Iterator roots, Midwife midwife) { super(); this.currentIterator = roots; // use a LinkedList since we will be pulling off the front and adding to the end this.iterators = new LinkedList(); this.midwife = midwife; } /** * @see java.util.Iterator#hasNext() */ public boolean hasNext() { if (this.currentIterator.hasNext()) { return true; } for (Iterator stream = this.iterators.iterator(); stream.hasNext(); ) { Iterator iterator = (Iterator) stream.next(); if (iterator.hasNext()) { return true; } } return false; } /** * @see java.util.Iterator#next() */ public Object next() { if (this.currentIterator.hasNext()) { return this.nextInternal(); } for (Iterator stream = this.iterators.iterator(); stream.hasNext(); ) { this.currentIterator = (Iterator) stream.next(); if (this.currentIterator.hasNext()) { break; } stream.remove(); } return this.nextInternal(); } /** * Fetch the children of the next node before returning it. */ private Object nextInternal() { Object next = this.currentIterator.next(); this.iterators.add(this.children(next)); return next; } /** * @see java.util.Iterator#remove() */ public void remove() { this.currentIterator.remove(); } /** * Return the immediate children of the specified object. */ protected Iterator children(Object next) { return this.midwife.children(next); } /** * @see java.lang.Object#toString() */ public String toString() { return ClassTools.shortClassNameForObject(this) + '(' + this.currentIterator + ')'; } //********** inner classes ********** /** * Used by <code>TreeIterator</code> to retrieve * the immediate children of a node in the tree. */ public interface Midwife { /** * Return the immediate children of the specified object. */ Iterator children(Object next); Midwife NULL_INSTANCE = new Midwife() { // return no children public Iterator children(Object next) { return NullIterator.instance(); } }; } }