package net.bytebuddy.matcher;
import java.util.
AbstractList;
import java.util.
ArrayList;
import java.util.
List;
/**
* A filterable list allows to use an {@link net.bytebuddy.matcher.ElementMatcher} to reduce a lists to elements
* that are matched by this matcher in this list.
*
* @param <T> The type of the collection's elements.
* @param <S> The type of this list.
*/
public interface
FilterableList<T, S extends
FilterableList<T, S>> extends
List<T> {
/**
* Filters any elements in this lists by the given {@code elementMatcher} and returns a list that are matched
* by the given matcher.
*
* @param elementMatcher The element matcher to match the elements of this list against.
* @return A new list only containing the matched elements.
*/
S
filter(
ElementMatcher<? super T>
elementMatcher);
/**
* Returns the only element of this list. If there is not exactly one element in this list, an
* {@link java.lang.IllegalStateException} is thrown.
*
* @return The only element of this list.
*/
T
getOnly();
@
Override
S
subList(int
fromIndex, int
toIndex);
/**
* An implementation of an empty {@link net.bytebuddy.matcher.FilterableList}.
*
* @param <T> The type of the collection's elements.
* @param <S> The type of this list.
*/
class
Empty<T, S extends
FilterableList<T, S>> extends
AbstractList<T> implements
FilterableList<T, S> {
@
Override
public T
get(int
index) {
throw new
IndexOutOfBoundsException("index = " +
index);
}
@
Override
public int
size() {
return 0;
}
@
Override
public T
getOnly() {
throw new
IllegalStateException("size = 0");
}
@
Override
@
SuppressWarnings("unchecked")
public S
filter(
ElementMatcher<? super T>
elementMatcher) {
return (S) this;
}
@
Override
@
SuppressWarnings("unchecked")
public S
subList(int
fromIndex, int
toIndex) {
if (
fromIndex ==
toIndex &&
toIndex == 0) {
return (S) this;
} else if (
fromIndex >
toIndex) {
throw new
IllegalArgumentException("fromIndex(" +
fromIndex + ") > toIndex(" +
toIndex + ")");
} else {
throw new
IndexOutOfBoundsException("fromIndex = " +
fromIndex);
}
}
}
/**
* A base implementation of a {@link net.bytebuddy.matcher.FilterableList}.
*
* @param <T> The type of the collection's elements.
* @param <S> The type of this list.
*/
abstract class
AbstractBase<T, S extends
FilterableList<T, S>> extends
AbstractList<T> implements
FilterableList<T, S> {
/**
* A convenience variable indicating the index of a list's only variable.
*/
private static final int
ONLY = 0;
@
Override
@
SuppressWarnings("unchecked")
public S
filter(
ElementMatcher<? super T>
elementMatcher) {
List<T>
filteredElements = new
ArrayList<T>(
size());
for (T
value : this) {
if (
elementMatcher.
matches(
value)) {
filteredElements.
add(
value);
}
}
return
filteredElements.
size() ==
size() ?
(S) this
:
wrap(
filteredElements);
}
@
Override
public T
getOnly() {
if (
size() != 1) {
throw new
IllegalStateException("size = " +
size());
}
return
get(
ONLY);
}
@
Override
public S
subList(int
fromIndex, int
toIndex) {
return
wrap(super.subList(
fromIndex,
toIndex));
}
/**
* Represents a list of values as an instance of this instance's list type.
*
* @param values The values to wrap in an instance of this list's type.
* @return A wrapped instance of the given {@code values}.
*/
protected abstract S
wrap(
List<T>
values);
}
}