1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.util;
14 import java.lang.reflect.Array;
16 public class ArrayUtils {
19 * Drop elements from array
21 * @param src source array
22 * @param elementsToDrop
23 * @return src or new array
26 public static <T> T[] dropElements(T src[], T...elementsToDrop)
28 if (src.length==0) return src;
32 for (T b : elementsToDrop)
33 if (a==b) continue nextA;
36 if (count==src.length) return src;
38 Class<?> componentClass = src.getClass().getComponentType();
39 @SuppressWarnings("unchecked")
40 T[] result = (T[]) Array.newInstance(componentClass, count);
41 if (count==0) return result;
45 for (T b : elementsToDrop)
46 if (a==b) continue nextA2;
53 * Replace first occurance of object with another
59 public static void replaceFirst(Object src[], Object from, Object to) {
60 for (int i=0; i<src.length; i++)
68 * Concatenate two arrays
71 * @return A new array with elements of a followed by elements of b
73 public static <T> T[] concatenate(T[] a, T[] b) {
74 @SuppressWarnings("unchecked")
75 Class<? extends T> compType = (Class<? extends T>) getCommonBase(a.getClass().getComponentType(), b.getClass().getComponentType());
77 throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName());
78 return concatenate(a, b, compType);
82 * Concatenate two arrays
85 * @param componentType The actual component type of the created array
86 * @return A new array with elements of a followed by elements of b
88 public static <T> T[] concatenate(T[] a, T[] b, Class<? extends T> componentType) {
89 @SuppressWarnings("unchecked")
90 T[] result = (T[]) Array.newInstance(componentType, a.length + b.length);
91 System.arraycopy(a, 0, result, 0, a.length);
92 System.arraycopy(b, 0, result, a.length, b.length);
97 * Concatenate two arrays, cropping or extending the result to a given length
100 * @param length Length of the resulting array
101 * @return A new array with elements of a followed by elements of b, possibly padded with nulls to reach a given length
103 public static <T> T[] concatenate(T[] a, T[] b, int length) {
104 @SuppressWarnings("unchecked")
105 Class<? extends T> compType = (Class<? extends T>)getCommonBase(a.getClass().getComponentType(), b.getClass().getComponentType());
106 if (compType == null)
107 throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName());
108 return concatenate(a, b, length, compType);
112 * Concatenate two arrays, cropping or extending the result to a given length
115 * @param length Length of the resulting array
116 * @param componentType The actual component type of the created array
117 * @return A new array with elements of a followed by elements of b, possibly padded with nulls to reach a given length
119 public static <T> T[] concatenate(T[] a, T[] b, int length, Class<? extends T> componentType) {
120 @SuppressWarnings("unchecked")
121 T[] result = (T[]) Array.newInstance(componentType, length);
122 System.arraycopy(a, 0, result, 0, Math.min(length, a.length));
123 if (length > a.length)
124 System.arraycopy(b, 0, result, a.length, Math.min(b.length, length - a.length));
129 * Add new elements to the end of an array
132 * @return A new array with elements b appended at the end
135 public static <T> T[] append(T[] a, T ... b) {
136 return concatenate(a, b);
140 * Add new elements to the end of an array
143 * @return A new array with elements b appended at the end
146 public static <T> T[] append(Class<? extends T> compType, T[] a, T ... b) {
147 return concatenate(a, b, compType);
151 * Add new elements to the end of an array
154 * @param length Length of the resulting array
155 * @return A new array with elements b appended at the end
158 public static <T> T[] append(int length, T[] a, T ... b) {
159 return concatenate(a, b, length);
163 * Add new elements to the end of an array
166 * @param length Length of the resulting array
167 * @return A new array with elements b appended at the end
170 public static <T> T[] append(Class<? extends T> compType, int length, T[] a, T ... b) {
171 return concatenate(a, b, length, compType);
175 * Get an array with elements from a source array at given indices
176 * @param source A source array
177 * @param index An index array
178 * @return A new array with element i equal to source[index[i]]
180 public static <T> T[] indirection(T[] source, int[] index) {
181 @SuppressWarnings("unchecked")
182 T[] result = (T[]) Array.newInstance(source.getClass().getComponentType(), index.length);
183 for (int i = 0; i < index.length; i++)
184 result[i] = source[index[i]];
189 * Get an array with given length with elements from a source array at given indices
190 * @param source A source array
191 * @param index An index array
192 * @return A new array with element i equal to source[index[i]]. The resulting array length is set to #length.
194 public static <T> T[] indirection(T[] source, int[] index, int length) {
195 @SuppressWarnings("unchecked")
196 T[] result = (T[]) Array.newInstance(source.getClass().getComponentType(), length);
197 int n = Math.min(length, index.length);
198 for (int i = 0; i < n; i++)
199 result[i] = source[index[i]];
204 * Get a nearest common base class for two types. An interface type is returned only if one of classes
205 * is an interface type that is implemented by a superclass of the other. Thus, the returned base class for
206 * String and StringBuffer is returned Object, instead of either of the possible choices of CharSequence or
212 public static Class<?> getCommonBase(Class<?> a, Class<?> b) {
213 if (a == null || b == null)
215 else if (a.isArray() && b.isArray())
216 return Array.newInstance(getCommonBase(a.getComponentType(), b.getComponentType()), 0).getClass();
217 else if (a.isAssignableFrom(b))
219 else if (b.isAssignableFrom(a))
222 /* Due to interface definitions, these cases might return different results. */
223 Class<?> ab = getCommonBase(a.getSuperclass(), b);
224 Class<?> ba = getCommonBase(a, b.getSuperclass());
226 /* Return the less generic one */
227 return ab.isAssignableFrom(ba) ? ba : ab;