/******************************************************************************* * Copyright (c) 2001, 2008 Oracle Corporation and others. * 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.eclipse.org/legal/epl-v10.html * * Contributors: * Oracle Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jst.jsf.common.internal.policy; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * An iterator policy that creates Iterators that traverse a target collection * by returning items in the order they are in the policyOrder object pased at * construction. The target collection passed to getIterator is copied, so the * iterator will not be effected by subsequent changes to the target. * * NOTE: the policyOrder iterable collection should not be modified after it is * passed to the constructor. * * The class is thread-safe, however the iterators are not. That is, more than * one thread can safely call any of the public methods, however each Iterator * returned by getIterator can only be used safely by a single thread. * * @author cbateman * * @param <ITERATORTYPE> */ public class IdentifierOrderedIteratorPolicy<ITERATORTYPE> implements IIteratorPolicy<ITERATORTYPE> { private final Iterable<ITERATORTYPE> _policyOrder; // controls whether the policy iterator will return items that are // not explicitly listed in policyOrder. private volatile boolean _excludeNonExplicitValues = false; /** * @param policyOrder */ public IdentifierOrderedIteratorPolicy(final Iterable<ITERATORTYPE> policyOrder) { _policyOrder = policyOrder; } /** * Default value is <b>false</b>. * * @return if true, the iterator will not return values in the forCollection * passed to getIterator whose identifier are not explicitly listed in * the policyOrder, If false, these values will be return after all * the policyOrder values have been returned. */ public boolean isExcludeNonExplicitValues() { return _excludeNonExplicitValues; } /** * @param excludeNonExplicitValues */ public void setExcludeNonExplicitValues(boolean excludeNonExplicitValues) { _excludeNonExplicitValues = excludeNonExplicitValues; } public Iterator<ITERATORTYPE> getIterator( final Collection<ITERATORTYPE> forCollection) { final boolean excludeNonExplicitValues = _excludeNonExplicitValues; return new MyIterator<ITERATORTYPE>(forCollection, excludeNonExplicitValues, _policyOrder); } private static class MyIterator<ITERATORTYPE> implements Iterator<ITERATORTYPE> { private final List<ITERATORTYPE> _items; private final Iterator<ITERATORTYPE> _policyIterator; private ITERATORTYPE _next; MyIterator(final Collection<ITERATORTYPE> collection, final boolean excludeNonExplicitValues, final Iterable<ITERATORTYPE> policyOrder) { _items = new ArrayList(); _items.addAll(collection); _policyIterator = policyOrder.iterator(); _next = findNext(); } public boolean hasNext() { return _next != null; } public ITERATORTYPE next() { if (_next != null) { ITERATORTYPE next = _next; //calculate next one before returning _next = findNext(); return next; } throw new NoSuchElementException("No more elements"); //$NON-NLS-1$ } public void remove() { throw new UnsupportedOperationException(); } private ITERATORTYPE findNext() { while (_policyIterator.hasNext()) { ITERATORTYPE next = _policyIterator.next(); if (_items.contains(next)) { _items.remove(next); return next; } } // we have exhausted the _items that are in the policy iterator // now return any further _items in the order they are in the list if (_items.size() > 0) { return _items.remove(0); } return null; } } }