001    /*
002     * Created on Apr 29, 2007
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     * 
007     * http://www.apache.org/licenses/LICENSE-2.0
008     * 
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     * 
013     * Copyright @2007 the original author or authors.
014     */
015    package org.fest.util;
016    
017    import static org.fest.util.Strings.quote;
018    
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.Collection;
022    import java.util.HashSet;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Set;
026    
027    /**
028     * Understands utility methods related to collections.
029     * 
030     * @author Yvonne Wang
031     * @author Alex Ruiz
032     */
033    public final class Collections {
034    
035      /**
036       * Creates a list containing the given elements.
037       * @param <T> the type of elements of the list to create.
038       * @param elements the elements to store in the list.
039       * @return a list containing the given elements.
040       */
041      public static <T> List<T> list(T... elements) {
042        if (elements == null) return null;
043        return new ArrayList<T>(Arrays.asList(elements));
044      }
045    
046      /**
047       * Returns any duplicate elements from the given collection.
048       * @param <T> the generic type of the given collection.
049       * @param c the given collection that might have duplicate elements.
050       * @return a collection containing the duplicate elements of the given one. If no duplicates are found, an empty
051       *         collection is returned.
052       */
053      public static <T> Collection<T> duplicatesFrom(Collection<T> c) {
054        Set<T> duplicates = new HashSet<T>();
055        if (isEmpty(c)) return duplicates;
056        Set<T> onlyOne = new HashSet<T>();
057        for (T e : c) {
058          if (onlyOne.contains(e)) {
059            duplicates.add(e);
060            continue;
061          }
062          onlyOne.add(e);
063        }
064        return duplicates;
065      }
066    
067      /**
068       * Returns <code>true</code> if the given collection is <code>null</code> or empty.
069       * @param c the collection to check.
070       * @return <code>true</code> if the given collection is <code>null</code> or empty, otherwise <code>false</code>.
071       */
072      public static boolean isEmpty(Collection<?> c) {
073        return c == null || c.isEmpty();
074      }
075    
076      private Collections() {}
077    
078      public static <T> List<T> filter(Collection<?> target, CollectionFilter<T> filter) {
079        return filter.filter(target);
080      }
081    
082      /**
083       * Returns the <code>String</code> representation of the given collection, or <code>null</code> if the given
084       * collection is <code>null</code>.
085       * @param c the collection to format.
086       * @return the <code>String</code> representation of the given collection.
087       */
088      public static String format(Collection<?> c) {
089        if (c == null) return null;
090        Iterator<?> i = c.iterator();
091        if (!i.hasNext()) return "[]";
092        StringBuilder b = new StringBuilder();
093        b.append('[');
094        for (;;) {
095          Object e = i.next();
096          b.append(e == c ? "(this Collection)" : quote(e));
097          if (!i.hasNext()) return b.append(']').toString();
098          b.append(", ");
099        }
100      }
101    
102      /**
103       * Returns a new collection composed of the non null elements of the given collection.
104       * <p>
105       * Returns an empty collection if given collection has only null elements, and null if given collection is null.
106       * 
107       * @param collection Collection we want to extract non null elements
108       * @return A new collection composed of the non null elements of the given collection
109       */
110      public static Collection<Object> nonNullElements(Collection<?> collection) {
111        if (collection == null) { return null; }
112        Collection<Object> filteredCollection = new ArrayList<Object>();
113        for (Object object : collection) {
114          if (object != null) {
115            filteredCollection.add(object);
116          }
117        }
118        return filteredCollection;
119      }
120    
121      /**
122       * Returns a new list composed of the non null elements of the given list.
123       * <p>
124       * Returns an empty list if given list has only null elements, and null if given list is null.
125       * 
126       * @param list List we want to extract non null elements
127       * @return A new list composed of the non null elements of the given list
128       */
129      public static List<Object> nonNullElements(List<?> list) {
130        if (list == null) { return null; }
131        // call nonNullElements(Collection<?> collection) to avoid code duplication
132        Collection<?> collection = list;
133        return new ArrayList<Object>(nonNullElements(collection));
134      }
135    
136      /**
137       * Returns true if the given collection has only null elements, false otherwise.
138       * <p>
139       * If given collection is empty, returns true.
140       * 
141       * @param collection the given collection, <b>must not be null</b>.
142       * @return True if the given collection has only null elements or is empty, false otherwise
143       * @throws NullPointerException if the given collection is null
144       */
145      public static boolean hasOnlyNullElements(Collection<?> collection) {
146        for (Object element : collection) {
147          if (element != null) { return false; }
148        }
149        return true;
150      }
151    
152    }