/*
 * History
 * Created on Aug 23, 2004 by kofke
 */
package etomica.atom.iterator;

import etomica.Atom;
import etomica.AtomIterator;
import etomica.AtomSet;
import etomica.action.AtomAction;
import etomica.action.AtomActionAdapter;
import etomica.action.AtomsetAction;
import etomica.action.AtomsetCount;
import etomica.atom.AtomFilter;

/**
 * Wraps an AtomIterator and filters its iterates so that
 * only those meeting specified criteria are returned.
 */
public class AtomIteratorFiltered implements AtomIterator {

	/**
	 * Default constructor that causes no atoms to be filtered.
	 * Iterator will give all iterates of the given iterator
	 * until another filter is specified.
	 */
	public AtomIteratorFiltered(AtomIterator iterator) {
		this(iterator, AtomFilter.ACCEPT_ALL);
	}
	
	/**
	 * Returns the iterates of the given iterator that meet
	 * the critertia of the given filter.
	 * @param iterator
	 * @param filter
	 */
	public AtomIteratorFiltered(AtomIterator iterator, AtomFilter filter) {
		this.iterator = iterator;
	}

	
	/**
	 * Returns true if the iterator contains the given atom and
	 * atom meets the filter's criteria.
	 */
	public boolean contains(AtomSet atom) {
		return filter.accept((Atom)atom) && iterator.contains(atom);
	}
	
	/**
	 * Indicates whether iterator has another iterate to return.
	 */
	public boolean hasNext() {
		return next != null;
	}

	/**
	 * Puts iterator in state ready for iteration.
	 */
	public void reset() {
		iterator.reset();
		next();
	}

	/**
	 * Sets iterator so that hasNext returns false.
	 */
	public void unset() {
		iterator.unset();
		next = null;
	}

	/**
	 * Returns the next atom from the iterator that meets the 
	 * filter's criteria.
	 */
	public Atom nextAtom() {
		Atom nextAtom = next;
		next = null;
		while(iterator.hasNext() && next == null) {
			next = iterator.nextAtom();
			if(!filter.accept(next)) next = null;
		}
		return nextAtom;
	}
	
	public AtomSet next() {
		return nextAtom();
	}
	
	/**
	 * Returns next atom without advancing the iterator.
	 */
	public AtomSet peek() {
		return next;
	}

	/**
	 * Performs the given action on all atoms from iterator that 
	 * meet the filter criteria.
	 */
	public void allAtoms(AtomsetAction action) {
		iterator.allAtoms(actionWrapper(filter,(AtomAction)action));
	}

	/**
	 * Returns the number of iterates given by the
	 * iterator that meet the criteria of the 
	 * filter.
	 */
	public int size() {
		AtomsetCount counter = new AtomsetCount();
		allAtoms(counter);
		return counter.callCount();
	}
	
	public final int nBody() {return 1;}
	
	/**
	 * @return Returns the filter.
	 */
	public AtomFilter getFilter() {
		return filter;
	}
	/**
	 * @param filter The filter to set.
	 */
	public void setFilter(AtomFilter filter) {
		this.filter = filter;
	}
	
	private final AtomIterator iterator;
	private AtomFilter filter;
	private Atom next;

	/**
	 * Returns a new action that wraps the given action such that action is performed
	 * only on the atoms meeting the filter's criteria.
	 */
	private static AtomAction actionWrapper(final AtomFilter filter, final AtomAction action) {
		return new AtomActionAdapter() {
			public void actionPerformed(Atom atom) {
				if(filter.accept(atom)) action.actionPerformed(atom);
			}
		};
	}
}

@@ -529,405 +529,316 @@
 %09 * 
-Default constructor that causes no atoms to be filtered.%0A%09 * Iterator will give all iterates of the given iterator%0A%09 * until another filter is specified.%0A%09 */%0A%09public AtomIteratorFiltered(AtomIterator iterator) %7B%0A%09%09this(iterator, AtomFilter.ACCEPT_ALL);%0A%09%7D%0A%09%0A%09/**%0A%09 * Returns the iterates of the given iterator that meet%0A%09 * the critertia of the given filter.%0A%09 * @param iterator%0A%09 * @param filter
+Returns the iterates of the given iterator that meet%0A%09 * the critertia of the given filter.  Filter is final and%0A     * cannot be changed after construction.%0A%09 * @param iterator the wrapped iterator%0A%09 * @param filter iterator returns only those atoms for which%0A     * this filter's accept method returns true
 %0A%09 *
@@ -940,16 +940,46 @@
 erator;%0A
+        this.filter = filter;%0A
 %09%7D%0A%0A%09%0A%09/
@@ -1428,16 +1428,20 @@
 ;%0A%09%09next
+Atom
 ();%0A%09%7D%0A%0A
@@ -2519,222 +2519,8 @@
 ;%7D%0A%09
-%0A%09/**%0A%09 * @return Returns the filter.%0A%09 */%0A%09public AtomFilter getFilter() %7B%0A%09%09return filter;%0A%09%7D%0A%09/**%0A%09 * @param filter The filter to set.%0A%09 */%0A%09public void setFilter(AtomFilter filter) %7B%0A%09%09this.filter = filter;%0A%09%7D%0A
 %09%0A%09p
@@ -2555,16 +2555,16 @@
 erator;%0A
-
 %09private
@@ -2560,24 +2560,30 @@
 r;%0A%09private 
+final 
 AtomFilter f

make filter final