001    /*
002     * Copyright (C) 2008 Google Inc.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.collect;
018    
019    import static com.google.common.base.Preconditions.checkArgument;
020    import static com.google.common.base.Preconditions.checkNotNull;
021    
022    import com.google.common.annotations.GwtCompatible;
023    import com.google.common.base.Function;
024    import com.google.common.base.Joiner;
025    import com.google.common.base.Predicate;
026    import com.google.common.base.Predicates;
027    
028    import java.util.AbstractCollection;
029    import java.util.Collection;
030    import java.util.Iterator;
031    import java.util.Set;
032    
033    import javax.annotation.Nullable;
034    
035    /**
036     * Provides static methods for working with {@code Collection} instances.
037     *
038     * @author Chris Povirk
039     * @author Mike Bostock
040     * @author Jared Levy
041     * @since 2 (imported from Google Collections Library)
042     */
043    @GwtCompatible
044    public final class Collections2 {
045      private Collections2() {}
046    
047      /**
048       * Returns {@code true} if the collection {@code self} contains all of the
049       * elements in the collection {@code c}.
050       *
051       * <p>This method iterates over the specified collection {@code c}, checking
052       * each element returned by the iterator in turn to see if it is contained in
053       * the specified collection {@code self}. If all elements are so contained,
054       * {@code true} is returned, otherwise {@code false}.
055       *
056       * @param self a collection which might contain all elements in {@code c}
057       * @param c a collection whose elements might be contained by {@code self}
058       */
059      // TODO: Make public?
060      static boolean containsAll(Collection<?> self, Collection<?> c) {
061        checkNotNull(self);
062        for (Object o : c) {
063          if (!self.contains(o)) {
064            return false;
065          }
066        }
067        return true;
068      }
069    
070      /**
071       * Converts an iterable into a collection. If the iterable is already a
072       * collection, it is returned. Otherwise, an {@link java.util.ArrayList} is
073       * created with the contents of the iterable in the same iteration order.
074       */
075      static <E> Collection<E> toCollection(Iterable<E> iterable) {
076        return (iterable instanceof Collection)
077            ? (Collection<E>) iterable
078            : Lists.newArrayList(iterable.iterator());
079      }
080    
081      /**
082       * Returns the elements of {@code unfiltered} that satisfy a predicate. The
083       * returned collection is a live view of {@code unfiltered}; changes to one
084       * affect the other.
085       *
086       * <p>The resulting collection's iterator does not support {@code remove()},
087       * but all other collection methods are supported. The collection's
088       * {@code add()} and {@code addAll()} methods throw an
089       * {@link IllegalArgumentException} if an element that doesn't satisfy the
090       * predicate is provided. When methods such as {@code removeAll()} and
091       * {@code clear()} are called on the filtered collection, only elements that
092       * satisfy the filter will be removed from the underlying collection.
093       *
094       * <p>The returned collection isn't threadsafe or serializable, even if
095       * {@code unfiltered} is.
096       *
097       * <p>Many of the filtered collection's methods, such as {@code size()},
098       * iterate across every element in the underlying collection and determine
099       * which elements satisfy the filter. When a live view is <i>not</i> needed,
100       * it may be faster to copy {@code Iterables.filter(unfiltered, predicate)}
101       * and use the copy.
102       */
103      public static <E> Collection<E> filter(
104          Collection<E> unfiltered, Predicate<? super E> predicate) {
105        if (unfiltered instanceof FilteredCollection) {
106          // Support clear(), removeAll(), and retainAll() when filtering a filtered
107          // collection.
108          return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
109        }
110    
111        return new FilteredCollection<E>(
112            checkNotNull(unfiltered), checkNotNull(predicate));
113      }
114    
115      /**
116       * Delegates to {@link Collection#contains}.  Returns {@code false} on {@code
117       * ClassCastException}
118       */
119      static boolean safeContains(Collection<?> collection, Object object) {
120        try {
121          return collection.contains(object);
122        } catch (ClassCastException e) {
123          return false;
124        }
125      }
126    
127      static class FilteredCollection<E> implements Collection<E> {
128        final Collection<E> unfiltered;
129        final Predicate<? super E> predicate;
130    
131        FilteredCollection(Collection<E> unfiltered,
132            Predicate<? super E> predicate) {
133          this.unfiltered = unfiltered;
134          this.predicate = predicate;
135        }
136    
137        FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
138          return new FilteredCollection<E>(unfiltered,
139              Predicates.<E>and(predicate, newPredicate));
140          // .<E> above needed to compile in JDK 5
141        }
142    
143        public boolean add(E element) {
144          checkArgument(predicate.apply(element));
145          return unfiltered.add(element);
146        }
147    
148        public boolean addAll(Collection<? extends E> collection) {
149          for (E element : collection) {
150            checkArgument(predicate.apply(element));
151          }
152          return unfiltered.addAll(collection);
153        }
154    
155        public void clear() {
156          Iterables.removeIf(unfiltered, predicate);
157        }
158    
159        public boolean contains(Object element) {
160          try {
161            // unsafe cast can result in a CCE from predicate.apply(), which we
162            // will catch
163            @SuppressWarnings("unchecked")
164            E e = (E) element;
165            return predicate.apply(e) && unfiltered.contains(element);
166          } catch (NullPointerException e) {
167            return false;
168          } catch (ClassCastException e) {
169            return false;
170          }
171        }
172    
173        public boolean containsAll(Collection<?> collection) {
174          for (Object element : collection) {
175            if (!contains(element)) {
176              return false;
177            }
178          }
179          return true;
180        }
181    
182        public boolean isEmpty() {
183          return !Iterators.any(unfiltered.iterator(), predicate);
184        }
185    
186        public Iterator<E> iterator() {
187          return Iterators.filter(unfiltered.iterator(), predicate);
188        }
189    
190        public boolean remove(Object element) {
191          try {
192            // unsafe cast can result in a CCE from predicate.apply(), which we
193            // will catch
194            @SuppressWarnings("unchecked")
195            E e = (E) element;
196            return predicate.apply(e) && unfiltered.remove(element);
197          } catch (NullPointerException e) {
198            return false;
199          } catch (ClassCastException e) {
200            return false;
201          }
202        }
203    
204        public boolean removeAll(final Collection<?> collection) {
205          checkNotNull(collection);
206          Predicate<E> combinedPredicate = new Predicate<E>() {
207            public boolean apply(E input) {
208              return predicate.apply(input) && collection.contains(input);
209            }
210          };
211          return Iterables.removeIf(unfiltered, combinedPredicate);
212        }
213    
214        public boolean retainAll(final Collection<?> collection) {
215          checkNotNull(collection);
216          Predicate<E> combinedPredicate = new Predicate<E>() {
217            public boolean apply(E input) {
218              return predicate.apply(input) && !collection.contains(input);
219            }
220          };
221          return Iterables.removeIf(unfiltered, combinedPredicate);
222        }
223    
224        public int size() {
225          return Iterators.size(iterator());
226        }
227    
228        public Object[] toArray() {
229          // creating an ArrayList so filtering happens once
230          return Lists.newArrayList(iterator()).toArray();
231        }
232    
233        public <T> T[] toArray(T[] array) {
234          return Lists.newArrayList(iterator()).toArray(array);
235        }
236    
237        @Override public String toString() {
238          return Iterators.toString(iterator());
239        }
240      }
241    
242      /**
243       * Returns a collection that applies {@code function} to each element of
244       * {@code fromCollection}. The returned collection is a live view of {@code
245       * fromCollection}; changes to one affect the other.
246       *
247       * <p>The returned collection's {@code add()} and {@code addAll()} methods
248       * throw an {@link UnsupportedOperationException}. All other collection
249       * methods are supported, as long as {@code fromCollection} supports them.
250       *
251       * <p>The returned collection isn't threadsafe or serializable, even if
252       * {@code fromCollection} is.
253       *
254       * <p>When a live view is <i>not</i> needed, it may be faster to copy the
255       * transformed collection and use the copy.
256       */
257      public static <F, T> Collection<T> transform(Collection<F> fromCollection,
258          Function<? super F, T> function) {
259        return new TransformedCollection<F, T>(fromCollection, function);
260      }
261    
262      static class TransformedCollection<F, T> extends AbstractCollection<T> {
263        final Collection<F> fromCollection;
264        final Function<? super F, ? extends T> function;
265    
266        TransformedCollection(Collection<F> fromCollection,
267            Function<? super F, ? extends T> function) {
268          this.fromCollection = checkNotNull(fromCollection);
269          this.function = checkNotNull(function);
270        }
271    
272        @Override public void clear() {
273          fromCollection.clear();
274        }
275    
276        @Override public boolean isEmpty() {
277          return fromCollection.isEmpty();
278        }
279    
280        @Override public Iterator<T> iterator() {
281          return Iterators.transform(fromCollection.iterator(), function);
282        }
283    
284        @Override public int size() {
285          return fromCollection.size();
286        }
287      }
288    
289      static boolean setEquals(Set<?> thisSet, @Nullable Object object) {
290        if (object == thisSet) {
291          return true;
292        }
293        if (object instanceof Set) {
294          Set<?> thatSet = (Set<?>) object;
295          return thisSet.size() == thatSet.size()
296              && thisSet.containsAll(thatSet);
297        }
298        return false;
299      }
300    
301      static final Joiner standardJoiner = Joiner.on(", ");
302    }