]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/util/ArrayUtils.java
Re-implement URIStringUtils escape and unescape using Unicode
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / ArrayUtils.java
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\r
4  *  All rights reserved. This program and the accompanying materials\r
5  *  are made available under the terms of the Eclipse Public License v1.0\r
6  *  which accompanies this distribution, and is available at\r
7  *  http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.util;
13 \r
14 import java.lang.reflect.Array;\r
15
16 public class ArrayUtils {\r
17         \r
18     /**\r
19      * Drop elements from array \r
20      * \r
21      * @param src source array\r
22      * @param elementsToDrop\r
23      * @return src or new array \r
24      */\r
25         @SafeVarargs\r
26         public static <T> T[] dropElements(T src[], T...elementsToDrop)\r
27     {\r
28         if (src.length==0) return src;\r
29         int count = 0;\r
30         nextA:\r
31         for (T a : src) {\r
32                 for (T b : elementsToDrop)\r
33                         if (a==b) continue nextA;\r
34                 count++;\r
35         }\r
36         if (count==src.length) return src;\r
37         \r
38         Class<?> componentClass = src.getClass().getComponentType();\r
39         @SuppressWarnings("unchecked")\r
40         T[] result = (T[]) Array.newInstance(componentClass, count);\r
41         if (count==0) return result;\r
42         int index = 0;\r
43         nextA2:\r
44         for (T a : src) {\r
45                 for (T b : elementsToDrop)\r
46                         if (a==b) continue nextA2;\r
47                 result[index++] = a;\r
48         }\r
49         return result;\r
50     }           \r
51     \r
52     /**\r
53      * Replace first occurance of object with another\r
54      * \r
55      * @param src\r
56      * @param from\r
57      * @param to\r
58      */\r
59     public static void replaceFirst(Object src[], Object from, Object to) {\r
60         for (int i=0; i<src.length; i++)\r
61                 if (src[i] == from) {\r
62                         src[i] = to;\r
63                         return;\r
64                 }\r
65     }\r
66     \r
67     /**\r
68      * Concatenate two arrays\r
69      * @param a\r
70      * @param b\r
71      * @return A new array with elements of a followed by elements of b\r
72      */\r
73     public static <T> T[] concatenate(T[] a, T[] b) {\r
74         @SuppressWarnings("unchecked")\r
75                 Class<? extends T> compType = (Class<? extends T>) getCommonBase(a.getClass().getComponentType(), b.getClass().getComponentType());\r
76         if (compType == null)\r
77                 throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName());\r
78         return concatenate(a, b, compType);\r
79     }\r
80     \r
81     /**\r
82      * Concatenate two arrays\r
83      * @param a\r
84      * @param b\r
85      * @param componentType             The actual component type of the created array\r
86      * @return A new array with elements of a followed by elements of b\r
87      */\r
88     public static <T> T[] concatenate(T[] a, T[] b, Class<? extends T> componentType) {\r
89         @SuppressWarnings("unchecked")\r
90                 T[] result = (T[]) Array.newInstance(componentType, a.length + b.length);\r
91         System.arraycopy(a, 0, result, 0, a.length);\r
92         System.arraycopy(b, 0, result, a.length, b.length);\r
93         return result;\r
94     }\r
95     \r
96     /**\r
97      * Concatenate two arrays, cropping or extending the result to a given length\r
98      * @param a\r
99      * @param b\r
100      * @param length    Length of the resulting array\r
101      * @return A new array with elements of a followed by elements of b, possibly padded with nulls to reach a given length\r
102      */\r
103     public static <T> T[] concatenate(T[] a, T[] b, int length) {\r
104         @SuppressWarnings("unchecked")\r
105                 Class<? extends T> compType = (Class<? extends T>)getCommonBase(a.getClass().getComponentType(), b.getClass().getComponentType());\r
106         if (compType == null)\r
107                 throw new RuntimeException("Could not deduce common array type for " + a.getClass().getName() + " and " + b.getClass().getName());\r
108         return concatenate(a, b, length, compType);\r
109     }\r
110     \r
111     /**\r
112      * Concatenate two arrays, cropping or extending the result to a given length\r
113      * @param a\r
114      * @param b\r
115      * @param length    Length of the resulting array\r
116      * @param componentType             The actual component type of the created array\r
117      * @return A new array with elements of a followed by elements of b, possibly padded with nulls to reach a given length\r
118      */\r
119     public static <T> T[] concatenate(T[] a, T[] b, int length, Class<? extends T> componentType) {\r
120                 @SuppressWarnings("unchecked")\r
121                 T[] result = (T[]) Array.newInstance(componentType, length);\r
122         System.arraycopy(a, 0, result, 0, Math.min(length, a.length));\r
123         if (length > a.length)\r
124                 System.arraycopy(b, 0, result, a.length, Math.min(b.length, length - a.length));\r
125         return result;\r
126     }\r
127     \r
128     /**\r
129      * Add new elements to the end of an array\r
130      * @param a\r
131      * @param b\r
132      * @return A new array with elements b appended at the end\r
133      */\r
134     @SafeVarargs\r
135     public static <T> T[] append(T[] a, T ... b) {\r
136         return concatenate(a, b);\r
137     }\r
138     
139     /**\r
140      * Add new elements to the end of an array\r
141      * @param a\r
142      * @param b\r
143      * @return A new array with elements b appended at the end\r
144      */\r
145     @SafeVarargs\r
146     public static <T> T[] append(Class<? extends T> compType, T[] a, T ... b) {\r
147         return concatenate(a, b, compType);\r
148     }\r
149     \r
150     /**\r
151      * Add new elements to the end of an array\r
152      * @param a\r
153      * @param b\r
154      * @param length    Length of the resulting array\r
155      * @return A new array with elements b appended at the end\r
156      */\r
157     @SafeVarargs\r
158     public static <T> T[] append(int length, T[] a,  T ... b) {\r
159         return concatenate(a, b, length);\r
160     }\r
161     \r
162     /**\r
163      * Add new elements to the end of an array\r
164      * @param a\r
165      * @param b\r
166      * @param length    Length of the resulting array\r
167      * @return A new array with elements b appended at the end\r
168      */\r
169     @SafeVarargs\r
170     public static <T> T[] append(Class<? extends T> compType, int length, T[] a, T ... b) {\r
171         return concatenate(a, b, length, compType);\r
172     }\r
173     \r
174     /**\r
175      * Get an array with elements from a source array at given indices\r
176      * @param source    A source array\r
177      * @param index             An index array\r
178      * @return A new array with element i equal to source[index[i]]\r
179      */\r
180     public static <T> T[] indirection(T[] source, int[] index) {\r
181         @SuppressWarnings("unchecked")\r
182                 T[] result = (T[]) Array.newInstance(source.getClass().getComponentType(), index.length);\r
183         for (int i = 0; i < index.length; i++)\r
184                 result[i] = source[index[i]];\r
185         return result;\r
186     }\r
187     \r
188     /**\r
189      * Get an array with given length with elements from a source array at given indices\r
190      * @param source    A source array\r
191      * @param index             An index array\r
192      * @return A new array with element i equal to source[index[i]]. The resulting array length is set to #length.\r
193      */\r
194     public static <T> T[] indirection(T[] source, int[] index, int length) {\r
195         @SuppressWarnings("unchecked")\r
196                 T[] result = (T[]) Array.newInstance(source.getClass().getComponentType(), length);\r
197         int n = Math.min(length, index.length);\r
198         for (int i = 0; i < n; i++)\r
199                 result[i] = source[index[i]];\r
200         return result;\r
201     }\r
202     \r
203     /**\r
204      * Get a nearest common base class for two types. An interface type is returned only if one of classes\r
205      * is an interface type that is implemented by a superclass of the other. Thus, the returned base class for\r
206      * String and StringBuffer is returned Object, instead of either of the possible choices of CharSequence or\r
207      * Serializable.\r
208      * @param a\r
209      * @param b\r
210      * @return\r
211      */\r
212     public static Class<?> getCommonBase(Class<?> a, Class<?> b) {\r
213         if (a == null || b == null)\r
214                 return Object.class;\r
215         else if (a.isArray() && b.isArray())\r
216                 return Array.newInstance(getCommonBase(a.getComponentType(), b.getComponentType()), 0).getClass();\r
217         else if (a.isAssignableFrom(b))\r
218                 return a;\r
219         else if (b.isAssignableFrom(a))\r
220                 return b;\r
221         else { \r
222                 /* Due to interface definitions, these cases might return different results. */\r
223                 Class<?> ab = getCommonBase(a.getSuperclass(), b);\r
224                 Class<?> ba = getCommonBase(a, b.getSuperclass());\r
225                 \r
226                 /* Return the less generic one */\r
227                 return ab.isAssignableFrom(ba) ? ba : ab;\r
228         }\r
229     }\r
230 }