package org.codefx.libfx.collection.transform;
import java.util.ListIterator;
import java.util.Objects;
import java.util.function.Function;
/**
* A {@link ListIterator} which wraps another list iterator and transforms elements from an inner type {@code I} to an
* outer type {@code O} and vice versa.
* <p>
* The transformation of null elements of either inner or outer type is fixed to {@code null -> null}. The
* transformation functions specified during construction do not have to handle null input elements and are not allowed
* to produce a null result.
*
* @param <I>
* the inner type, i.e. the type of the elements returned by the wrapped/inner list iterator
* @param <O>
* the outer type, i.e. the type of elements returned by this list iterator
*/
public final class TransformingListIterator<I, O> extends AbstractTransformingListIterator<I, O> {
private final ListIterator<I> innerListIterator;
private final Function<? super I, ? extends O> transformToOuter;
private final Function<? super O, ? extends I> transformToInner;
/**
* Creates a new transforming list iterator.
* <p>
* If the specified list iterator is used by any other instance, the behavior is undefined. The specified transform
* functions will not be called with null elements and are not allowed to return null.
*
* @param innerListIterator
* the wrapped/inner list iterator
* @param transformToOuter
* transforms elements from the inner type {@code I} to the outer type {@code O}
* @param transformToInner
* transforms elements from the outer type {@code O} to the inner type {@code I}
*/
public TransformingListIterator(
ListIterator<I> innerListIterator,
Function<? super I, ? extends O> transformToOuter, Function<? super O, ? extends I> transformToInner) {
Objects.requireNonNull(innerListIterator, "The argument 'innerListIterator' must not be null.");
Objects.requireNonNull(transformToOuter, "The argument 'transformToOuter' must not be null.");
Objects.requireNonNull(transformToInner, "The argument 'transformToInner' must not be null.");
this.innerListIterator = innerListIterator;
this.transformToOuter = transformToOuter;
this.transformToInner = transformToInner;
}
@Override
protected ListIterator<I> getInnerIterator() {
return innerListIterator;
}
@Override
protected O transformToOuter(I innerElement) {
if (innerElement == null)
return null;
O outerElement = transformToOuter.apply(innerElement);
Objects.requireNonNull(outerElement, "The transformation must not create null instances.");
return outerElement;
}
@Override
protected I transformToInner(O outerElement) {
if (outerElement == null)
return null;
I innerElement = transformToInner.apply(outerElement);
Objects.requireNonNull(innerElement, "The transformation must not create null instances.");
return innerElement;
}
}