package nl.ipo.cds.etl.featurecollection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;
import nl.ipo.cds.domain.FeatureType;
import nl.ipo.cds.etl.Feature;
import nl.ipo.cds.etl.FeatureFilter;
import nl.ipo.cds.etl.FeatureOutputStream;
import nl.ipo.cds.etl.GenericFeature;
import org.deegree.geometry.Envelope;
public class FilteringFeatureCollection implements FeatureCollection {
private final FeatureCollection collection;
private final FeatureFilter<GenericFeature, GenericFeature> filter;
private final FeatureOutputStream<Feature> errorOutputStream;
public FilteringFeatureCollection (final FeatureCollection collection, final FeatureFilter<GenericFeature, GenericFeature> filter) {
this (collection, filter, null);
}
public FilteringFeatureCollection (final FeatureCollection collection, final FeatureFilter<GenericFeature, GenericFeature> filter, final FeatureOutputStream<Feature> errorStream) {
if (collection == null) {
throw new NullPointerException ("collection cannot be null");
}
this.collection = collection;
this.filter = filter;
this.errorOutputStream = errorStream;
}
@Override
public Iterator<GenericFeature> iterator () {
if (filter == null) {
return collection.iterator ();
}
return new FilteringIterator ();
}
@Override
public Envelope getBoundedBy () {
return collection.getBoundedBy ();
}
@Override
public FeatureType getFeatureType () {
return collection.getFeatureType ();
}
private class FilteringIterator implements Iterator<GenericFeature> {
private final Iterator<GenericFeature> iterator;
private final Queue<GenericFeature> queue = new LinkedList<GenericFeature> ();
private final FeatureOutputStream<GenericFeature> outputStream;
private final FeatureOutputStream<Feature> errorStream;
public FilteringIterator () {
this.iterator = collection.iterator ();
this.outputStream = new FeatureOutputStream<GenericFeature> () {
@Override
public void writeFeature (final GenericFeature feature) {
queue.offer (feature);
}
};
this.errorStream = new FeatureOutputStream<Feature> () {
@Override
public void writeFeature(Feature feature) {
if (errorOutputStream != null) {
errorOutputStream.writeFeature (feature);
}
}
};
}
@Override
public boolean hasNext () {
if (!populateQueue ()) {
return false;
}
return true;
}
@Override
public GenericFeature next () {
if (!populateQueue ()) {
throw new NoSuchElementException ();
}
return queue.poll ();
}
@Override
public void remove () {
throw new UnsupportedOperationException ("remove is not supported");
}
/**
* Reads values from the input iterator and filters them until the queue is no longer empty.
*
* @return true if items have been added to the queue, false if the input iterator is exhausted.
*/
private boolean populateQueue () {
while (queue.isEmpty ()) {
if (!iterator.hasNext ()) {
return false;
}
final GenericFeature feature = iterator.next ();
filter.processFeature (feature, outputStream, errorStream);
}
return true;
}
}
}