001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import static org.apache.juneau.common.internal.ArgUtils.*; 016import static org.apache.juneau.common.internal.StringUtils.*; 017 018import java.lang.reflect.*; 019import java.util.*; 020 021import org.apache.juneau.common.internal.*; 022 023/** 024 * Quick and dirty utilities for working with arrays. 025 * 026 * <h5 class='section'>See Also:</h5><ul> 027 028 * </ul> 029 */ 030public final class ArrayUtils { 031 032 /** 033 * Appends one or more elements to an array. 034 * 035 * @param <T> The element type. 036 * @param array The array to append to. 037 * @param newElements The new elements to append to the array. 038 * @return A new array with the specified elements appended. 039 */ 040 @SuppressWarnings("unchecked") 041 public static <T> T[] append(T[] array, T...newElements) { 042 if (array == null) 043 return newElements; 044 if (newElements.length == 0) 045 return array; 046 T[] a = (T[])Array.newInstance(array.getClass().getComponentType(), array.length + newElements.length); 047 for (int i = 0; i < array.length; i++) 048 a[i] = array[i]; 049 for (int i = 0; i < newElements.length; i++) 050 a[i+array.length] = newElements[i]; 051 return a; 052 } 053 054 /** 055 * Combine an arbitrary number of arrays into a single array. 056 * 057 * @param <E> The element type. 058 * @param arrays Collection of arrays to combine. 059 * @return A new combined array, or <jk>null</jk> if all arrays are <jk>null</jk>. 060 */ 061 @SuppressWarnings("unchecked") 062 public static <E> E[] combine(E[]...arrays) { 063 assertArgNotNull("arrays", arrays); 064 int l = 0; 065 E[] a1 = null; 066 for (E[] a : arrays) { 067 if (a1 == null && a != null) 068 a1 = a; 069 l += (a == null ? 0 : a.length); 070 } 071 if (a1 == null) 072 return null; 073 E[] a = (E[])Array.newInstance(a1.getClass().getComponentType(), l); 074 int i = 0; 075 for (E[] aa : arrays) 076 if (aa != null) 077 for (E t : aa) 078 a[i++] = t; 079 return a; 080 } 081 082 /** 083 * Converts the specified array to a <c>Set</c>. 084 * 085 * <p> 086 * The order of the entries in the set are the same as the array. 087 * 088 * @param <T> The entry type of the array. 089 * @param array The array being wrapped in a <c>Set</c> interface. 090 * @return The new set. 091 */ 092 public static <T> Set<T> asSet(final T[] array) { 093 assertArgNotNull("array", array); 094 return new AbstractSet<>() { 095 096 @Override /* Set */ 097 public Iterator<T> iterator() { 098 return new Iterator<>() { 099 int i = 0; 100 101 @Override /* Iterator */ 102 public boolean hasNext() { 103 return i < array.length; 104 } 105 106 @Override /* Iterator */ 107 public T next() { 108 if (i >= array.length) 109 throw new NoSuchElementException(); 110 T t = array[i]; 111 i++; 112 return t; 113 } 114 115 @Override /* Iterator */ 116 public void remove() { 117 throw new UnsupportedOperationException("Not supported."); 118 } 119 }; 120 } 121 122 @Override /* Set */ 123 public int size() { 124 return array.length; 125 } 126 }; 127 } 128 129 /** 130 * Converts the specified collection to an array. 131 * 132 * <p> 133 * Works on both object and primitive arrays. 134 * 135 * @param <E> The element type. 136 * @param c The collection to convert to an array. 137 * @param elementType The component type of the collection. 138 * @return A new array. 139 */ 140 public static <E> Object toArray(Collection<?> c, Class<E> elementType) { 141 Object a = Array.newInstance(elementType, c.size()); 142 Iterator<?> it = c.iterator(); 143 int i = 0; 144 while (it.hasNext()) 145 Array.set(a, i++, it.next()); 146 return a; 147 } 148 149 /** 150 * Returns <jk>true</jk> if the specified object is an array. 151 * 152 * @param array The array to test. 153 * @return <jk>true</jk> if the specified object is an array. 154 */ 155 public static boolean isArray(Object array) { 156 return array != null && array.getClass().isArray(); 157 } 158 159 /** 160 * Converts the specified array to an <c>ArrayList</c> 161 * 162 * @param <E> The element type. 163 * @param array The array to convert. 164 * @param elementType 165 * The type of objects in the array. 166 * It must match the actual component type in the array. 167 * @return A new {@link ArrayList} 168 */ 169 @SuppressWarnings("unchecked") 170 public static <E> List<E> toList(Object array, Class<E> elementType) { 171 List<E> l = new ArrayList<>(Array.getLength(array)); 172 for (int i = 0; i < Array.getLength(array); i++) 173 l.add((E)Array.get(array, i)); 174 return l; 175 } 176 177 /** 178 * Recursively converts the specified array into a list of objects. 179 * 180 * @param array The array to convert. 181 * @return A new {@link ArrayList} 182 */ 183 public static List<Object> toObjectList(Object array) { 184 List<Object> l = new ArrayList<>(Array.getLength(array)); 185 for (int i = 0; i < Array.getLength(array); i++) { 186 Object o = Array.get(array, i); 187 if (o != null && o.getClass().isArray()) 188 o = toObjectList(o); 189 l.add(o); 190 } 191 return l; 192 } 193 194 /** 195 * Copies the specified array into the specified list. 196 * 197 * <p> 198 * Works on both object and primitive arrays. 199 * 200 * @param array The array to copy into a list. 201 * @param list The list to copy the values into. 202 * @return The same list passed in. 203 */ 204 @SuppressWarnings({"unchecked","rawtypes"}) 205 public static List copyToList(Object array, List list) { 206 if (array != null) { 207 int length = Array.getLength(array); 208 for (int i = 0; i < length; i++) 209 list.add(Array.get(array, i)); 210 } 211 return list; 212 } 213 214 /** 215 * Returns <jk>true</jk> if the specified array contains the specified element using the {@link String#equals(Object)} 216 * method. 217 * 218 * @param element The element to check for. 219 * @param array The array to check. 220 * @return 221 * <jk>true</jk> if the specified array contains the specified element, 222 * <jk>false</jk> if the array or element is <jk>null</jk>. 223 */ 224 public static boolean contains(String element, String[] array) { 225 return indexOf(element, array) != -1; 226 } 227 228 /** 229 * Returns the index position of the element in the specified array using the {@link String#equals(Object)} method. 230 * 231 * @param element The element to check for. 232 * @param array The array to check. 233 * @return 234 * The index position of the element in the specified array, or 235 * <c>-1</c> if the array doesn't contain the element, or the array or element is <jk>null</jk>. 236 */ 237 public static int indexOf(String element, String[] array) { 238 if (element == null || array == null) 239 return -1; 240 for (int i = 0; i < array.length; i++) 241 if (element.equals(array[i])) 242 return i; 243 return -1; 244 } 245 246 /** 247 * Converts the specified collection to an array of strings. 248 * 249 * <p> 250 * Entries are converted to strings using {@link #toString()}. 251 * <jk>null</jk> values remain <jk>null</jk>. 252 * 253 * @param c The collection to convert. 254 * @return The collection as a string array. 255 */ 256 public static String[] toStringArray(Collection<?> c) { 257 String[] r = new String[c.size()]; 258 int i = 0; 259 for (Object o : c) 260 r[i++] = stringify(o); 261 return r; 262 } 263 264 /** 265 * Returns <jk>true</jk> if the following sorted arrays are equals. 266 * 267 * @param a1 Array #1. 268 * @param a2 Array #2. 269 * @return <jk>true</jk> if the following sorted arrays are equals. 270 */ 271 public static boolean equals(String[] a1, String[] a2) { 272 if (a1.length != a2.length) 273 return false; 274 for (int i = 0; i < a1.length; i++) 275 if (! StringUtils.eq(a1[i], a2[i])) 276 return false; 277 return true; 278 } 279 280 /** 281 * Makes a copy of the specified array. 282 * 283 * @param array The array to copy. 284 * @param <T> The element type. 285 * @return A new copy of the array, or <jk>null</jk> if the array was <jk>null</jk>.s 286 */ 287 public static <T> T[] copyOf(T[] array) { 288 return array == null ? null : Arrays.copyOf(array, array.length); 289 } 290 291 /** 292 * Returns <jk>true</jk> if the specified array is not null and has a length greater than zero. 293 * 294 * @param array The array to check. 295 * @return <jk>true</jk> if the specified array is not null and has a length greater than zero. 296 */ 297 public static boolean isNotEmptyArray(Object[] array) { 298 return array != null && array.length > 0; 299 } 300 301 /** 302 * Returns <jk>true</jk> if the specified array is null or has a length of zero. 303 * 304 * @param array The array to check. 305 * @return <jk>true</jk> if the specified array is null or has a length of zero. 306 */ 307 public static boolean isEmptyArray(Object[] array) { 308 return array == null || array.length == 0; 309 } 310 311 /** 312 * Returns <jk>true</jk> if both specified arrays are null or have a length of zero. 313 * 314 * @param array1 The array to check. 315 * @param array2 The array to check. 316 * @return <jk>true</jk> if the specified array is null or has a length of zero. 317 */ 318 public static boolean isEmptyArray(Object[] array1, Object[] array2) { 319 return isEmptyArray(array1) && isEmptyArray(array2); 320 } 321 322 /** 323 * Reverses the entries in an array. 324 * 325 * @param <E> The element type. 326 * @param array The array to reverse. 327 * @return The same array. 328 */ 329 public static <E> E[] reverse(E[] array) { 330 for (int i = 0; i < array.length / 2; i++) { 331 E temp = array[i]; 332 array[i] = array[array.length - i - 1]; 333 array[array.length - i - 1] = temp; 334 } 335 return array; 336 } 337}