001    /*
002     * Copyright 2006 Mat Gessel <mat.gessel@gmail.com>
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package asquare.gwt.tk.client.util;
017    
018    import java.util.List;
019    
020    /**
021     * General utility methods for working with in GWT. 
022     */
023    public class GwtUtil
024    {
025            /**
026             * Checks that the specified index is valid for the list (the GWT emulation
027             * of {@link java.util.Vector Vector} does not perform range checking). A
028             * flag is passed to indicate whether the range should be extended by 1 to
029             * allow for adding a last element. Throws an exception if the index is out
030             * of bounds for the list.
031             * 
032             * @param list the list to check against
033             * @param index the index to range check
034             * @param adding <code>true</code> to allow for
035             *            {@link List#add(int, java.lang.Object) adding} at the index
036             *            after last element in list
037             * @throws IndexOutOfBoundsException if the index is out of range
038             */
039            public static void rangeCheck(List list, int index, boolean adding) throws IndexOutOfBoundsException
040            {
041                    rangeCheck(0, list.size(), index, adding);
042            }
043            
044            /**
045             * Checks that a number is contained within the specified range. A flag is
046             * passed to indicate whether the range should be extended by 1 (to allow
047             * for adding a last element). Throws an exception if the index is out of
048             * bounds for the range.
049             * 
050             * @param first the first allowable number
051             * @param size the size of the allowed range
052             * @param n the index to range check
053             * @param extend <code>true</code> to extend the size of the range by
054             *            <code>1</code>
055             * @throws IndexOutOfBoundsException if the index is out of range
056             */
057            public static void rangeCheck(int first, int size, int n, boolean extend) throws IndexOutOfBoundsException
058            {
059                    if (n < first || n > (first + size) || (! extend) && n == (first + size))
060                            throw new IndexOutOfBoundsException(Integer.toString(n));
061            }
062            
063            /**
064             * Copies elements from the <code>src</code> array to the <code>dest</code> array. 
065             * 
066             * @param src the source array
067             * @param srcPos the starting position in the source array
068             * @param dest the destination array
069             * @param destPos the starting position in the destination array
070             * @param length the number of array elements to copy
071             * @throws NullPointerException if <code>src</code> or <code>dest</code> is <code>null</code>
072             * @throws IndexOutOfBoundsException if <code>srcPos < 0 || destPos < 0 || length < 0 || (srcPos + length > src.length) || (destPos + length > dest.length)</code>
073             * @throws ArrayStoreException if an element in <code>src</code> cannot not be copied to <code>dest</code> due to a type mismatch
074             * @see System#arraycopy(Object, int, Object, int, int)
075             */
076            public static void arrayCopy(Object src, int srcPos, Object dest, int destPos, int length)
077            {
078                    // need to check srcPos and destPos for script mode
079                    if (length < 0 || srcPos < 0 || destPos < 0)
080                            throw new IndexOutOfBoundsException();
081                    
082                    if (src instanceof Object[] && dest instanceof Object[])
083                    {
084                            arrayCopy((Object[]) src, srcPos, (Object[]) dest, destPos, length);
085                    }
086                    else if (src instanceof int[] && dest instanceof int[])
087                    {
088                            arrayCopy((int[]) src, srcPos, (int[]) dest, destPos, length);
089                    }
090                    else if (src instanceof boolean[] && dest instanceof boolean[])
091                    {
092                            arrayCopy((boolean[]) src, srcPos, (boolean[]) dest, destPos, length);
093                    }
094                    else if (src instanceof float[] && dest instanceof float[])
095                    {
096                            arrayCopy((float[]) src, srcPos, (float[]) dest, destPos, length);
097                    }
098                    else if (src instanceof char[] && dest instanceof char[])
099                    {
100                            arrayCopy((char[]) src, srcPos, (char[]) dest, destPos, length);
101                    }
102                    else if (src instanceof byte[] && dest instanceof byte[])
103                    {
104                            arrayCopy((byte[]) src, srcPos, (byte[]) dest, destPos, length);
105                    }
106                    else if (src instanceof short[] && dest instanceof short[])
107                    {
108                            arrayCopy((short[]) src, srcPos, (short[]) dest, destPos, length);
109                    }
110                    else if (src instanceof long[] && dest instanceof long[])
111                    {
112                            arrayCopy((long[]) src, srcPos, (long[]) dest, destPos, length);
113                    }
114                    else if (src instanceof double[] && dest instanceof double[])
115                    {
116                            arrayCopy((double[]) src, srcPos, (double[]) dest, destPos, length);
117                    }
118                    else if (src == null || dest == null)
119                    {
120                            throw new NullPointerException();
121                    }
122                    else
123                    {
124                            throw new ArrayStoreException();
125                    }
126            }
127            
128            private static void arrayCopy(Object[] src, int srcPos, Object[] dest, int destPos, int length)
129            {
130                    if (srcPos + length > src.length || destPos + length > dest.length)
131                            throw new IndexOutOfBoundsException();
132                    
133                    for (int i = 0; i < length; i++)
134                    {
135                            dest[destPos + i] = src[srcPos + i];
136                    }
137            }
138            
139            private static void arrayCopy(int[] src, int srcPos, int[] dest, int destPos, int length)
140            {
141                    if (srcPos + length > src.length || destPos + length > dest.length)
142                            throw new IndexOutOfBoundsException();
143                    
144                    for (int i = 0; i < length; i++)
145                    {
146                            dest[destPos + i] = src[srcPos + i];
147                    }
148            }
149            
150            private static void arrayCopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length)
151            {
152                    if (srcPos + length > src.length || destPos + length > dest.length)
153                            throw new IndexOutOfBoundsException();
154                    
155                    for (int i = 0; i < length; i++)
156                    {
157                            dest[destPos + i] = src[srcPos + i];
158                    }
159            }
160            
161            private static void arrayCopy(float[] src, int srcPos, float[] dest, int destPos, int length)
162            {
163                    if (srcPos + length > src.length || destPos + length > dest.length)
164                            throw new IndexOutOfBoundsException();
165                    
166                    for (int i = 0; i < length; i++)
167                    {
168                            dest[destPos + i] = src[srcPos + i];
169                    }
170            }
171            
172            private static void arrayCopy(char[] src, int srcPos, char[] dest, int destPos, int length)
173            {
174                    if (srcPos + length > src.length || destPos + length > dest.length)
175                            throw new IndexOutOfBoundsException();
176                    
177                    for (int i = 0; i < length; i++)
178                    {
179                            dest[destPos + i] = src[srcPos + i];
180                    }
181            }
182            
183            private static void arrayCopy(byte[] src, int srcPos, byte[] dest, int destPos, int length)
184            {
185                    if (srcPos + length > src.length || destPos + length > dest.length)
186                            throw new IndexOutOfBoundsException();
187                    
188                    for (int i = 0; i < length; i++)
189                    {
190                            dest[destPos + i] = src[srcPos + i];
191                    }
192            }
193            
194            private static void arrayCopy(short[] src, int srcPos, short[] dest, int destPos, int length)
195            {
196                    if (srcPos + length > src.length || destPos + length > dest.length)
197                            throw new IndexOutOfBoundsException();
198                    
199                    for (int i = 0; i < length; i++)
200                    {
201                            dest[destPos + i] = src[srcPos + i];
202                    }
203            }
204            
205            private static void arrayCopy(long[] src, int srcPos, long[] dest, int destPos, int length)
206            {
207                    if (srcPos + length > src.length || destPos + length > dest.length)
208                            throw new IndexOutOfBoundsException();
209                    
210                    for (int i = 0; i < length; i++)
211                    {
212                            dest[destPos + i] = src[srcPos + i];
213                    }
214            }
215            
216            private static void arrayCopy(double[] src, int srcPos, double[] dest, int destPos, int length)
217            {
218                    if (srcPos + length > src.length || destPos + length > dest.length)
219                            throw new IndexOutOfBoundsException();
220                    
221                    for (int i = 0; i < length; i++)
222                    {
223                            dest[destPos + i] = src[srcPos + i];
224                    }
225            }
226            
227            /**
228             * Copies all of the elements in <code>list</code> to <code>array</code>.
229             * Similar to {@link List#toArray(Object[])} except this does not
230             * automatically expand the array size.
231             * 
232             * @param src a list
233             * @param dest a non-primitive array
234             * @throws NullPointerException if <code>src</code> or <code>dest</code>
235             *             is <code>null</code>
236             * @throws IndexOutOfBoundsException if <code>dest</code> is not large
237             *             enough to contain all of the list elements.
238             * @throws ArrayStoreException if an element in <code>list</code> cannot
239             *             not be copied to <code>dest</code> due to a type mismatch
240             */
241            public static Object[] toArray(List src, Object[] dest)
242            {
243                    // necessary in web mode
244                    if (src == null || dest == null)
245                            throw new NullPointerException();
246                    
247                    int size = src.size();
248                    rangeCheck(0, dest.length, size - 1, false);
249                    
250                    for (int i = 0; i < size; i++)
251                    {
252                            dest[i] = src.get(i);
253                    }
254                    
255                    return dest;
256            }
257            
258            /**
259             * Tests two Strings for equality. Same as {@link String#equals(Object)}.
260             * Either argument may be <code>null</code>.
261             * 
262             * @param a a String, or <code>null</code>
263             * @param b a String, or <code>null</code>
264             * @return <code>true</code> if <code>(a == b || a != null && a.equals(b))</code>
265             */
266            public static native boolean equals(String a, String b) /*-{
267                    return a == b;
268            }-*/;
269    }