diff options
Diffstat (limited to 'javax/lang/model/util/ElementFilter.java')
-rw-r--r-- | javax/lang/model/util/ElementFilter.java | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/javax/lang/model/util/ElementFilter.java b/javax/lang/model/util/ElementFilter.java new file mode 100644 index 000000000..b91a1debc --- /dev/null +++ b/javax/lang/model/util/ElementFilter.java @@ -0,0 +1,425 @@ +/* ElementFilter.java -- Filter for a collection of elements. + Copyright (C) 2012 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.lang.model.util; + +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +/** + * <p>Filter for selecting elements of interest from a collection. + * The returned collections are new instances, but use the original + * collection as a backing store. They are not safe for concurrent + * access. The iteration order remains the same. Null values are + * not allowed and will throw a {@code NullPointerException}.</p> + *<p>For convenience, a static import may be used to allow the + * methods to be called more succinctly.</p> + * + * @since 1.6 + */ +public class ElementFilter +{ + + /** + * Returns a set containing just the {@link TypeElement}s + * held in {@code elements}. + * + * @param elements the elements to filter. + * @return the filtered set. + */ + public static Set<TypeElement> typesIn(Set<? extends Element> elements) + { + return new FilteredSet<TypeElement>(elements, TypeElement.class); + } + + /** + * Provides a filtered view of the given set, returning only + * instances which are instances of the specified class or + * one of its subclasses. + */ + private static final class FilteredSet<E extends Element> implements Set<E> + { + + /** + * The set being filtered. + */ + private Set<Element> elements; + + /** + * The class returned elements must be instances of. + */ + private Class<E> clazz; + + /** + * Constructs a new filtered set, returning + * only instances of {@code clazz} from + * {@code elements}. + * + * @param elements the set to filter. + * @param clazz the class returned elements must be instances of. + * @throws NullPointerException if the set contains a null element. + */ + @SuppressWarnings("unchecked") + public FilteredSet(Set<? extends Element> elements, Class<E> clazz) + { + this.elements = (Set<Element>) elements; + this.clazz = clazz; + for (Element e : elements) + if (e == null) + throw new NullPointerException("Sets can not contain null values."); + } + + /** + * Adds an element to the set by passing it to the backing set. + * + * @param elem the element to add. + * @return true if the element was added. + */ + public boolean add(E elem) + { + return elements.add(elem); + } + + /** + * Add all elements of the given collection, which aren't already + * present in this set, to this set. If the supplied collection + * is also a set, the resulting set is the union of the two. + * This call is passed to the backing set. + * + * @param coll the collection of elements to add. + * @return true if the set was modified. + */ + public boolean addAll(Collection<? extends E> coll) + { + return elements.addAll(coll); + } + + /** + * Removes all elements from the set. + */ + public void clear() + { + elements.clear(); + } + + /** + * Returns true if the element is an instance of the + * filter class and the backing set contains the given element. + * + * @param obj the object to check for. + * @return true if the backing set contains the element. + */ + public boolean contains(Object obj) + { + if (clazz.isInstance(obj)) + return elements.contains(obj); + return false; + } + + /** + * Returns true if the set contains all elements of the + * given collection. If the collection is also a set, + * a return value of {@code true} means that the given + * set is a subset of this set. + * + * @param coll the collection of elements to check. + * @return true if the set contains all elements in {@code coll}. + */ + public boolean containsAll(Collection<?> coll) + { + for (Object obj : coll) + if (!contains(obj)) + return false; + return true; + } + + /** + * Returns true if the specified object is also a set + * of the same size and every member of it is also contained + * in this set. + * + * @param obj the object to compare. + * @return true if the above requirements are met. + */ + public boolean equals(Object obj) + { + if (obj == null) + return false; + if (obj instanceof Set) + { + Set<?> otherSet = (Set<?>) obj; + return size() == otherSet.size() && + containsAll(otherSet); + } + return false; + } + + /** + * Returns the hashcode of the set. The hash code is computed + * by taking the sum of the hash codes of the objects in the set. + * + * @return the hashcode of this set. + */ + public int hashCode() + { + int sum = 0; + for (E elem : this) + sum += elem.hashCode(); + return sum; + } + + /** + * Returns true if the set contains no elements. + * + * @return true if the size is zero. + */ + public boolean isEmpty() + { + return size() == 0; + } + + /** + * Returns an iterator over the set's elements. + * + * @return the iterator. + */ + public Iterator<E> iterator() + { + return new FilteredIterator<E>(elements.iterator(), clazz); + } + + /** + * Removes an element from the set if present. + * + * @param obj the object to remove. + * @return true if the set contained the element. + */ + public boolean remove(Object obj) + { + if (clazz.isInstance(obj)) + return elements.remove(obj); + return false; + } + + /** + * Removes from the set all elements contained in the specified + * collection. If the collection is also a set, the resulting + * set is the asymmetric set difference of the two. + * + * @param coll the collection of elements to remove. + * @return true if the set changed. + */ + public boolean removeAll(Collection<?> coll) + { + boolean modified = false; + for (Object obj : coll) + if (remove(obj)) + modified = true; + return modified; + } + + /** + * Retains only the elements in this set which are also contained in + * the specified collection. If the collection is also a set, the + * resulting set is the intersection of the two. + * + * @param coll the collection of elements to remove. + * @return true if the set changed. + */ + public boolean retainAll(Collection<?> coll) + { + boolean modified = false; + for (E elem : this) + if (!coll.contains(elem)) + { + remove(elem); + modified = true; + } + return modified; + } + + /** + * Returns the size of this set. This is the size of the backing + * set, minus any elements which aren't instances of the filter class. + * + * @return the size of the set. + */ + public int size() + { + int count = 0; + for (Element elem : elements) + if (clazz.isInstance(elem)) + ++count; + return count; + } + + /** + * Returns a new array containing all the elements in the set. + * Modifications to the array do not affect the set. + * + * @return an array of all elements in the set. + */ + public Object[] toArray() + { + int size = size(); + Object[] array = new Object[size]; + Iterator<E> iterator = iterator(); + for (int a = 0; a < size; ++a) + array[a] = iterator.next(); + return array; + } + + /** + * Returns a array containing all the elements in the set with + * the runtime type of the specified array. If all the elements + * from the set fit into the specified array, it will be used + * for the returned array and any remaining space will be + * populated with {@code null} values. Otherwise, a new array + * will be allocated. + * + * @param array the array which may be reused to provide the + * return value of this method. + * @return an array containing all elements in the set. + */ + public <T> T[] toArray(T[] array) + { + int a, size = size(); + Iterator<E> iterator = iterator(); + if (array.length < size) + { + @SuppressWarnings("unchecked") + T[] newArray = (T[]) new Object[size]; + array = newArray; + } + @SuppressWarnings("unchecked") + E[] elemArray = (E[]) array; + for (a = 0; a < size; ++a) + elemArray[a] = iterator.next(); + for (; a < array.length; ++a) + elemArray[a] = null; + return array; + } + + } + + /** + * Provides a filtered view of the given iterator, returning only + * instances which are instances of the specified class or + * one of its subclasses. + */ + private static final class FilteredIterator<E extends Element> implements Iterator<E> + { + + /** + * The iterator to filter. + */ + private Iterator<Element> iterator; + + /** + * The class returned elements must be instances of. + */ + private Class<E> clazz; + + /** + * Holds the next object if we had to retrieve it + * in the {@link #hasNext()} method. + */ + private E next; + + /** + * Constructs a new filtered iterator which only returns + * elements that are a subclass of the given class. + * + * @param iterator the iterator to filter. + * @param clazz the class returned elements must be instances of. + */ + public FilteredIterator(Iterator<Element> iterator, Class<E> clazz) + { + this.iterator = iterator; + this.clazz = clazz; + } + + /** + * Returns true if there are more elements to come. + * + * @return true if there are more elements to retrieve. + */ + public boolean hasNext() + { + while (iterator.hasNext() && next == null) + { + next = clazz.cast(iterator.next()); + if (!clazz.isInstance(next)) + next = null; + } + return next != null; + } + + /** + * Returns the next element in the iteration which is an + * instance of the specified class. + * + * @return the next element. + */ + public E next() + { + if (next == null) + if (!hasNext()) + throw new NoSuchElementException("No more elements to return."); + E retVal = next; + next = null; + return retVal; + } + + /** + * Removes the last element returned by the iterator. + * As we only return elements that match the filter, + * the underlying iterator will always remove one of those. + */ + public void remove() + { + iterator.remove(); + } + + } +} + |