Coverage Report - org.kuali.rice.core.api.util.CollectionUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
CollectionUtils
59%
22/37
44%
15/34
2.688
CollectionUtils$1
N/A
N/A
2.688
CollectionUtils$IterableEnumeration
0%
0/7
0%
0/2
2.688
CollectionUtils$IterableEnumeration$1
0%
0/4
N/A
2.688
CollectionUtils$IterableIterator
0%
0/7
0%
0/2
2.688
 
 1  
 /*
 2  
  * Copyright 2007-2010 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.core.api.util;
 17  
 
 18  
 import java.lang.reflect.Field;
 19  
 import java.util.Collection;
 20  
 import java.util.Collections;
 21  
 import java.util.Enumeration;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.Set;
 26  
 
 27  
 /**
 28  
  * Yet another utility class to help work with Collections. This class contains helper methods not
 29  
  * found in any of the Collection utilities rice currently uses.
 30  
  * 
 31  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 32  
  * 
 33  
  */
 34  
 public final class CollectionUtils {
 35  
 
 36  
     /** do not call. */
 37  0
     private CollectionUtils() {
 38  0
         throw new UnsupportedOperationException("do not call");
 39  
     }
 40  
 
 41  
     /**
 42  
      * Performs a "brute force" comparison of collections by testing whether the collections contain
 43  
      * each other. This circumvents any particular uniqueness or ordering constraints on the
 44  
      * collections (for instance, lists that are unordered but contain the same elements, where a
 45  
      * hashset would not suffice for comparison purposes because it enforces element uniqueness)
 46  
      */
 47  
     public static boolean collectionsEquivalent(Collection<?> a, Collection<?> b) {
 48  0
         if (a == null && b == null) {
 49  0
             return true;
 50  
         }
 51  0
         if (a == null ^ b == null) {
 52  0
             return false;
 53  
         }
 54  0
         return a.containsAll(b) && b.containsAll(a);
 55  
     }
 56  
 
 57  
     /**
 58  
      * Creates an Iterable view of a Iterator. This allows Iterators to be used in a foreach loop.
 59  
      * 
 60  
      * <pre>
 61  
          * {@code
 62  
          *   Iterator<String> i ...
 63  
          * 
 64  
          *   for(String s : CollectionUtils.toIterable(i)) [
 65  
          *     System.out.println("i love for each " + s);        
 66  
          *   }
 67  
          * }
 68  
          * </pre>
 69  
      * 
 70  
      * @param <T> the type of the Iterable
 71  
      * @param i the iterator to wrap
 72  
      * @return the iterable
 73  
      */
 74  
     public static <T> Iterable<T> toIterable(Iterator<T> i) {
 75  0
         return new IterableIterator<T>(i);
 76  
     }
 77  
 
 78  
     /**
 79  
      * Creates an Iterable view of a Enumeration. This allows Enumerations to be used in a foreach
 80  
      * loop.
 81  
      * 
 82  
      * <pre>
 83  
          * {@code
 84  
          *   Enumeration<String> e ...
 85  
          * 
 86  
          *   for(String s : CollectionUtils.toIterable(e)) [
 87  
          *     System.out.println("i love for each " + s);        
 88  
          *   }
 89  
          * }
 90  
          * </pre>
 91  
      * 
 92  
      * @param <T> the type of the Iterable
 93  
      * @param e the enumeration to wrap
 94  
      * @return the iterable
 95  
      */
 96  
     public static <T> Iterable<T> toIterable(Enumeration<T> e) {
 97  0
         return new IterableEnumeration<T>(e);
 98  
     }
 99  
 
 100  
     /**
 101  
      * Functions as per {@link Collections#unmodifiableList(Collection)} with the exception that if the
 102  
      * given collection is null, this method will return an unmodifiable empty collection as per
 103  
      * {@link Collections#emptyList()}.
 104  
      *
 105  
      * @param collection the collection for which an unmodifiable view is to be returned
 106  
      * @return an unmodifiable view of the specified collection, or an unmodifiable empty collection if the
 107  
      *         given collection is null
 108  
      */
 109  
     public static <T> Collection<T> unmodifiableCollectionNullSafe(Collection<? extends T> collection) {
 110  0
         if (collection == null) {
 111  0
             return Collections.emptyList();
 112  
         }
 113  0
         return Collections.unmodifiableCollection(collection);
 114  
     }
 115  
 
 116  
     /**
 117  
      * Functions as per {@link Collections#unmodifiableList(List)} with the exception that if the
 118  
      * given list is null, this method will return an unmodifiable empty list as per
 119  
      * {@link Collections#emptyList()}.
 120  
      * 
 121  
      * @param list the list for which an unmodifiable view is to be returned
 122  
      * @return an unmodifiable view of the specified list, or an unmodifiable empty list if the
 123  
      *         given list is null
 124  
      */
 125  
     public static <T> List<T> unmodifiableListNullSafe(List<? extends T> list) {
 126  212
         if (list == null) {
 127  183
             return Collections.emptyList();
 128  
         }
 129  29
         return Collections.unmodifiableList(list);
 130  
     }
 131  
 
 132  
     /**
 133  
      * Functions as per {@link Collections#unmodifiableSet(Set)} with the exception that if the
 134  
      * given set is null, this method will return an unmodifiable empty set as per
 135  
      * {@link Collections#emptySet()}.
 136  
      * 
 137  
      * @param set the set for which an unmodifiable view is to be returned
 138  
      * @return an unmodifiable view of the specified set, or an unmodifiable empty set if the given
 139  
      *         set is null
 140  
      */
 141  
     public static <T> Set<T> unmodifiableSetNullSafe(Set<? extends T> set) {
 142  22
         if (set == null) {
 143  0
             return Collections.emptySet();
 144  
         }
 145  22
         return Collections.unmodifiableSet(set);
 146  
     }
 147  
 
 148  
     /**
 149  
      * Functions as per {@link Collections#unmodifiableMap(Map)} with the exception that if the
 150  
      * given map is null, this method will return an unmodifiable empty map as per
 151  
      * {@link Collections#emptyMap()}.
 152  
      * 
 153  
      * @param map the map for which an unmodifiable view is to be returned
 154  
      * @return an unmodifiable view of the specified set, or an unmodifiable empty set if the given
 155  
      *         set is null
 156  
      */
 157  
     public static <K, V> Map<K, V> unmodifiableMapNullSafe(Map<? extends K, ? extends V> map) {
 158  22
         if (map == null) {
 159  3
             return Collections.emptyMap();
 160  
         }
 161  19
         return Collections.unmodifiableMap(map);
 162  
     }
 163  
 
 164  
     /**
 165  
      * This method will iterate over all the fields on an object searching for declared fields defined as
 166  
      * Collection, List, Set, Map type.  If those fields are null they will be set to empty unmodifiable
 167  
      * instances.  If those fields are not null then it will force them to be unmodifiable.
 168  
      *
 169  
      * This method does not handle nested types.
 170  
      *
 171  
      * @param o the object to modify.  a null object will do nothing.
 172  
      */
 173  
     public static void makeUnmodifiableAndNullSafe(Object o) throws IllegalAccessException {
 174  173
         if (o == null) {
 175  0
             return;
 176  
         }
 177  
 
 178  173
         Class<?> targetClass = o.getClass();
 179  894
         for (Field f : targetClass.getDeclaredFields()) {
 180  721
             f.setAccessible(true);
 181  
             try {
 182  721
                 if (f.getType().isAssignableFrom(List.class)) {
 183  212
                     f.set(o, unmodifiableListNullSafe((List<?>) f.get(o)));
 184  509
                 } else if (f.getType().isAssignableFrom(Set.class)) {
 185  22
                     f.set(o, unmodifiableSetNullSafe((Set<?>) f.get(o)));
 186  487
                 } else if (f.getType().isAssignableFrom(Collection.class)) {
 187  0
                     f.set(o, unmodifiableCollectionNullSafe((Collection<?>) f.get(o)));
 188  487
                 } else if (f.getType().isAssignableFrom(Map.class)) {
 189  22
                     f.set(o, unmodifiableMapNullSafe((Map<?, ?>) f.get(o)));
 190  
                 }
 191  
             } finally {
 192  721
                 f.setAccessible(false);
 193  721
             }
 194  
         }
 195  173
     }
 196  
 
 197  
     /**
 198  
      * An adapter from an Enumeration to Iterable.
 199  
      * 
 200  
      * @author Kuali Rice Team (rice.collab@kuali.org)
 201  
      * 
 202  
      * @param <T> the type of Enumeration and Iterable
 203  
      */
 204  0
     private static class IterableEnumeration<T> implements Iterable<T> {
 205  
         private final Enumeration<T> e;
 206  
 
 207  0
         private IterableEnumeration(final Enumeration<T> e) {
 208  0
             if (e == null) {
 209  0
                 throw new IllegalArgumentException("the enumeration is null");
 210  
             }
 211  
 
 212  0
             this.e = e;
 213  0
         }
 214  
 
 215  
         @Override
 216  
         public Iterator<T> iterator() {
 217  0
             return new Iterator<T>() {
 218  
                 @Override
 219  
                 public boolean hasNext() {
 220  0
                     return e.hasMoreElements();
 221  
                 }
 222  
 
 223  
                 @Override
 224  
                 public T next() {
 225  0
                     return e.nextElement();
 226  
                 }
 227  
 
 228  
                 @Override
 229  
                 public void remove() {
 230  0
                     throw new UnsupportedOperationException("this iterator does not support remove");
 231  
                 }
 232  
             };
 233  
         }
 234  
     }
 235  
 
 236  
     /**
 237  
      * An adapter from an Iterator to Iterable.
 238  
      * 
 239  
      * @author Kuali Rice Team (rice.collab@kuali.org)
 240  
      * 
 241  
      * @param <T> the type of Iterator and Iterable
 242  
      */
 243  0
     private static class IterableIterator<T> implements Iterable<T> {
 244  
         private final Iterator<T> i;
 245  
 
 246  0
         private IterableIterator(final Iterator<T> i) {
 247  0
             if (i == null) {
 248  0
                 throw new IllegalArgumentException("the iterator is null");
 249  
             }
 250  
 
 251  0
             this.i = i;
 252  0
         }
 253  
 
 254  
         @Override
 255  
         public Iterator<T> iterator() {
 256  0
             return i;
 257  
         }
 258  
     }
 259  
 }