/******************************************************************************* * 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.Iterator; import java.util.NoSuchElementException; import org.eclipse.persistence.tools.workbench.utility.ClassTools; /** * A <code>ChainIterator</code> provides a pluggable <code>Iterator</code> * that loops over a chain of arbitrarily linked objects. The chain * should be null-terminated (i.e. a call to the <code>nextLink(Object)</code> * method should return <code>null</code> when it is passed the last * link of the chain). * To use, supply a starting link and supply a <code>Linker</code> or * subclass <code>ChainIterator</code> and override the * <code>nextLink(Object)</code> method. * The starting link will be the first object returned by the iterator. * If the starting link is <code>null</code>, the iterator will be empty. * Note that the iterator does not support <code>null</code> elements. */ public class ChainIterator implements Iterator { private Object nextLink; private Linker linker; /** * Construct an iterator with the specified starting link * and a linker that simply returns null, indicating the end of the chain. * Use this constructor if you want to override the * <code>nextLink(Object)</code> method instead of building * a <code>Linker</code>. */ public ChainIterator(Object startLink) { this(startLink, Linker.NULL_INSTANCE); } /** * Construct an iterator with the specified starting link * and linker. */ public ChainIterator(Object startLink, Linker linker) { super(); this.nextLink = startLink; this.linker = linker; } /** * @see java.util.Iterator#hasNext() */ public boolean hasNext() { return this.nextLink != null; } /** * @see java.util.Iterator#next() */ public Object next() { if (this.nextLink == null) { throw new NoSuchElementException(); } Object result = this.nextLink; this.nextLink = this.nextLink(this.nextLink); return result; } /** * @see java.util.Iterator#remove() */ public void remove() { throw new UnsupportedOperationException(); } /** * Return the next link in the chain. */ protected Object nextLink(Object currentLink) { return this.linker.nextLink(currentLink); } /** * @see java.lang.Object#toString() */ public String toString() { return ClassTools.shortClassNameForObject(this) + '(' + this.nextLink + ')'; } //********** inner classes ********** /** * Used by <code>ChainIterator</code> to link * the elements in the chain. */ public interface Linker { /** * Return the next link in the chain. */ Object nextLink(Object currentLink); Linker NULL_INSTANCE = new Linker() { // simply return null, indicating the chain is ended public Object nextLink(Object currentLink) { return null; } }; } }