View Javadoc

1   package net.sourceforge.pmd.util;
2   
3   import java.util.HashMap;
4   import java.util.HashSet;
5   import java.util.Iterator;
6   import java.util.Map;
7   import java.util.Set;
8   import java.util.Map.Entry;
9   
10  /***
11   * Generic collection and array-related utility functions.
12   * 
13   * @author Brian Remedios
14   * @version $Revision$
15   */
16  public class CollectionUtil {
17  
18  	public static final TypeMap collectionInterfacesByNames = new TypeMap( new Class[] {
19  		java.util.List.class,
20  		java.util.Collection.class,
21  		java.util.Map.class,
22  		java.util.Set.class,
23  		});
24  		
25  	public static final TypeMap collectionClassesByNames = new TypeMap( new Class[] {
26  		java.util.ArrayList.class,
27  		java.util.LinkedList.class,
28  		java.util.Vector.class,
29  		java.util.HashMap.class,
30  		java.util.LinkedHashMap.class,
31  		java.util.TreeMap.class,
32  		java.util.TreeSet.class,
33  		java.util.HashSet.class,
34  		java.util.LinkedHashSet.class
35  		});
36  	
37  	private CollectionUtil() {};
38  	
39  	/***
40  	 * Returns the collection type if we recognize it by its short name.
41  	 * 
42  	 * @param shortName String
43  	 * @return Class
44  	 */
45  	public static Class getCollectionTypeFor(String shortName) {
46  		Class cls = collectionClassesByNames.typeFor(shortName);
47  		if (cls != null) return cls;
48  		
49  		return collectionInterfacesByNames.typeFor(shortName);
50  	}
51  	
52  	/***
53  	 * Return whether we can identify the typeName as a java.util collection class
54  	 * or interface as specified.
55  	 * 
56  	 * @param typeName String
57  	 * @param includeInterfaces boolean
58  	 * @return boolean
59  	 */
60  	public static boolean isCollectionType(String typeName, boolean includeInterfaces) {
61  		
62  		if (collectionClassesByNames.contains(typeName)) return true;
63  
64  		return includeInterfaces && collectionInterfacesByNames.contains(typeName);
65  	}
66  	
67      /***
68       * Return whether we can identify the typeName as a java.util collection class
69       * or interface as specified.
70       * 
71       * @param clazzType Class
72       * @param includeInterfaces boolean
73       * @return boolean
74       */
75      public static boolean isCollectionType(Class clazzType, boolean includeInterfaces) {
76  
77          if (collectionClassesByNames.contains(clazzType)) {
78              return true;
79          }
80  
81          return includeInterfaces && collectionInterfacesByNames.contains(clazzType);
82      }
83  
84      /***
85       * Returns the items as a populated set.
86       * 
87       * @param items Object[]
88       * @return Set
89       */
90      public static Set asSet(Object[] items) {
91      	
92      	Set set = new HashSet(items.length);
93      	for (int i=0; i<items.length; i++) {
94      		set.add(items[i]);
95      	}
96      	return set;
97      }	
98      
99  	/***
100 	 * Creates and returns a map populated with the keyValuesSets where
101 	 * the value held by the tuples are they key and value in that order.
102 	 * 
103 	 * @param keyValueSets Object[][]
104 	 * @return Map
105 	 */
106 	public static Map mapFrom(Object[][] keyValueSets) {
107 		Map map = new HashMap(keyValueSets.length);
108 		for (int i=0; i<keyValueSets.length; i++) {
109 			map.put(keyValueSets[i][0], keyValueSets[i][1]);
110 		}
111 		return map;
112 	}
113 	
114 	/***
115 	 * Returns a map based on the source but with the key & values swapped.
116 	 * 
117 	 * @param source Map
118 	 * @return Map
119 	 */
120 	public static Map invertedMapFrom(Map source) {
121 		Map map = new HashMap(source.size());
122 		Iterator iter = source.entrySet().iterator();
123 		Entry entry;
124 		while (iter.hasNext()) {
125 			entry = (Entry)iter.next();
126 			map.put(entry.getValue(), entry.getKey());
127 		}
128 		return map;
129 	}
130 	
131 	/***
132 	 * Returns true if the objects are array instances and each of their elements compares
133 	 * via equals as well.
134 	 * 
135 	 * @param value Object
136 	 * @param otherValue Object
137 	 * @return boolean
138 	 */
139 	public static final boolean arraysAreEqual(Object value, Object otherValue) {
140 		if (value instanceof Object[]) {
141 			if (otherValue instanceof Object[]) return valuesAreTransitivelyEqual((Object[])value, (Object[])otherValue);
142 			return false;
143 		}
144 		return false;
145 	}
146 	
147 	/***
148 	 * Returns whether the arrays are equal by examining each of their elements, even if they are
149 	 * arrays themselves.
150 	 * 
151 	 * @param thisArray Object[]
152 	 * @param thatArray Object[]
153 	 * @return boolean
154 	 */
155 	public static final boolean valuesAreTransitivelyEqual(Object[] thisArray, Object[] thatArray) {
156 		if (thisArray == thatArray) return true;
157 		if ((thisArray == null) || (thatArray == null)) return false;
158 		if (thisArray.length != thatArray.length) return false;
159 		for (int i = 0; i < thisArray.length; i++) {
160 			if (!areEqual(thisArray[i], thatArray[i])) return false;	// recurse if req'd
161 		}
162 		return true;
163 	}
164 
165 	/***
166 	 * A comprehensive isEqual method that handles nulls and arrays safely.
167 	 * 
168 	 * @param value Object
169 	 * @param otherValue Object
170 	 * @return boolean
171 	 */
172 	public static final boolean areEqual(Object value, Object otherValue) {
173 		if (value == otherValue) return true;
174 		if (value == null) return false;
175 		if (otherValue == null) return false;
176 
177 		if (value.getClass().getComponentType() != null) return arraysAreEqual(value, otherValue);
178 		return value.equals(otherValue);
179 	}
180 }