Coverage Report - org.webslinger.collections.CollectionUtil
 
Classes in this File Line Coverage Branch Coverage Complexity
CollectionUtil
42%
70/167
48%
10/21
0
CollectionUtil$Convertor
N/A
N/A
0
CollectionUtil$StringConvertor
33%
1/3
N/A
0
 
 1  
 package org.webslinger.collections;
 2  
 
 3  
 import java.util.Arrays;
 4  
 import java.util.ArrayList;
 5  
 import java.util.Collection;
 6  
 import java.util.Enumeration;
 7  
 import java.util.HashMap;
 8  
 import java.util.Iterator;
 9  
 import java.util.ListIterator;
 10  
 import java.util.List;
 11  
 import java.util.Map;
 12  
 import java.util.Set;
 13  
 import java.util.NoSuchElementException;
 14  
 import java.util.StringTokenizer;
 15  
 import java.util.concurrent.atomic.AtomicReference;
 16  
 
 17  
 import org.apache.commons.lang.StringUtils;
 18  
 import org.apache.commons.collections.Transformer;
 19  
 import org.apache.commons.collections.iterators.EnumerationIterator;
 20  
 
 21  
 /**
 22  
  * This class contains various utility methods for manipulating various
 23  
  * collection type objects.
 24  
  * @author Adam Heath <a href="mailto:doogie@brainfood.com">doogie@brainfood.com</a>
 25  
  */
 26  0
 public final class CollectionUtil {
 27  
     public static final String NESTED_CONTAINER_SEPARATORS = "./";
 28  
 
 29  
     /**
 30  
      * Splits <code>key</code> into parts specified by
 31  
      * {@link #NESTED_CONTAINER_SEPARATORS}, creates intervening HashMap
 32  
      * containers, then adds <code>item</code> * into the array at the
 33  
      * final leaf.  This method just calls {@link
 34  
      * #push(Map, String, String, Object) push(container, key,
 35  
      * NESTED_CONTAINER_SEPARATORS, item)}.
 36  
      * @param container Where to start the push.
 37  
      * @param key The location to place the new item.
 38  
      * @param item The item to push.
 39  
      */
 40  
     public static void push(Map<String, Object> container, String key, Object item) {
 41  5
         push(container, key, NESTED_CONTAINER_SEPARATORS, item);
 42  5
     }
 43  
 
 44  
     /**
 45  
      * Splits <code>key</code> into parts specified by
 46  
      * <code>separators</code>, creates intervening HashMap containers,
 47  
      * then adds <code>item</code> into the array at the final leaf.
 48  
      * @param container Where to start the push.
 49  
      * @param key The location to place the new item.
 50  
      * @param separators The characters used to split the <code>key
 51  
      * </code> with.
 52  
      * @param item The item to push.
 53  
      */
 54  
     public static void push(Map<String, Object> container, String key, String separators, Object item) {
 55  5
         push(container, new StringTokenizer(key, separators), item);
 56  5
     }
 57  
 
 58  
     public static void push(Map<String, Object> container, StringTokenizer st, Object item) {
 59  10
         String key = st.nextToken();
 60  10
         if (st.hasMoreTokens()) {
 61  
             Map<String, Object> nextContainer;
 62  5
             synchronized (container) {
 63  5
                 nextContainer = (Map<String, Object>) container.get(key);
 64  5
                 if (nextContainer == null) {
 65  2
                     nextContainer = new HashMap<String, Object>();
 66  2
                     container.put(key, nextContainer);
 67  
                 }
 68  5
             }
 69  5
             push(nextContainer, st, item);
 70  5
             return;
 71  
         }
 72  
         Collection<Object> col;
 73  5
         synchronized (container) {
 74  5
             col = (Collection<Object>) container.get(key);
 75  5
             if (col == null) {
 76  3
                 col = new ArrayList<Object>();
 77  3
                 container.put(key, col);
 78  
             }
 79  5
         }
 80  5
         synchronized (col) {
 81  5
             col.add(item);
 82  5
         }
 83  5
     }
 84  
 
 85  
     public static Object pop(Map<String, Object> container, String key) {
 86  0
         return pop(container, key, NESTED_CONTAINER_SEPARATORS);
 87  
     }
 88  
 
 89  
     public static Object pop(Map<String, Object> container, String key, String separators) {
 90  0
         return pop(container, new StringTokenizer(key, separators));
 91  
     }
 92  
 
 93  
     public static Object pop(Map<String, Object> container, StringTokenizer st) {
 94  0
         String key = st.nextToken();
 95  0
         if (st.hasMoreTokens()) {
 96  0
             Map<String, Object> nextContainer = (Map<String, Object>) container.get(key);
 97  0
             synchronized (container) {
 98  0
                 nextContainer = (Map<String, Object>) container.get(key);
 99  0
                 if (nextContainer == null) {
 100  0
                     nextContainer = new HashMap<String, Object>();
 101  0
                     container.put(key, nextContainer);
 102  
                 }
 103  0
             }
 104  0
             return pop(nextContainer, st);
 105  
         }
 106  
         Collection<Object> col;
 107  0
         synchronized (container) {
 108  0
             col = (Collection<Object>) container.get(key);
 109  0
             if (col == null) return null;
 110  0
             synchronized (col) {
 111  0
                 Iterator<Object> it = col.iterator();
 112  
                 try {
 113  0
                     if (it.hasNext()) return it.next();
 114  0
                     return null;
 115  
                 } finally {
 116  0
                     if (!it.hasNext()) container.remove(key);
 117  
                 }
 118  0
             }
 119  0
         }
 120  
     }
 121  
 
 122  
     public static void set(Map<String, Object> container, String key, Object item) {
 123  0
         set(container, key, NESTED_CONTAINER_SEPARATORS, item);
 124  0
     }
 125  
 
 126  
     public static void set(Map<String, Object> container, String key, String separators, Object item) {
 127  5
         set(container, new StringTokenizer(key, separators), item);
 128  5
     }
 129  
 
 130  
     public static void set(Map<String, Object> container, StringTokenizer st, Object item) {
 131  15
         String key = st.nextToken();
 132  15
         if (st.hasMoreTokens()) {
 133  
             Map<String, Object> nextContainer;
 134  10
             synchronized (container) {
 135  10
                 nextContainer = (Map<String, Object>) container.get(key);
 136  10
                 if (nextContainer == null) {
 137  5
                     nextContainer = new HashMap<String, Object>();
 138  5
                     container.put(key, nextContainer);
 139  
                 }
 140  10
             }
 141  10
             set(nextContainer, st, item);
 142  10
             return;
 143  
         }
 144  5
         synchronized (container) {
 145  5
             container.put(key, item);
 146  5
         }
 147  5
     }
 148  
 
 149  
     public static void remove(Map<String, Object> container, String key) {
 150  0
         remove(container, key, NESTED_CONTAINER_SEPARATORS);
 151  0
     }
 152  
 
 153  
     public static void remove(Map<String, Object> container, String key, String separators) {
 154  0
         remove(container, new StringTokenizer(key, separators));
 155  0
     }
 156  
 
 157  
     public static void remove(Map<String, Object> container, StringTokenizer st) {
 158  0
         String key = st.nextToken();
 159  0
         if (st.hasMoreTokens()) {
 160  
             Map<String, Object> nextContainer;
 161  0
             synchronized (container) {
 162  0
                 nextContainer = (Map<String, Object>) container.get(key);
 163  0
                 if (nextContainer == null) {
 164  0
                     nextContainer = new HashMap<String, Object>();
 165  0
                     container.put(key, nextContainer);
 166  
                 }
 167  0
             }
 168  0
             remove(nextContainer, st);
 169  0
             return;
 170  
         }
 171  0
         synchronized (container) {
 172  0
             container.remove(key);
 173  0
         }
 174  0
     }
 175  
 
 176  
     public static Object get(Map<String, Object> container, String key) {
 177  0
         return get(container, key, NESTED_CONTAINER_SEPARATORS);
 178  
     }
 179  
 
 180  
     public static Object get(Map<String, Object> container, String key, String separators) {
 181  0
         return get(container, new StringTokenizer(key, separators));
 182  
     }
 183  
 
 184  
     public static Object get(Map<String, Object> container, StringTokenizer st) {
 185  0
         String key = st.nextToken();
 186  0
         if (st.hasMoreTokens()) {
 187  
             Map<String, Object> nextContainer;
 188  0
             synchronized (container) {
 189  0
                 nextContainer = (Map<String, Object>) container.get(key);
 190  0
                 if (nextContainer == null) {
 191  0
                     nextContainer = new HashMap<String, Object>();
 192  0
                     container.put(key, nextContainer);
 193  
                 }
 194  0
             }
 195  0
             return get(nextContainer, st);
 196  
         }
 197  0
         synchronized (container) {
 198  0
             return container.get(key);
 199  0
         }
 200  
     }
 201  
 
 202  
     public static ListIterator<String> parse(String name, String separator) {
 203  0
         StringTokenizer st = new StringTokenizer(name, separator);
 204  0
         List<String> parts = new ArrayList<String>();
 205  
         try {
 206  
             while (true) {
 207  0
                 parts.add(st.nextToken());
 208  
             }
 209  0
         } catch (NoSuchElementException e) {
 210  
             // ignore
 211  
         }
 212  0
         return parts.listIterator();
 213  
     }
 214  
 
 215  
     public static <T> Collection<T> addAll(Collection<T> col, T[] array) {
 216  0
         org.apache.commons.collections.CollectionUtils.addAll(col, array);
 217  0
         return col;
 218  
     }
 219  
 
 220  
     public static <T> Collection<T> addAll(Collection<T> col, Enumeration<T> en) {
 221  0
         org.apache.commons.collections.CollectionUtils.addAll(col, en);
 222  0
         return col;
 223  
     }
 224  
 
 225  
     public static <T> Collection<T> addAll(Collection<T> col, Iterator<T> it) {
 226  0
         org.apache.commons.collections.CollectionUtils.addAll(col, it);
 227  0
         return col;
 228  
     }
 229  
 
 230  
     public static String join(String[] items, String sep) {
 231  0
         return StringUtils.join(items, sep);
 232  
     }
 233  
 
 234  
     public static String join(Collection<? extends Object> items, String sep) {
 235  861
         return StringUtils.join(items, sep);
 236  
     }
 237  
 
 238  
     public static String join(Iterator<? extends Object> it, String sep) {
 239  0
         return StringUtils.join(it, sep);
 240  
     }
 241  
 
 242  
     public static String join(Enumeration<? extends Object> en, String sep) {
 243  0
         return StringUtils.join(new EnumerationIterator(en), sep);
 244  
     }
 245  
 
 246  
     public static List<String> split(String str, String regex) {
 247  0
         String[] parts = str.split(regex);
 248  0
         return Arrays.asList(parts);
 249  
     }
 250  
 
 251  
     public static List<String> split(String str, String regex, int limit) {
 252  0
         String[] parts = str.split(regex, limit);
 253  0
         return Arrays.asList(parts);
 254  
     }
 255  
 
 256  
     public static final <R, T> Collection<R> convert(Collection<T> names, Convertor<R, T> convertor) {
 257  0
         return convert(names.iterator(), convertor);
 258  
     }
 259  
 
 260  
     public static final <R, T> Collection<R> convert(Iterator<T> it, Convertor<R, T> convertor) {
 261  0
         List<R> converted = new ArrayList<R>();
 262  0
         while (it.hasNext()) {
 263  0
             converted.add(convertor.convert(it.next()));
 264  
         }
 265  0
         return converted;
 266  
     }
 267  
 
 268  
     public interface Convertor<R, T> {
 269  
         R convert(T value);
 270  
     }
 271  
 
 272  2
     public static abstract class StringConvertor implements Convertor<String, Object>, Transformer {
 273  
         public Object transform(Object value) {
 274  0
             return convertString((String) value);
 275  
         }
 276  
 
 277  
         public String convert(Object value) {
 278  0
             return convertString((String) value);
 279  
         }
 280  
 
 281  
         public abstract String convertString(String value);
 282  
     }
 283  
 
 284  
     public static Map<String, Object> expandMap(Map<String, Object> inMap) {
 285  1
         return expandMap(inMap, new HashMap<String, Object>());
 286  
     }
 287  
 
 288  
     public static Map<String, Object> expandMap(Map<String, Object> inMap, Map<String, Object> returnMap) {
 289  1
         for (Map.Entry<String, Object> entry: inMap.entrySet()) {
 290  5
             String key = entry.getKey();
 291  5
             Object value = entry.getValue();
 292  5
             set(returnMap, key, ".", value instanceof String[] ? ((String[]) value)[0] : value);
 293  5
         }
 294  1
         return returnMap;
 295  
     }
 296  
 
 297  
     public static Map<String, Object> flattenMap(Map<String, Object> inMap) {
 298  1
         return flattenMap("", inMap);
 299  
     }
 300  
 
 301  
     public static Map<String, Object> flattenMap(String prefix, Map<String, Object> inMap) {
 302  1
         HashMap<String, Object> returnMap = new HashMap<String, Object>();
 303  1
         StringBuilder sb = new StringBuilder();
 304  1
         sb.append(prefix);
 305  1
         flattenMap(returnMap, inMap, sb);
 306  1
         return returnMap;
 307  
     }
 308  
 
 309  
     private static void flattenMap(Map<String, Object> returnMap, Map<String, Object> inMap, StringBuilder sb) {
 310  5
         int length = sb.length();
 311  5
         synchronized (inMap) {
 312  5
             for (Map.Entry<String, Object> entry: inMap.entrySet()) {
 313  8
                 sb.append(entry.getKey()).append('.');
 314  8
                 Object value = entry.getValue();
 315  8
                 if (value instanceof Map) {
 316  4
                     flattenMap(returnMap, (Map<String, Object>) value, sb);
 317  
                 } else {
 318  4
                     if (sb.charAt(sb.length() - 1) == '.') sb.setLength(sb.length() - 1);
 319  4
                     returnMap.put(sb.toString(), value);
 320  
                 }
 321  8
                 sb.setLength(length);
 322  8
             }
 323  5
         }
 324  5
     }
 325  
 
 326  
     public static Map toMap(Object... args) {
 327  0
         HashMap map = new HashMap(args.length / 2);
 328  0
         for (int i = 0; i < args.length - 1; ) {
 329  0
             Object key = args[i++];
 330  0
             Object value = args[i++];
 331  0
             map.put(key, value);
 332  0
         }
 333  0
         return map;
 334  
     }
 335  
 
 336  
     public static <K, V> Map<? extends K, ? extends V> toMap(K k1, V v1) {
 337  1
         HashMap<K, V> map = new HashMap<K, V>(1);
 338  1
         map.put(k1, v1);
 339  1
         return map;
 340  
     }
 341  
 
 342  
     public static <K, V> Map<? extends K, ? extends V> toMap(K k1, V v1, K k2, V v2) {
 343  0
         HashMap<K, V> map = new HashMap<K, V>(2);
 344  0
         map.put(k1, v1);
 345  0
         map.put(k2, v2);
 346  0
         return map;
 347  
     }
 348  
 
 349  
     public static <K, V> Map<? extends K, ? extends V> toMap(K k1, V v1, K k2, V v2, K k3, V v3) {
 350  0
         HashMap<K, V> map = new HashMap<K, V>(3);
 351  0
         map.put(k1, v1);
 352  0
         map.put(k2, v2);
 353  0
         map.put(k3, v3);
 354  0
         return map;
 355  
     }
 356  
 }
 357