]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/util/ArrayUtils.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / ArrayUtils.java
1 /*******************************************************************************
2  *  Copyright (c) 2010 Association for Decentralized Information Management in
3  *  Industry THTH ry.
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
8  *
9  *  Contributors:
10  *      VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.util;
13
14 import java.lang.reflect.Array;
15
16 public class ArrayUtils {
17         
18     /**
19      * Drop elements from array 
20      * 
21      * @param src source array
22      * @param elementsToDrop
23      * @return src or new array 
24      */
25         @SafeVarargs
26         public static <T> T[] dropElements(T src[], T...elementsToDrop)
27     {
28         if (src.length==0) return src;
29         int count = 0;
30         nextA:
31         for (T a : src) {
32                 for (T b : elementsToDrop)
33                         if (a==b) continue nextA;
34                 count++;
35         }
36         if (count==src.length) return src;
37         
38         Class<?> componentClass = src.getClass().getComponentType();
39         @SuppressWarnings("unchecked")
40         T[] result = (T[]) Array.newInstance(componentClass, count);
41         if (count==0) return result;
42         int index = 0;
43         nextA2:
44         for (T a : src) {
45                 for (T b : elementsToDrop)
46                         if (a==b) continue nextA2;
47                 result[index++] = a;
48         }
49         return result;
50     }           
51     
52     /**
53      * Replace first occurance of object with another
54      * 
55      * @param src
56      * @param from
57      * @param to
58      */
59     public static void replaceFirst(Object src[], Object from, Object to) {
60         for (int i=0; i<src.length; i++)
61                 if (src[i] == from) {
62                         src[i] = to;
63                         return;
64                 }
65     }
66     
67     /**
68      * Concatenate two arrays
69      * @param a
70      * @param b
71      * @return A new array with elements of a followed by elements of b
72      */
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());
76         if (compType == null)
77                 throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName());
78         return concatenate(a, b, compType);
79     }
80     
81     /**
82      * Concatenate two arrays
83      * @param a
84      * @param b
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
87      */
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);
93         return result;
94     }
95     
96     /**
97      * Concatenate two arrays, cropping or extending the result to a given length
98      * @param a
99      * @param b
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
102      */
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);
109     }
110     
111     /**
112      * Concatenate two arrays, cropping or extending the result to a given length
113      * @param a
114      * @param b
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
118      */
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));
125         return result;
126     }
127     
128     /**
129      * Add new elements to the end of an array
130      * @param a
131      * @param b
132      * @return A new array with elements b appended at the end
133      */
134     @SafeVarargs
135     public static <T> T[] append(T[] a, T ... b) {
136         return concatenate(a, b);
137     }
138     
139     /**
140      * Add new elements to the end of an array
141      * @param a
142      * @param b
143      * @return A new array with elements b appended at the end
144      */
145     @SafeVarargs
146     public static <T> T[] append(Class<? extends T> compType, T[] a, T ... b) {
147         return concatenate(a, b, compType);
148     }
149     
150     /**
151      * Add new elements to the end of an array
152      * @param a
153      * @param b
154      * @param length    Length of the resulting array
155      * @return A new array with elements b appended at the end
156      */
157     @SafeVarargs
158     public static <T> T[] append(int length, T[] a,  T ... b) {
159         return concatenate(a, b, length);
160     }
161     
162     /**
163      * Add new elements to the end of an array
164      * @param a
165      * @param b
166      * @param length    Length of the resulting array
167      * @return A new array with elements b appended at the end
168      */
169     @SafeVarargs
170     public static <T> T[] append(Class<? extends T> compType, int length, T[] a, T ... b) {
171         return concatenate(a, b, length, compType);
172     }
173     
174     /**
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]]
179      */
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]];
185         return result;
186     }
187     
188     /**
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.
193      */
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]];
200         return result;
201     }
202     
203     /**
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
207      * Serializable.
208      * @param a
209      * @param b
210      * @return
211      */
212     public static Class<?> getCommonBase(Class<?> a, Class<?> b) {
213         if (a == null || b == null)
214                 return Object.class;
215         else if (a.isArray() && b.isArray())
216                 return Array.newInstance(getCommonBase(a.getComponentType(), b.getComponentType()), 0).getClass();
217         else if (a.isAssignableFrom(b))
218                 return a;
219         else if (b.isAssignableFrom(a))
220                 return b;
221         else { 
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());
225                 
226                 /* Return the less generic one */
227                 return ab.isAssignableFrom(ba) ? ba : ab;
228         }
229     }
230 }