/******************************************************************************* * 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 org.eclipse.persistence.tools.workbench.utility.ClassTools; /** * A <code>CloneIterator</code> iterates over a copy of a collection, * allowing for concurrent access to the original collection. * <p> * The original collection passed to the <code>CloneIterator</code>'s * constructor should be synchronized; otherwise you run the risk of * a corrupted collection. * <p> * By default, a <code>CloneIterator</code> does not support the * <code>#remove()</code> operation; this is because it does not have * access to the original collection. But if the <code>CloneIterator</code> * is supplied with an <code>Mutator</code> it will delegate the * <code>#remove()</code> operation to the <code>Mutator</code>. * Alternatively, a subclass can override the <code>#remove(Object)</code> * method. */ public class CloneIterator implements Iterator { private Iterator nestedIterator; private Object current; private Mutator mutator; private static final Object UNKNOWN = new Object(); // ********** constructors ********** /** * Construct an iterator on a copy of the specified collection. * The <code>#remove()</code> method will not be supported, * unless a subclass overrides the <code>#remove(Object)</code>. */ public CloneIterator(Collection c) { this(c, Mutator.READ_ONLY_INSTANCE); } /** * Construct an iterator on a copy of the specified collection. * Use the specified mutator to remove objects from the * original collection. */ public CloneIterator(Collection c, Mutator mutator) { super(); this.nestedIterator = new ArrayIterator(c.toArray()); this.mutator = mutator; this.current = UNKNOWN; } // ********** Iterator implementation ********** /** * @see java.util.Iterator#hasNext() */ public boolean hasNext() { return this.nestedIterator.hasNext(); } /** * @see java.util.Iterator#next() */ public Object next() { this.current = this.nestedIterator.next(); return this.current; } /** * @see java.util.Iterator#remove() */ public void remove() { if (this.current == UNKNOWN) { throw new IllegalStateException(); } this.remove(this.current); this.current = UNKNOWN; } // ********** internal methods ********** /** * Remove the specified element from the original collection. * <p> * This method can be overridden by a subclass as an * alternative to building an <code>Mutator</code>. */ protected void remove(Object o) { this.mutator.remove(o); } /** * @see java.lang.Object#toString() */ public String toString() { return ClassTools.shortClassNameForObject(this); } //********** member interface ********** /** * Used by <code>CloneIterator</code> to remove * elements from the original collection; since the iterator * does not have direct access to the original collection. */ public interface Mutator { /** * Remove the specified object from the original collection. */ void remove(Object current); Mutator READ_ONLY_INSTANCE = new Mutator() { public void remove(Object current) { throw new UnsupportedOperationException(); } public String toString() { return "ReadOnlyMutator"; } }; } }