/**
* The MIT License (MIT)
*
* Copyright (c) 2014-2017 Yegor Bugayenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.takes.misc;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;
/**
* Select elements into a new iterable with given condition.
*
* @author Jason Wong (super132j@yahoo.com)
* @version $Id: 03ff330913d8522d7bc1cb3967c8582ebb61976c $
* @param <T> Type of item
* @since 0.13.8
*/
public final class Select<T> implements Iterable<T> {
/**
* Internal storage to hold the elements from iterables.
*/
private final Iterable<T> list;
/**
* The condition to filter the element in the iterator.
*/
private final Condition<T> condition;
/**
* To produce an iterable collection, determined by condition, combining a
* and b, with order of the elements in a first.
* @param itb Iterable to select
* @param cond To determine which element to add in the final iterable
*/
public Select(final Iterable<T> itb, final Condition<T> cond) {
this.list = itb;
this.condition = cond;
}
@Override
public String toString() {
return String.format("%s [if %s]", this.list, this.condition);
}
@Override
public Iterator<T> iterator() {
return new SelectIterator<T>(
this.list.iterator(),
this.condition
);
}
/**
* The select iterator to traverse the input iterables and return the
* elements from the list with given condition.
*
* <p>This class is NOT thread-safe.
*
* @param <E> Type of item
*/
private static final class SelectIterator<E> implements Iterator<E> {
/**
* The iterator to reflect the traverse state.
*/
private final Iterator<E> iterator;
/**
* The condition to filter the elements in the iterator.
*/
private final Condition<E> condition;
/**
* The buffer storing the objects of the iterator.
*/
private final Queue<E> buffer;
/**
* Ctor. ConcatIterator traverses the element.
* @param itr Iterator of the original iterable
* @param cond Condition to filter out elements
*/
SelectIterator(final Iterator<E> itr, final Condition<E> cond) {
this.buffer = new LinkedList<E>();
this.condition = cond;
this.iterator = itr;
}
@Override
public boolean hasNext() {
if (this.buffer.isEmpty()) {
while (this.iterator.hasNext()) {
final E object = this.iterator.next();
if (this.condition.fits(object)) {
this.buffer.add(object);
break;
}
}
}
return !this.buffer.isEmpty();
}
@Override
public E next() {
if (!this.hasNext()) {
throw new NoSuchElementException(
"No more element with fits the select condition."
);
}
return this.buffer.poll();
}
@Override
public void remove() {
throw new UnsupportedOperationException(
"This iterable is immutable and cannot remove anything"
);
}
}
}