/******************************************************************************* * Copyright (c) 2010 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.databoard.util; import java.lang.reflect.Array; public class ArrayUtils { /** * Drop elements from array * * @param src source array * @param elementsToDrop * @return src or new array */ @SafeVarargs public static T[] dropElements(T src[], T...elementsToDrop) { if (src.length==0) return src; int count = 0; nextA: for (T a : src) { for (T b : elementsToDrop) if (a==b) continue nextA; count++; } if (count==src.length) return src; Class componentClass = src.getClass().getComponentType(); @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(componentClass, count); if (count==0) return result; int index = 0; nextA2: for (T a : src) { for (T b : elementsToDrop) if (a==b) continue nextA2; result[index++] = a; } return result; } /** * Replace first occurance of object with another * * @param src * @param from * @param to */ public static void replaceFirst(Object src[], Object from, Object to) { for (int i=0; i T[] concatenate(T[] a, T[] b) { @SuppressWarnings("unchecked") Class compType = (Class) getCommonBase(a.getClass().getComponentType(), b.getClass().getComponentType()); if (compType == null) throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName()); return concatenate(a, b, compType); } /** * Concatenate two arrays * @param a * @param b * @param componentType The actual component type of the created array * @return A new array with elements of a followed by elements of b */ public static T[] concatenate(T[] a, T[] b, Class componentType) { @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(componentType, a.length + b.length); System.arraycopy(a, 0, result, 0, a.length); System.arraycopy(b, 0, result, a.length, b.length); return result; } /** * Concatenate two arrays, cropping or extending the result to a given length * @param a * @param b * @param length Length of the resulting array * @return A new array with elements of a followed by elements of b, possibly padded with nulls to reach a given length */ public static T[] concatenate(T[] a, T[] b, int length) { @SuppressWarnings("unchecked") Class compType = (Class)getCommonBase(a.getClass().getComponentType(), b.getClass().getComponentType()); if (compType == null) throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName()); return concatenate(a, b, length, compType); } /** * Concatenate two arrays, cropping or extending the result to a given length * @param a * @param b * @param length Length of the resulting array * @param componentType The actual component type of the created array * @return A new array with elements of a followed by elements of b, possibly padded with nulls to reach a given length */ public static T[] concatenate(T[] a, T[] b, int length, Class componentType) { @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(componentType, length); System.arraycopy(a, 0, result, 0, Math.min(length, a.length)); if (length > a.length) System.arraycopy(b, 0, result, a.length, Math.min(b.length, length - a.length)); return result; } /** * Add new elements to the end of an array * @param a * @param b * @return A new array with elements b appended at the end */ @SafeVarargs public static T[] append(T[] a, T ... b) { return concatenate(a, b); } /** * Add new elements to the end of an array * @param a * @param b * @return A new array with elements b appended at the end */ @SafeVarargs public static T[] append(Class compType, T[] a, T ... b) { return concatenate(a, b, compType); } /** * Add new elements to the end of an array * @param a * @param b * @param length Length of the resulting array * @return A new array with elements b appended at the end */ @SafeVarargs public static T[] append(int length, T[] a, T ... b) { return concatenate(a, b, length); } /** * Add new elements to the end of an array * @param a * @param b * @param length Length of the resulting array * @return A new array with elements b appended at the end */ @SafeVarargs public static T[] append(Class compType, int length, T[] a, T ... b) { return concatenate(a, b, length, compType); } /** * Get an array with elements from a source array at given indices * @param source A source array * @param index An index array * @return A new array with element i equal to source[index[i]] */ public static T[] indirection(T[] source, int[] index) { @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(source.getClass().getComponentType(), index.length); for (int i = 0; i < index.length; i++) result[i] = source[index[i]]; return result; } /** * Get an array with given length with elements from a source array at given indices * @param source A source array * @param index An index array * @return A new array with element i equal to source[index[i]]. The resulting array length is set to #length. */ public static T[] indirection(T[] source, int[] index, int length) { @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(source.getClass().getComponentType(), length); int n = Math.min(length, index.length); for (int i = 0; i < n; i++) result[i] = source[index[i]]; return result; } /** * Get a nearest common base class for two types. An interface type is returned only if one of classes * is an interface type that is implemented by a superclass of the other. Thus, the returned base class for * String and StringBuffer is returned Object, instead of either of the possible choices of CharSequence or * Serializable. * @param a * @param b * @return */ public static Class getCommonBase(Class a, Class b) { if (a == null || b == null) return Object.class; else if (a.isArray() && b.isArray()) return Array.newInstance(getCommonBase(a.getComponentType(), b.getComponentType()), 0).getClass(); else if (a.isAssignableFrom(b)) return a; else if (b.isAssignableFrom(a)) return b; else { /* Due to interface definitions, these cases might return different results. */ Class ab = getCommonBase(a.getSuperclass(), b); Class ba = getCommonBase(a, b.getSuperclass()); /* Return the less generic one */ return ab.isAssignableFrom(ba) ? ba : ab; } } }