1
2
3
4 package net.sourceforge.pmd.util;
5
6 import java.lang.reflect.Array;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16
17
18
19
20
21
22
23 public final class CollectionUtil {
24
25 @SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
26 public static final TypeMap COLLECTION_INTERFACES_BY_NAMES = new TypeMap(new Class[] { java.util.List.class,
27 java.util.Collection.class, java.util.Map.class, java.util.Set.class, });
28
29 @SuppressWarnings({"PMD.LooseCoupling", "PMD.UnnecessaryFullyQualifiedName"})
30 public static final TypeMap COLLECTION_CLASSES_BY_NAMES = new TypeMap(new Class[] { java.util.ArrayList.class,
31 java.util.LinkedList.class, java.util.Vector.class, java.util.HashMap.class, java.util.LinkedHashMap.class,
32 java.util.TreeMap.class, java.util.TreeSet.class, java.util.HashSet.class, java.util.LinkedHashSet.class,
33 java.util.Hashtable.class});
34
35 private CollectionUtil() {
36 };
37
38
39
40
41
42
43
44
45
46 public static int addWithoutDuplicates(Collection<String> source, Collection<String> target) {
47
48 int added = 0;
49
50 for (String item : source) {
51 if (target.contains(item)) continue;
52 target.add(item);
53 added++;
54 }
55
56 return added;
57 }
58
59
60
61
62
63
64
65 public static Class<?> getCollectionTypeFor(String shortName) {
66 Class<?> cls = COLLECTION_CLASSES_BY_NAMES.typeFor(shortName);
67 if (cls != null) {
68 return cls;
69 }
70
71 return COLLECTION_INTERFACES_BY_NAMES.typeFor(shortName);
72 }
73
74
75
76
77
78
79
80
81
82 public static boolean isCollectionType(String typeName, boolean includeInterfaces) {
83
84 if (COLLECTION_CLASSES_BY_NAMES.contains(typeName)) {
85 return true;
86 }
87
88 return includeInterfaces && COLLECTION_INTERFACES_BY_NAMES.contains(typeName);
89 }
90
91
92
93
94
95
96
97
98
99 public static boolean isCollectionType(Class<?> clazzType, boolean includeInterfaces) {
100
101 if (COLLECTION_CLASSES_BY_NAMES.contains(clazzType)) {
102 return true;
103 }
104
105 return includeInterfaces && COLLECTION_INTERFACES_BY_NAMES.contains(clazzType);
106 }
107
108
109
110
111
112
113
114 public static <T> Set<T> asSet(T[] items) {
115
116 return new HashSet<T>(Arrays.asList(items));
117 }
118
119
120
121
122
123
124
125
126
127 public static <K, V> Map<K, V> mapFrom(K[] keys, V[] values) {
128 if (keys.length != values.length) {
129 throw new RuntimeException("mapFrom keys and values arrays have different sizes");
130 }
131 Map<K, V> map = new HashMap<K, V>(keys.length);
132 for (int i = 0; i < keys.length; i++) {
133 map.put(keys[i], values[i]);
134 }
135 return map;
136 }
137
138
139
140
141
142
143
144 public static <K, V> Map<V, K> invertedMapFrom(Map<K, V> source) {
145 Map<V, K> map = new HashMap<V, K>(source.size());
146 for (Map.Entry<K, V> entry : source.entrySet()) {
147 map.put(entry.getValue(), entry.getKey());
148 }
149 return map;
150 }
151
152
153
154
155
156
157
158
159
160 public static boolean arraysAreEqual(Object value, Object otherValue) {
161 if (value instanceof Object[]) {
162 if (otherValue instanceof Object[]) {
163 return valuesAreTransitivelyEqual((Object[]) value, (Object[]) otherValue);
164 }
165 return false;
166 }
167 return false;
168 }
169
170
171
172
173
174
175
176
177
178 public static boolean valuesAreTransitivelyEqual(Object[] thisArray, Object[] thatArray) {
179 if (thisArray == thatArray) {
180 return true;
181 }
182 if (thisArray == null || thatArray == null) {
183 return false;
184 }
185 if (thisArray.length != thatArray.length) {
186 return false;
187 }
188 for (int i = 0; i < thisArray.length; i++) {
189 if (!areEqual(thisArray[i], thatArray[i])) {
190 return false;
191 }
192 }
193 return true;
194 }
195
196
197
198
199
200
201
202
203 @SuppressWarnings("PMD.CompareObjectsWithEquals")
204 public static boolean areEqual(Object value, Object otherValue) {
205 if (value == otherValue) {
206 return true;
207 }
208 if (value == null) {
209 return false;
210 }
211 if (otherValue == null) {
212 return false;
213 }
214
215 if (value.getClass().getComponentType() != null) {
216 return arraysAreEqual(value, otherValue);
217 }
218 return value.equals(otherValue);
219 }
220
221
222
223
224
225
226 public static boolean isEmpty(Object[] items) {
227 return items == null || items.length == 0;
228 }
229
230
231
232
233
234
235
236
237 public static boolean isNotEmpty(Object[] items) {
238 return !isEmpty(items);
239 }
240
241
242
243
244
245
246
247
248
249
250
251 public static <T> boolean areSemanticEquals(T[] a, T[] b) {
252
253 if (a == null) { return isEmpty(b); }
254 if (b == null) { return isEmpty(a); }
255
256 if (a.length != b.length) return false;
257
258 for (int i=0; i<a.length; i++) {
259 if (!areEqual(a[i], b[i])) return false;
260 }
261
262 return true;
263 }
264
265
266
267
268
269
270
271
272
273
274
275 public static <T> T[] addWithoutDuplicates(T[] values, T newValue) {
276
277 for (T value : values) {
278 if (value.equals(newValue)) {
279 return values;
280 }
281 }
282
283 T[] largerOne = (T[])Array.newInstance(values.getClass().getComponentType(), values.length + 1);
284 System.arraycopy(values, 0, largerOne, 0, values.length);
285 largerOne[values.length] = newValue;
286 return largerOne;
287 }
288
289
290
291
292
293
294
295
296
297 public static <T> T[] addWithoutDuplicates(T[] values, T[] newValues) {
298
299 Set<T> originals = new HashSet<T>(values.length);
300 for (T value : values) { originals.add(value); }
301 List<T> newOnes = new ArrayList<T>(newValues.length);
302 for (T value : newValues) {
303 if (originals.contains(value)) { continue; }
304 newOnes.add(value);
305 }
306
307 T[] largerOne = (T[])Array.newInstance(values.getClass().getComponentType(), values.length + newOnes.size());
308 System.arraycopy(values, 0, largerOne, 0, values.length);
309 for (int i=values.length; i<largerOne.length; i++) { largerOne[i] = newOnes.get(i-values.length); }
310 return largerOne;
311 }
312 }