1 /* 2 * Copyright 2002-2008 the original author or authors. 3 * 4 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 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 17 package org.argeo.osgi.boot.internal.springutil; 18 19 import java.util.Arrays; 20 import java.util.Collection; 21 import java.util.Enumeration; 22 import java.util.Iterator; 23 import java.util.List; 24 import java.util.Map; 25 import java.util.Properties; 26 27 /** 28 * Miscellaneous collection utility methods. 29 * Mainly for internal use within the framework. 30 * 31 * @author Juergen Hoeller 32 * @author Rob Harrop 33 * @since 1.1.3 34 */ 35 @SuppressWarnings({ "rawtypes", "unchecked" }) 36 public abstract class CollectionUtils { 37 38 /** 39 * Return <code>true</code> if the supplied Collection is <code>null</code> 40 * or empty. Otherwise, return <code>false</code>. 41 * @param collection the Collection to check 42 * @return whether the given Collection is empty 43 */ 44 public static boolean isEmpty(Collection collection) { 45 return (collection == null || collection.isEmpty()); 46 } 47 48 /** 49 * Return <code>true</code> if the supplied Map is <code>null</code> 50 * or empty. Otherwise, return <code>false</code>. 51 * @param map the Map to check 52 * @return whether the given Map is empty 53 */ 54 public static boolean isEmpty(Map map) { 55 return (map == null || map.isEmpty()); 56 } 57 58 /** 59 * Convert the supplied array into a List. A primitive array gets 60 * converted into a List of the appropriate wrapper type. 61 * <p>A <code>null</code> source value will be converted to an 62 * empty List. 63 * @param source the (potentially primitive) array 64 * @return the converted List result 65 * @see ObjectUtils#toObjectArray(Object) 66 */ 67 public static List arrayToList(Object source) { 68 return Arrays.asList(ObjectUtils.toObjectArray(source)); 69 } 70 71 /** 72 * Merge the given array into the given Collection. 73 * @param array the array to merge (may be <code>null</code>) 74 * @param collection the target Collection to merge the array into 75 */ 76 public static void mergeArrayIntoCollection(Object array, Collection collection) { 77 if (collection == null) { 78 throw new IllegalArgumentException("Collection must not be null"); 79 } 80 Object[] arr = ObjectUtils.toObjectArray(array); 81 for (int i = 0; i < arr.length; i++) { 82 collection.add(arr[i]); 83 } 84 } 85 86 /** 87 * Merge the given Properties instance into the given Map, 88 * copying all properties (key-value pairs) over. 89 * <p>Uses <code>Properties.propertyNames()</code> to even catch 90 * default properties linked into the original Properties instance. 91 * @param props the Properties instance to merge (may be <code>null</code>) 92 * @param map the target Map to merge the properties into 93 */ 94 public static void mergePropertiesIntoMap(Properties props, Map map) { 95 if (map == null) { 96 throw new IllegalArgumentException("Map must not be null"); 97 } 98 if (props != null) { 99 for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { 100 String key = (String) en.nextElement(); 101 map.put(key, props.getProperty(key)); 102 } 103 } 104 } 105 106 107 /** 108 * Check whether the given Iterator contains the given element. 109 * @param iterator the Iterator to check 110 * @param element the element to look for 111 * @return <code>true</code> if found, <code>false</code> else 112 */ 113 public static boolean contains(Iterator iterator, Object element) { 114 if (iterator != null) { 115 while (iterator.hasNext()) { 116 Object candidate = iterator.next(); 117 if (ObjectUtils.nullSafeEquals(candidate, element)) { 118 return true; 119 } 120 } 121 } 122 return false; 123 } 124 125 /** 126 * Check whether the given Enumeration contains the given element. 127 * @param enumeration the Enumeration to check 128 * @param element the element to look for 129 * @return <code>true</code> if found, <code>false</code> else 130 */ 131 public static boolean contains(Enumeration enumeration, Object element) { 132 if (enumeration != null) { 133 while (enumeration.hasMoreElements()) { 134 Object candidate = enumeration.nextElement(); 135 if (ObjectUtils.nullSafeEquals(candidate, element)) { 136 return true; 137 } 138 } 139 } 140 return false; 141 } 142 143 /** 144 * Check whether the given Collection contains the given element instance. 145 * <p>Enforces the given instance to be present, rather than returning 146 * <code>true</code> for an equal element as well. 147 * @param collection the Collection to check 148 * @param element the element to look for 149 * @return <code>true</code> if found, <code>false</code> else 150 */ 151 public static boolean containsInstance(Collection collection, Object element) { 152 if (collection != null) { 153 for (Iterator it = collection.iterator(); it.hasNext();) { 154 Object candidate = it.next(); 155 if (candidate == element) { 156 return true; 157 } 158 } 159 } 160 return false; 161 } 162 163 /** 164 * Return <code>true</code> if any element in '<code>candidates</code>' is 165 * contained in '<code>source</code>'; otherwise returns <code>false</code>. 166 * @param source the source Collection 167 * @param candidates the candidates to search for 168 * @return whether any of the candidates has been found 169 */ 170 public static boolean containsAny(Collection source, Collection candidates) { 171 if (isEmpty(source) || isEmpty(candidates)) { 172 return false; 173 } 174 for (Iterator it = candidates.iterator(); it.hasNext();) { 175 if (source.contains(it.next())) { 176 return true; 177 } 178 } 179 return false; 180 } 181 182 /** 183 * Return the first element in '<code>candidates</code>' that is contained in 184 * '<code>source</code>'. If no element in '<code>candidates</code>' is present in 185 * '<code>source</code>' returns <code>null</code>. Iteration order is 186 * {@link Collection} implementation specific. 187 * @param source the source Collection 188 * @param candidates the candidates to search for 189 * @return the first present object, or <code>null</code> if not found 190 */ 191 public static Object findFirstMatch(Collection source, Collection candidates) { 192 if (isEmpty(source) || isEmpty(candidates)) { 193 return null; 194 } 195 for (Iterator it = candidates.iterator(); it.hasNext();) { 196 Object candidate = it.next(); 197 if (source.contains(candidate)) { 198 return candidate; 199 } 200 } 201 return null; 202 } 203 204 /** 205 * Find a single value of the given type in the given Collection. 206 * @param collection the Collection to search 207 * @param type the type to look for 208 * @return a value of the given type found if there is a clear match, 209 * or <code>null</code> if none or more than one such value found 210 */ 211 public static Object findValueOfType(Collection collection, Class type) { 212 if (isEmpty(collection)) { 213 return null; 214 } 215 Object value = null; 216 for (Iterator it = collection.iterator(); it.hasNext();) { 217 Object obj = it.next(); 218 if (type == null || type.isInstance(obj)) { 219 if (value != null) { 220 // More than one value found... no clear single value. 221 return null; 222 } 223 value = obj; 224 } 225 } 226 return value; 227 } 228 229 /** 230 * Find a single value of one of the given types in the given Collection: 231 * searching the Collection for a value of the first type, then 232 * searching for a value of the second type, etc. 233 * @param collection the collection to search 234 * @param types the types to look for, in prioritized order 235 * @return a value of one of the given types found if there is a clear match, 236 * or <code>null</code> if none or more than one such value found 237 */ 238 public static Object findValueOfType(Collection collection, Class[] types) { 239 if (isEmpty(collection) || ObjectUtils.isEmpty(types)) { 240 return null; 241 } 242 for (int i = 0; i < types.length; i++) { 243 Object value = findValueOfType(collection, types[i]); 244 if (value != null) { 245 return value; 246 } 247 } 248 return null; 249 } 250 251 /** 252 * Determine whether the given Collection only contains a single unique object. 253 * @param collection the Collection to check 254 * @return <code>true</code> if the collection contains a single reference or 255 * multiple references to the same instance, <code>false</code> else 256 */ 257 public static boolean hasUniqueObject(Collection collection) { 258 if (isEmpty(collection)) { 259 return false; 260 } 261 boolean hasCandidate = false; 262 Object candidate = null; 263 for (Iterator it = collection.iterator(); it.hasNext();) { 264 Object elem = it.next(); 265 if (!hasCandidate) { 266 hasCandidate = true; 267 candidate = elem; 268 } 269 else if (candidate != elem) { 270 return false; 271 } 272 } 273 return true; 274 } 275 276 }