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); } }