View Javadoc

1   /*
2    $Id: InvokerHelper.java,v 1.68 2005/05/11 01:17:39 phk Exp $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Codehaus.  For written permission,
22      please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25      nor may "groovy" appear in their names without prior written
26      permission of The Codehaus. "groovy" is a registered
27      trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30      http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45   */
46  package org.codehaus.groovy.runtime;
47  
48  import groovy.lang.*;
49  
50  import java.beans.Introspector;
51  import java.io.IOException;
52  import java.io.InputStream;
53  import java.io.InputStreamReader;
54  import java.io.Reader;
55  import java.io.Writer;
56  import java.lang.reflect.Array;
57  import java.math.BigDecimal;
58  import java.math.BigInteger;
59  import java.util.ArrayList;
60  import java.util.Collection;
61  import java.util.HashMap;
62  import java.util.Iterator;
63  import java.util.List;
64  import java.util.Map;
65  import java.util.regex.Matcher;
66  import java.util.regex.Pattern;
67  
68  /***
69   * A static helper class to make bytecode generation easier and act as a facade over the Invoker
70   *
71   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
72   * @version $Revision: 1.68 $
73   */
74  public class InvokerHelper {
75      public static final Object[] EMPTY_ARGS = {
76      };
77  
78      private static final Object[] EMPTY_MAIN_ARGS = new Object[]{new String[0]};
79  
80      private static final Invoker singleton = new Invoker();
81  
82      private static final Integer ZERO = new Integer(0);
83      private static final Integer MINUS_ONE = new Integer(-1);
84      private static final Integer ONE = new Integer(1);
85  
86      public static MetaClass getMetaClass(Object object) {
87          return getInstance().getMetaClass(object);
88      }
89  
90      public static void removeClass(Class clazz) {
91          getInstance().removeMetaClass(clazz);
92          Introspector.flushFromCaches(clazz);
93      }
94  
95      public static Invoker getInstance() {
96          return singleton;
97      }
98  
99      public static Object invokeNoArgumentsMethod(Object object, String methodName) {
100         return getInstance().invokeMethod(object, methodName, EMPTY_ARGS);
101     }
102 
103     public static Object invokeMethod(Object object, String methodName, Object arguments) {
104         return getInstance().invokeMethod(object, methodName, arguments);
105     }
106 
107     public static Object invokeSuperMethod(Object object, String methodName, Object arguments) {
108         return getInstance().invokeSuperMethod(object, methodName, arguments);
109     }
110 
111     public static Object invokeMethodSafe(Object object, String methodName, Object arguments) {
112         if (object != null) {
113             return getInstance().invokeMethod(object, methodName, arguments);
114         }
115         return null;
116     }
117 
118     public static Object invokeStaticMethod(String type, String methodName, Object arguments) {
119         return getInstance().invokeStaticMethod(type, methodName, arguments);
120     }
121 
122     public static Object invokeStaticNoArgumentsMethod(String type, String methodName) {
123         return getInstance().invokeStaticMethod(type, methodName, EMPTY_ARGS);
124     }
125 
126     public static Object invokeConstructor(String type, Object arguments) {
127         return getInstance().invokeConstructor(type, arguments);
128     }
129 
130     public static Object invokeConstructorOf(Class type, Object arguments) {
131         return getInstance().invokeConstructorOf(type, arguments);
132     }
133 
134     public static Object invokeNoArgumentsConstructorOf(Class type) {
135         return getInstance().invokeConstructorOf(type, EMPTY_ARGS);
136     }
137 
138     public static Object invokeClosure(Object closure, Object arguments) {
139         return getInstance().invokeMethod(closure, "doCall", arguments);
140     }
141 
142     public static Iterator asIterator(Object collection) {
143         return getInstance().asIterator(collection);
144     }
145 
146     public static Collection asCollection(Object collection) {
147         return getInstance().asCollection(collection);
148     }
149 
150     public static List asList(Object args) {
151         return getInstance().asList(args);
152     }
153 
154     public static String toString(Object arguments) {
155         return getInstance().toString(arguments);
156     }
157 
158     public static String toTypeString(Object[] arguments) {
159         return getInstance().toTypeString(arguments);
160     }
161 
162     public static String inspect(Object self) {
163         return getInstance().inspect(self);
164     }
165 
166     public static Object getAttribute(Object object, String attribute) {
167         return getInstance().getAttribute(object, attribute);
168     }
169 
170     public static void setAttribute(Object object, String attribute, Object newValue) {
171         getInstance().setAttribute(object, attribute, newValue);
172     }
173 
174     public static Object getProperty(Object object, String property) {
175         return getInstance().getProperty(object, property);
176     }
177 
178     public static Object getPropertySafe(Object object, String property) {
179         if (object != null) {
180             return getInstance().getProperty(object, property);
181         }
182         return null;
183     }
184 
185     public static void setProperty(Object object, String property, Object newValue) {
186         getInstance().setProperty(object, property, newValue);
187     }
188 
189     /***
190      * This is so we don't have to reorder the stack when we call this method.
191      * At some point a better name might be in order.
192      */
193     public static void setProperty2(Object newValue, Object object, String property) {
194         getInstance().setProperty(object, property, newValue);
195     }
196 
197 
198     /***
199      * This is so we don't have to reorder the stack when we call this method.
200      * At some point a better name might be in order.
201      */
202     public static void setGroovyObjectProperty(Object newValue, GroovyObject object, String property) {
203         object.setProperty(property, newValue);
204     }
205 
206     public static Object getGroovyObjectProperty(GroovyObject object, String property) {
207         return object.getProperty(property);
208     }
209 
210 
211     /***
212      * This is so we don't have to reorder the stack when we call this method.
213      * At some point a better name might be in order.
214      */
215     public static void setPropertySafe2(Object newValue, Object object, String property) {
216         if (object != null) {
217             setProperty2(newValue, object, property);
218         }
219     }
220 
221     /***
222      * Returns the method pointer for the given object name
223      */
224     public static Closure getMethodPointer(Object object, String methodName) {
225         return getInstance().getMethodPointer(object, methodName);
226     }
227 
228     /***
229      * Provides a hook for type coercion of the given object to the required type
230      *
231      * @param type   of object to convert the given object to
232      * @param object the object to be converted
233      * @return the original object or a new converted value
234      */
235     public static Object asType(Object object, Class type) {
236         return getInstance().asType(object, type);
237     }
238 
239     public static boolean asBool(Object object) {
240         return getInstance().asBool(object);
241     }
242 
243     public static boolean notObject(Object object) {
244         return !asBool(object);
245     }
246 
247     public static boolean notBoolean(boolean bool) {
248         return !bool;
249     }
250 
251     public static Object negate(Object value) {
252         if (value instanceof Integer) {
253             Integer number = (Integer) value;
254             return integerValue(-number.intValue());
255         }
256         else if (value instanceof Long) {
257             Long number = (Long) value;
258             return new Long(-number.longValue());
259         }
260         else if (value instanceof BigInteger) {
261             return ((BigInteger) value).negate();
262         }
263         else if (value instanceof BigDecimal) {
264             return ((BigDecimal) value).negate();
265         }
266         else if (value instanceof Double) {
267             Double number = (Double) value;
268             return new Double(-number.doubleValue());
269         }
270         else if (value instanceof Float) {
271             Float number = (Float) value;
272             return new Float(-number.floatValue());
273         }
274         else if (value instanceof ArrayList) {
275             // value is an list.
276             ArrayList newlist = new ArrayList();
277             Iterator it = ((ArrayList) value).iterator();
278             for (; it.hasNext();) {
279                 newlist.add(negate(it.next()));
280             }
281             return newlist;
282         }
283         else {
284             throw new GroovyRuntimeException("Cannot negate type " + value.getClass().getName() + ", value " + value);
285         }
286     }
287 
288     public static Object bitNegate(Object value) {
289         if (value instanceof Integer) {
290             Integer number = (Integer) value;
291             return integerValue(~number.intValue());
292         }
293         else if (value instanceof Long) {
294             Long number = (Long) value;
295             return new Long(~number.longValue());
296         }
297         else if (value instanceof BigInteger) {
298             return ((BigInteger) value).not();
299         }
300         else if (value instanceof String) {
301             // value is a regular expression.
302             return getInstance().regexPattern(value);
303         }
304         else if (value instanceof GString) {
305             // value is a regular expression.
306             return getInstance().regexPattern(value.toString());
307         }
308         else if (value instanceof ArrayList) {
309             // value is an list.
310             ArrayList newlist = new ArrayList();
311             Iterator it = ((ArrayList) value).iterator();
312             for (; it.hasNext();) {
313                 newlist.add(bitNegate(it.next()));
314             }
315             return newlist;
316         }
317         else {
318             throw new BitwiseNegateEvaluatingException("Cannot bitwise negate type " + value.getClass().getName() + ", value " + value);
319         }
320     }
321 
322     public static boolean isCase(Object switchValue, Object caseExpression) {
323         return asBool(invokeMethod(caseExpression, "isCase", new Object[]{switchValue}));
324     }
325 
326     public static boolean compareIdentical(Object left, Object right) {
327         return left == right;
328     }
329 
330     public static boolean compareEqual(Object left, Object right) {
331         return getInstance().objectsEqual(left, right);
332     }
333 
334     public static Matcher findRegex(Object left, Object right) {
335         return getInstance().objectFindRegex(left, right);
336     }
337 
338     public static boolean matchRegex(Object left, Object right) {
339         return getInstance().objectMatchRegex(left, right);
340     }
341 
342     public static Pattern regexPattern(Object regex) {
343         return getInstance().regexPattern(regex);
344     }
345 
346     public static boolean compareNotEqual(Object left, Object right) {
347         return !getInstance().objectsEqual(left, right);
348     }
349 
350     public static boolean compareLessThan(Object left, Object right) {
351         return getInstance().compareTo(left, right) < 0;
352     }
353 
354     public static boolean compareLessThanEqual(Object left, Object right) {
355         return getInstance().compareTo(left, right) <= 0;
356     }
357 
358     public static boolean compareGreaterThan(Object left, Object right) {
359         return getInstance().compareTo(left, right) > 0;
360     }
361 
362     public static boolean compareGreaterThanEqual(Object left, Object right) {
363         return getInstance().compareTo(left, right) >= 0;
364     }
365 
366     public static Integer compareTo(Object left, Object right) {
367         int answer = getInstance().compareTo(left, right);
368         if (answer == 0) {
369             return ZERO;
370         }
371         else {
372             return answer > 0 ? ONE : MINUS_ONE;
373         }
374     }
375 
376     public static Tuple createTuple(Object[] array) {
377         return new Tuple(array);
378     }
379 
380     public static SpreadList spreadList(Object value) {
381         if (value instanceof List) {
382             // value is a list.
383             Object[] values = new Object[((List) value).size()];
384             int index = 0;
385             Iterator it = ((List) value).iterator();
386             for (; it.hasNext();) {
387                 values[index++] = it.next();
388             }
389             return new SpreadList(values);
390         }
391         else {
392             throw new SpreadListEvaluatingException("Cannot spread the type " + value.getClass().getName() + ", value " + value);
393         }
394     }
395 
396     public static SpreadMap spreadMap(Object value) {
397         if (value instanceof Map) {
398             Object[] values = new Object[((Map) value).keySet().size() * 2];
399             int index = 0;
400             Iterator it = ((Map) value).keySet().iterator();
401             for (; it.hasNext();) {
402                 Object key = it.next();
403                 values[index++] = key;
404                 values[index++] = ((Map) value).get(key);
405             }
406             return new SpreadMap(values);
407         }
408         else {
409             throw new SpreadMapEvaluatingException("Cannot spread the map " + value.getClass().getName() + ", value " + value);
410         }
411     }
412 
413     public static List createList(Object[] values) {
414         ArrayList answer = new ArrayList(values.length);
415         for (int i = 0; i < values.length; i++) {
416             if (values[i] instanceof SpreadList) {
417                 SpreadList slist = (SpreadList) values[i];
418                 for (int j = 0; j < slist.size(); j++) {
419                     answer.add(slist.get(j));
420                 }
421             }
422             else {
423                 answer.add(values[i]);
424             }
425         }
426         return answer;
427     }
428 
429     public static Map createMap(Object[] values) {
430         Map answer = new HashMap(values.length / 2);
431         int i = 0;
432         while (i < values.length - 1) {
433             if ((values[i] instanceof SpreadMap) && (values[i+1] instanceof Map)) {
434                 Map smap = (Map) values[i+1];
435                 Iterator iter = smap.keySet().iterator();
436                 for (; iter.hasNext(); ) {
437                     Object key = (Object) iter.next();
438                     answer.put(key, smap.get(key));
439                 }
440                 i+=2;
441             }
442             else {
443                 answer.put(values[i++], values[i++]);
444             }
445         }
446         return answer;
447     }
448 
449     public static List createRange(Object from, Object to, boolean inclusive) {
450         if (!inclusive) {
451             if (compareGreaterThan(from, to)) {
452                 to = invokeMethod(to, "next", EMPTY_ARGS);
453             }
454             else {
455                 to = invokeMethod(to, "previous", EMPTY_ARGS);
456             }
457         }
458         if (from instanceof Integer && to instanceof Integer) {
459             return new IntRange(asInt(from), asInt(to));
460         }
461         else {
462             return new ObjectRange((Comparable) from, (Comparable) to);
463         }
464     }
465 
466     public static int asInt(Object value) {
467         return getInstance().asInt(value);
468     }
469 
470     public static void assertFailed(Object expression, Object message) {
471         if (message == null || "".equals(message)) {
472             throw new AssertionError("Expression: " + expression);
473         }
474         else {
475             throw new AssertionError("" + message + ". Expression: " + expression);
476         }
477     }
478 
479     public static Object runScript(Class scriptClass, String[] args) {
480         Binding context = new Binding(args);
481         Script script = createScript(scriptClass, context);
482         return invokeMethod(script, "run", EMPTY_ARGS);
483     }
484 
485     public static Script createScript(Class scriptClass, Binding context) {
486         // for empty scripts
487         if (scriptClass == null) {
488             return new Script() {
489                 public Object run() {
490                     return null;
491                 }
492             };
493         }
494         try {
495             final GroovyObject object = (GroovyObject) scriptClass.newInstance();
496             Script script = null;
497             if (object instanceof Script) {
498                 script = (Script) object;
499             }
500             else {
501                 // it could just be a class, so lets wrap it in a Script wrapper
502                 // though the bindings will be ignored
503                 script = new Script() {
504                     public Object run() {
505                         object.invokeMethod("main", EMPTY_MAIN_ARGS);
506                         return null;
507                     }
508                 };
509                 setProperties(object, context.getVariables());
510             }
511             script.setBinding(context);
512             return script;
513         }
514         catch (Exception e) {
515             throw new GroovyRuntimeException("Failed to create Script instance for class: " + scriptClass + ". Reason: " + e,
516                     e);
517         }
518     }
519 
520     /***
521      * Sets the properties on the given object
522      *
523      * @param object
524      * @param map
525      */
526     public static void setProperties(Object object, Map map) {
527         getMetaClass(object).setProperties(object, map);
528     }
529 
530     public static String getVersion() {
531         String version = null;
532         Package p = Package.getPackage("groovy.lang");
533         if (p != null) {
534             version = p.getImplementationVersion();
535         }
536         if (version == null) {
537             version = "";
538         }
539         return version;
540     }
541 
542     /***
543      * Allows conversion of arrays into a mutable List
544      *
545      * @return the array as a List
546      */
547     protected static List primitiveArrayToList(Object array) {
548         int size = Array.getLength(array);
549         List list = new ArrayList(size);
550         for (int i = 0; i < size; i++) {
551             list.add(Array.get(array, i));
552         }
553         return list;
554     }
555 
556     /***
557      * Writes the given object to the given stream
558      */
559     public static void write(Writer out, Object object) throws IOException {
560         if (object instanceof String) {
561             out.write((String) object);
562         }
563         else if (object instanceof Writable) {
564             Writable writable = (Writable) object;
565             writable.writeTo(out);
566         }
567         else if (object instanceof InputStream || object instanceof Reader) {
568             // Copy stream to stream
569             Reader reader;
570             if (object instanceof InputStream) {
571                 reader = new InputStreamReader((InputStream) object);
572             }
573             else {
574                 reader = (Reader) object;
575             }
576             char[] chars = new char[8192];
577             int i;
578             while ((i = reader.read(chars)) != -1) {
579                 out.write(chars, 0, i);
580             }
581             reader.close();
582         }
583         else {
584             out.write(toString(object));
585         }
586     }
587 
588     public static Object box(boolean value) {
589         return value ? Boolean.TRUE : Boolean.FALSE;
590     }
591 
592     public static Object box(byte value) {
593         return new Byte(value);
594     }
595 
596     public static Object box(char value) {
597         return new Character(value);
598     }
599 
600     public static Object box(short value) {
601         return new Short(value);
602     }
603 
604     public static Object box(int value) {
605         return integerValue(value);
606     }
607 
608     public static Object box(long value) {
609         return new Long(value);
610     }
611 
612     public static Object box(float value) {
613         return new Float(value);
614     }
615 
616     public static Object box(double value) {
617         return new Double(value);
618     }
619 
620     public static byte byteUnbox(Object value) {
621         Number n = (Number) asType(value, Byte.class);
622         return n.byteValue();
623     }
624 
625     public static char charUnbox(Object value) {
626         Character n = (Character) asType(value, Character.class);
627         return n.charValue();
628     }
629 
630     public static short shortUnbox(Object value) {
631         Number n = (Number) asType(value, Short.class);
632         return n.shortValue();
633     }
634 
635     public static int intUnbox(Object value) {
636         Number n = (Number) asType(value, Integer.class);
637         return n.intValue();
638     }
639 
640     public static boolean booleanUnbox(Object value) {
641         Boolean n = (Boolean) asType(value, Boolean.class);
642         return n.booleanValue();
643     }
644 
645     public static long longUnbox(Object value) {
646         Number n = (Number) asType(value, Long.class);
647         return n.longValue();
648     }
649 
650     public static float floatUnbox(Object value) {
651         Number n = (Number) asType(value, Float.class);
652         return n.floatValue();
653     }
654 
655     public static double doubleUnbox(Object value) {
656         Number n = (Number) asType(value, Double.class);
657         return n.doubleValue();
658     }
659 
660     /***
661      * @param a    array of primitives
662      * @param type component type of the array
663      * @return
664      */
665     public static Object[] convertPrimitiveArray(Object a, Class type) {
666 //        System.out.println("a.getClass() = " + a.getClass());
667         Object[] ans = null;
668         String elemType = type.getName();
669         if (elemType.equals("int")) {
670             // conservative coding
671             if (a.getClass().getName().equals("[Ljava.lang.Integer;")) {
672                 ans = (Integer[]) a;
673             }
674             else {
675                 int[] ia = (int[]) a;
676                 ans = new Integer[ia.length];
677                 for (int i = 0; i < ia.length; i++) {
678                     int e = ia[i];
679                     ans[i] = integerValue(e);
680                 }
681             }
682         }
683         else if (elemType.equals("char")) {
684             if (a.getClass().getName().equals("[Ljava.lang.Character;")) {
685                 ans = (Character[]) a;
686             }
687             else {
688                 char[] ia = (char[]) a;
689                 ans = new Character[ia.length];
690                 for (int i = 0; i < ia.length; i++) {
691                     char e = ia[i];
692                     ans[i] = new Character(e);
693                 }
694             }
695         }
696         else if (elemType.equals("boolean")) {
697             if (a.getClass().getName().equals("[Ljava.lang.Boolean;")) {
698                 ans = (Boolean[]) a;
699             }
700             else {
701                 boolean[] ia = (boolean[]) a;
702                 ans = new Boolean[ia.length];
703                 for (int i = 0; i < ia.length; i++) {
704                     boolean e = ia[i];
705                     ans[i] = new Boolean(e);
706                 }
707             }
708         }
709         else if (elemType.equals("byte")) {
710             if (a.getClass().getName().equals("[Ljava.lang.Byte;")) {
711                 ans = (Byte[]) a;
712             }
713             else {
714                 byte[] ia = (byte[]) a;
715                 ans = new Byte[ia.length];
716                 for (int i = 0; i < ia.length; i++) {
717                     byte e = ia[i];
718                     ans[i] = new Byte(e);
719                 }
720             }
721         }
722         else if (elemType.equals("short")) {
723             if (a.getClass().getName().equals("[Ljava.lang.Short;")) {
724                 ans = (Short[]) a;
725             }
726             else {
727                 short[] ia = (short[]) a;
728                 ans = new Short[ia.length];
729                 for (int i = 0; i < ia.length; i++) {
730                     short e = ia[i];
731                     ans[i] = new Short(e);
732                 }
733             }
734         }
735         else if (elemType.equals("float")) {
736             if (a.getClass().getName().equals("[Ljava.lang.Float;")) {
737                 ans = (Float[]) a;
738             }
739             else {
740                 float[] ia = (float[]) a;
741                 ans = new Float[ia.length];
742                 for (int i = 0; i < ia.length; i++) {
743                     float e = ia[i];
744                     ans[i] = new Float(e);
745                 }
746             }
747         }
748         else if (elemType.equals("long")) {
749             if (a.getClass().getName().equals("[Ljava.lang.Long;")) {
750                 ans = (Long[]) a;
751             }
752             else {
753                 long[] ia = (long[]) a;
754                 ans = new Long[ia.length];
755                 for (int i = 0; i < ia.length; i++) {
756                     long e = ia[i];
757                     ans[i] = new Long(e);
758                 }
759             }
760         }
761         else if (elemType.equals("double")) {
762             if (a.getClass().getName().equals("[Ljava.lang.Double;")) {
763                 ans = (Double[]) a;
764             }
765             else {
766                 double[] ia = (double[]) a;
767                 ans = new Double[ia.length];
768                 for (int i = 0; i < ia.length; i++) {
769                     double e = ia[i];
770                     ans[i] = new Double(e);
771                 }
772             }
773         }
774         return ans;
775     }
776 
777     public static int[] convertToIntArray(Object a) {
778         int[] ans = null;
779 
780         // conservative coding
781         if (a.getClass().getName().equals("[I")) {
782             ans = (int[]) a;
783         }
784         else {
785             Object[] ia = (Object[]) a;
786             ans = new int[ia.length];
787             for (int i = 0; i < ia.length; i++) {
788                 if (ia[i] == null) {
789                     continue;
790                 }
791                 ans[i] = ((Number) ia[i]).intValue();
792             }
793         }
794         return ans;
795     }
796 
797     public static boolean[] convertToBooleanArray(Object a) {
798         boolean[] ans = null;
799 
800         // conservative coding
801         if (a.getClass().getName().equals("[Z")) {
802             ans = (boolean[]) a;
803         }
804         else {
805             Object[] ia = (Object[]) a;
806             ans = new boolean[ia.length];
807             for (int i = 0; i < ia.length; i++) {
808                 if (ia[i] == null) {
809                     continue;
810                 }
811                 ans[i] = ((Boolean) ia[i]).booleanValue();
812             }
813         }
814         return ans;
815     }
816 
817     public static byte[] convertToByteArray(Object a) {
818         byte[] ans = null;
819 
820         // conservative coding
821         if (a.getClass().getName().equals("[B")) {
822             ans = (byte[]) a;
823         }
824         else {
825             Object[] ia = (Object[]) a;
826             ans = new byte[ia.length];
827             for (int i = 0; i < ia.length; i++) {
828                 if (ia[i] != null) {
829                     ans[i] = ((Number) ia[i]).byteValue();
830                 }
831             }
832         }
833         return ans;
834     }
835 
836     public static short[] convertToShortArray(Object a) {
837         short[] ans = null;
838 
839         // conservative coding
840         if (a.getClass().getName().equals("[S")) {
841             ans = (short[]) a;
842         }
843         else {
844             Object[] ia = (Object[]) a;
845             ans = new short[ia.length];
846             for (int i = 0; i < ia.length; i++) {
847                 ans[i] = ((Number) ia[i]).shortValue();
848             }
849         }
850         return ans;
851     }
852 
853     public static char[] convertToCharArray(Object a) {
854         char[] ans = null;
855 
856         // conservative coding
857         if (a.getClass().getName().equals("[C")) {
858             ans = (char[]) a;
859         }
860         else {
861             Object[] ia = (Object[]) a;
862             ans = new char[ia.length];
863             for (int i = 0; i < ia.length; i++) {
864                 if (ia[i] == null) {
865                     continue;
866                 }
867                 ans[i] = ((Character) ia[i]).charValue();
868             }
869         }
870         return ans;
871     }
872 
873     public static long[] convertToLongArray(Object a) {
874         long[] ans = null;
875 
876         // conservative coding
877         if (a.getClass().getName().equals("[J")) {
878             ans = (long[]) a;
879         }
880         else {
881             Object[] ia = (Object[]) a;
882             ans = new long[ia.length];
883             for (int i = 0; i < ia.length; i++) {
884                 if (ia[i] == null) {
885                     continue;
886                 }
887                 ans[i] = ((Number) ia[i]).longValue();
888             }
889         }
890         return ans;
891     }
892 
893     public static float[] convertToFloatArray(Object a) {
894         float[] ans = null;
895 
896         // conservative coding
897         if (a.getClass().getName().equals("[F")) {
898             ans = (float[]) a;
899         }
900         else {
901             Object[] ia = (Object[]) a;
902             ans = new float[ia.length];
903             for (int i = 0; i < ia.length; i++) {
904                 if (ia[i] == null) {
905                     continue;
906                 }
907                 ans[i] = ((Number) ia[i]).floatValue();
908             }
909         }
910         return ans;
911     }
912 
913     public static double[] convertToDoubleArray(Object a) {
914         double[] ans = null;
915 
916         // conservative coding
917         if (a.getClass().getName().equals("[D")) {
918             ans = (double[]) a;
919         }
920         else {
921             Object[] ia = (Object[]) a;
922             ans = new double[ia.length];
923             for (int i = 0; i < ia.length; i++) {
924                 if (ia[i] == null) {
925                     continue;
926                 }
927                 ans[i] = ((Number) ia[i]).doubleValue();
928             }
929         }
930         return ans;
931     }
932 
933     public static Object convertToPrimitiveArray(Object a, Class type) {
934         if (type == Byte.TYPE) {
935             return convertToByteArray(a);
936         }
937         if (type == Boolean.TYPE) {
938             return convertToBooleanArray(a);
939         }
940         if (type == Short.TYPE) {
941             return convertToShortArray(a);
942         }
943         if (type == Character.TYPE) {
944             return convertToCharArray(a);
945         }
946         if (type == Integer.TYPE) {
947             return convertToIntArray(a);
948         }
949         if (type == Long.TYPE) {
950             return convertToLongArray(a);
951         }
952         if (type == Float.TYPE) {
953             return convertToFloatArray(a);
954         }
955         if (type == Double.TYPE) {
956             return convertToDoubleArray(a);
957         }
958         else {
959             return a;
960         }
961     }
962 
963     /***
964      * get the Integer object from an int. Cached version is used for small ints.
965      *
966      * @param v
967      * @return
968      */
969     public static Integer integerValue(int v) {
970         int index = v + INT_CACHE_OFFSET;
971         if (index >= 0 && index < INT_CACHE_LEN) {
972             return SMALL_INTEGERS[index];
973         }
974         else {
975             return new Integer(v);
976         }
977     }
978 
979     private static Integer[] SMALL_INTEGERS;
980     private static int INT_CACHE_OFFSET = 128, INT_CACHE_LEN = 256;
981 
982     static {
983         SMALL_INTEGERS = new Integer[INT_CACHE_LEN];
984         for (int i = 0; i < SMALL_INTEGERS.length; i++) {
985             SMALL_INTEGERS[i] = new Integer(i - INT_CACHE_OFFSET);
986         }
987     }
988 }