View Javadoc

1   /*
2    $Id: InvokerHelper.java,v 1.70 2005/07/23 12:09:48 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.70 $
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         if (arguments instanceof Object[])
156             return getInstance().toArrayString((Object[])arguments);
157         else if (arguments instanceof Collection)
158             return getInstance().toListString((Collection)arguments);
159         else if (arguments instanceof Map)
160             return getInstance().toMapString((Map)arguments);
161         else
162             return getInstance().toString(arguments);
163     }
164 
165     public static String toTypeString(Object[] arguments) {
166         return getInstance().toTypeString(arguments);
167     }
168 
169     public static String toMapString(Map arg) {
170         return getInstance().toMapString(arg);
171     }
172 
173     public static String toListString(Collection arg) {
174         return getInstance().toListString(arg);
175     }
176 
177     public static String toArrayString(Object[] arguments) {
178         return getInstance().toArrayString(arguments);
179     }
180 
181     public static String inspect(Object self) {
182         return getInstance().inspect(self);
183     }
184 
185     public static Object getAttribute(Object object, String attribute) {
186         return getInstance().getAttribute(object, attribute);
187     }
188 
189     public static void setAttribute(Object object, String attribute, Object newValue) {
190         getInstance().setAttribute(object, attribute, newValue);
191     }
192 
193     public static Object getProperty(Object object, String property) {
194         return getInstance().getProperty(object, property);
195     }
196 
197     public static Object getPropertySafe(Object object, String property) {
198         if (object != null) {
199             return getInstance().getProperty(object, property);
200         }
201         return null;
202     }
203 
204     public static void setProperty(Object object, String property, Object newValue) {
205         getInstance().setProperty(object, property, newValue);
206     }
207 
208     /***
209      * This is so we don't have to reorder the stack when we call this method.
210      * At some point a better name might be in order.
211      */
212     public static void setProperty2(Object newValue, Object object, String property) {
213         getInstance().setProperty(object, property, newValue);
214     }
215 
216 
217     /***
218      * This is so we don't have to reorder the stack when we call this method.
219      * At some point a better name might be in order.
220      */
221     public static void setGroovyObjectProperty(Object newValue, GroovyObject object, String property) {
222         object.setProperty(property, newValue);
223     }
224 
225     public static Object getGroovyObjectProperty(GroovyObject object, String property) {
226         return object.getProperty(property);
227     }
228 
229 
230     /***
231      * This is so we don't have to reorder the stack when we call this method.
232      * At some point a better name might be in order.
233      */
234     public static void setPropertySafe2(Object newValue, Object object, String property) {
235         if (object != null) {
236             setProperty2(newValue, object, property);
237         }
238     }
239 
240     /***
241      * Returns the method pointer for the given object name
242      */
243     public static Closure getMethodPointer(Object object, String methodName) {
244         return getInstance().getMethodPointer(object, methodName);
245     }
246 
247     /***
248      * Provides a hook for type coercion of the given object to the required type
249      *
250      * @param type   of object to convert the given object to
251      * @param object the object to be converted
252      * @return the original object or a new converted value
253      */
254     public static Object asType(Object object, Class type) {
255         return getInstance().asType(object, type);
256     }
257 
258     public static boolean asBool(Object object) {
259         return getInstance().asBool(object);
260     }
261 
262     public static boolean notObject(Object object) {
263         return !asBool(object);
264     }
265 
266     public static boolean notBoolean(boolean bool) {
267         return !bool;
268     }
269 
270     public static Object negate(Object value) {
271         if (value instanceof Integer) {
272             Integer number = (Integer) value;
273             return integerValue(-number.intValue());
274         }
275         else if (value instanceof Long) {
276             Long number = (Long) value;
277             return new Long(-number.longValue());
278         }
279         else if (value instanceof BigInteger) {
280             return ((BigInteger) value).negate();
281         }
282         else if (value instanceof BigDecimal) {
283             return ((BigDecimal) value).negate();
284         }
285         else if (value instanceof Double) {
286             Double number = (Double) value;
287             return new Double(-number.doubleValue());
288         }
289         else if (value instanceof Float) {
290             Float number = (Float) value;
291             return new Float(-number.floatValue());
292         }
293         else if (value instanceof ArrayList) {
294             // value is an list.
295             ArrayList newlist = new ArrayList();
296             Iterator it = ((ArrayList) value).iterator();
297             for (; it.hasNext();) {
298                 newlist.add(negate(it.next()));
299             }
300             return newlist;
301         }
302         else {
303             throw new GroovyRuntimeException("Cannot negate type " + value.getClass().getName() + ", value " + value);
304         }
305     }
306 
307     public static Object bitNegate(Object value) {
308         if (value instanceof Integer) {
309             Integer number = (Integer) value;
310             return integerValue(~number.intValue());
311         }
312         else if (value instanceof Long) {
313             Long number = (Long) value;
314             return new Long(~number.longValue());
315         }
316         else if (value instanceof BigInteger) {
317             return ((BigInteger) value).not();
318         }
319         else if (value instanceof String) {
320             // value is a regular expression.
321             return getInstance().regexPattern(value);
322         }
323         else if (value instanceof GString) {
324             // value is a regular expression.
325             return getInstance().regexPattern(value.toString());
326         }
327         else if (value instanceof ArrayList) {
328             // value is an list.
329             ArrayList newlist = new ArrayList();
330             Iterator it = ((ArrayList) value).iterator();
331             for (; it.hasNext();) {
332                 newlist.add(bitNegate(it.next()));
333             }
334             return newlist;
335         }
336         else {
337             throw new BitwiseNegateEvaluatingException("Cannot bitwise negate type " + value.getClass().getName() + ", value " + value);
338         }
339     }
340 
341     public static boolean isCase(Object switchValue, Object caseExpression) {
342         return asBool(invokeMethod(caseExpression, "isCase", new Object[]{switchValue}));
343     }
344 
345     public static boolean compareIdentical(Object left, Object right) {
346         return left == right;
347     }
348 
349     public static boolean compareEqual(Object left, Object right) {
350         return getInstance().objectsEqual(left, right);
351     }
352 
353     public static Matcher findRegex(Object left, Object right) {
354         return getInstance().objectFindRegex(left, right);
355     }
356 
357     public static boolean matchRegex(Object left, Object right) {
358         return getInstance().objectMatchRegex(left, right);
359     }
360 
361     public static Pattern regexPattern(Object regex) {
362         return getInstance().regexPattern(regex);
363     }
364 
365     public static boolean compareNotEqual(Object left, Object right) {
366         return !getInstance().objectsEqual(left, right);
367     }
368 
369     public static boolean compareLessThan(Object left, Object right) {
370         return getInstance().compareTo(left, right) < 0;
371     }
372 
373     public static boolean compareLessThanEqual(Object left, Object right) {
374         return getInstance().compareTo(left, right) <= 0;
375     }
376 
377     public static boolean compareGreaterThan(Object left, Object right) {
378         return getInstance().compareTo(left, right) > 0;
379     }
380 
381     public static boolean compareGreaterThanEqual(Object left, Object right) {
382         return getInstance().compareTo(left, right) >= 0;
383     }
384 
385     public static Integer compareTo(Object left, Object right) {
386         int answer = getInstance().compareTo(left, right);
387         if (answer == 0) {
388             return ZERO;
389         }
390         else {
391             return answer > 0 ? ONE : MINUS_ONE;
392         }
393     }
394 
395     public static Tuple createTuple(Object[] array) {
396         return new Tuple(array);
397     }
398 
399     public static SpreadList spreadList(Object value) {
400         if (value instanceof List) {
401             // value is a list.
402             Object[] values = new Object[((List) value).size()];
403             int index = 0;
404             Iterator it = ((List) value).iterator();
405             for (; it.hasNext();) {
406                 values[index++] = it.next();
407             }
408             return new SpreadList(values);
409         }
410         else {
411             throw new SpreadListEvaluatingException("Cannot spread the type " + value.getClass().getName() + ", value " + value);
412         }
413     }
414 
415     public static SpreadMap spreadMap(Object value) {
416         if (value instanceof Map) {
417             Object[] values = new Object[((Map) value).keySet().size() * 2];
418             int index = 0;
419             Iterator it = ((Map) value).keySet().iterator();
420             for (; it.hasNext();) {
421                 Object key = it.next();
422                 values[index++] = key;
423                 values[index++] = ((Map) value).get(key);
424             }
425             return new SpreadMap(values);
426         }
427         else {
428             throw new SpreadMapEvaluatingException("Cannot spread the map " + value.getClass().getName() + ", value " + value);
429         }
430     }
431 
432     public static List createList(Object[] values) {
433         ArrayList answer = new ArrayList(values.length);
434         for (int i = 0; i < values.length; i++) {
435             if (values[i] instanceof SpreadList) {
436                 SpreadList slist = (SpreadList) values[i];
437                 for (int j = 0; j < slist.size(); j++) {
438                     answer.add(slist.get(j));
439                 }
440             }
441             else {
442                 answer.add(values[i]);
443             }
444         }
445         return answer;
446     }
447 
448     public static Map createMap(Object[] values) {
449         Map answer = new HashMap(values.length / 2);
450         int i = 0;
451         while (i < values.length - 1) {
452             if ((values[i] instanceof SpreadMap) && (values[i+1] instanceof Map)) {
453                 Map smap = (Map) values[i+1];
454                 Iterator iter = smap.keySet().iterator();
455                 for (; iter.hasNext(); ) {
456                     Object key = (Object) iter.next();
457                     answer.put(key, smap.get(key));
458                 }
459                 i+=2;
460             }
461             else {
462                 answer.put(values[i++], values[i++]);
463             }
464         }
465         return answer;
466     }
467 
468     public static List createRange(Object from, Object to, boolean inclusive) {
469         if (!inclusive) {
470             if (compareEqual(from,to)){
471                 return new EmptyRange((Comparable)from);
472             }
473             if (compareGreaterThan(from, to)) {
474                 to = invokeMethod(to, "next", EMPTY_ARGS);
475             }
476             else {
477                 to = invokeMethod(to, "previous", EMPTY_ARGS);
478             }
479         }
480         if (from instanceof Integer && to instanceof Integer) {
481             return new IntRange(asInt(from), asInt(to));
482         }
483         else {
484             return new ObjectRange((Comparable) from, (Comparable) to);
485         }
486     }
487 
488     public static int asInt(Object value) {
489         return getInstance().asInt(value);
490     }
491 
492     public static void assertFailed(Object expression, Object message) {
493         if (message == null || "".equals(message)) {
494             throw new AssertionError("Expression: " + expression);
495         }
496         else {
497             throw new AssertionError("" + message + ". Expression: " + expression);
498         }
499     }
500 
501     public static Object runScript(Class scriptClass, String[] args) {
502         Binding context = new Binding(args);
503         Script script = createScript(scriptClass, context);
504         return invokeMethod(script, "run", EMPTY_ARGS);
505     }
506 
507     public static Script createScript(Class scriptClass, Binding context) {
508         // for empty scripts
509         if (scriptClass == null) {
510             return new Script() {
511                 public Object run() {
512                     return null;
513                 }
514             };
515         }
516         try {
517             final GroovyObject object = (GroovyObject) scriptClass.newInstance();
518             Script script = null;
519             if (object instanceof Script) {
520                 script = (Script) object;
521             }
522             else {
523                 // it could just be a class, so lets wrap it in a Script wrapper
524                 // though the bindings will be ignored
525                 script = new Script() {
526                     public Object run() {
527                         object.invokeMethod("main", EMPTY_MAIN_ARGS);
528                         return null;
529                     }
530                 };
531                 setProperties(object, context.getVariables());
532             }
533             script.setBinding(context);
534             return script;
535         }
536         catch (Exception e) {
537             throw new GroovyRuntimeException("Failed to create Script instance for class: " + scriptClass + ". Reason: " + e,
538                     e);
539         }
540     }
541 
542     /***
543      * Sets the properties on the given object
544      *
545      * @param object
546      * @param map
547      */
548     public static void setProperties(Object object, Map map) {
549         getMetaClass(object).setProperties(object, map);
550     }
551 
552     public static String getVersion() {
553         String version = null;
554         Package p = Package.getPackage("groovy.lang");
555         if (p != null) {
556             version = p.getImplementationVersion();
557         }
558         if (version == null) {
559             version = "";
560         }
561         return version;
562     }
563 
564     /***
565      * Allows conversion of arrays into a mutable List
566      *
567      * @return the array as a List
568      */
569     protected static List primitiveArrayToList(Object array) {
570         int size = Array.getLength(array);
571         List list = new ArrayList(size);
572         for (int i = 0; i < size; i++) {
573             list.add(Array.get(array, i));
574         }
575         return list;
576     }
577 
578     /***
579      * Writes the given object to the given stream
580      */
581     public static void write(Writer out, Object object) throws IOException {
582         if (object instanceof String) {
583             out.write((String) object);
584         }
585         else if (object instanceof Object[]) {
586             out.write(toArrayString((Object[]) object));
587         }
588         else if (object instanceof Map) {
589             out.write(toMapString((Map) object));
590         }
591         else if (object instanceof Collection) {
592             out.write(toListString((Collection) object));
593         }
594         else if (object instanceof Writable) {
595             Writable writable = (Writable) object;
596             writable.writeTo(out);
597         }
598         else if (object instanceof InputStream || object instanceof Reader) {
599             // Copy stream to stream
600             Reader reader;
601             if (object instanceof InputStream) {
602                 reader = new InputStreamReader((InputStream) object);
603             }
604             else {
605                 reader = (Reader) object;
606             }
607             char[] chars = new char[8192];
608             int i;
609             while ((i = reader.read(chars)) != -1) {
610                 out.write(chars, 0, i);
611             }
612             reader.close();
613         }
614         else {
615             out.write(toString(object));
616         }
617     }
618 
619     public static Object box(boolean value) {
620         return value ? Boolean.TRUE : Boolean.FALSE;
621     }
622 
623     public static Object box(byte value) {
624         return new Byte(value);
625     }
626 
627     public static Object box(char value) {
628         return new Character(value);
629     }
630 
631     public static Object box(short value) {
632         return new Short(value);
633     }
634 
635     public static Object box(int value) {
636         return integerValue(value);
637     }
638 
639     public static Object box(long value) {
640         return new Long(value);
641     }
642 
643     public static Object box(float value) {
644         return new Float(value);
645     }
646 
647     public static Object box(double value) {
648         return new Double(value);
649     }
650 
651     public static byte byteUnbox(Object value) {
652         Number n = (Number) asType(value, Byte.class);
653         return n.byteValue();
654     }
655 
656     public static char charUnbox(Object value) {
657         Character n = (Character) asType(value, Character.class);
658         return n.charValue();
659     }
660 
661     public static short shortUnbox(Object value) {
662         Number n = (Number) asType(value, Short.class);
663         return n.shortValue();
664     }
665 
666     public static int intUnbox(Object value) {
667         Number n = (Number) asType(value, Integer.class);
668         return n.intValue();
669     }
670 
671     public static boolean booleanUnbox(Object value) {
672         Boolean n = (Boolean) asType(value, Boolean.class);
673         return n.booleanValue();
674     }
675 
676     public static long longUnbox(Object value) {
677         Number n = (Number) asType(value, Long.class);
678         return n.longValue();
679     }
680 
681     public static float floatUnbox(Object value) {
682         Number n = (Number) asType(value, Float.class);
683         return n.floatValue();
684     }
685 
686     public static double doubleUnbox(Object value) {
687         Number n = (Number) asType(value, Double.class);
688         return n.doubleValue();
689     }
690 
691     /***
692      * @param a    array of primitives
693      * @param type component type of the array
694      * @return
695      */
696     public static Object[] convertPrimitiveArray(Object a, Class type) {
697 //        System.out.println("a.getClass() = " + a.getClass());
698         Object[] ans = null;
699         String elemType = type.getName();
700         if (elemType.equals("int")) {
701             // conservative coding
702             if (a.getClass().getName().equals("[Ljava.lang.Integer;")) {
703                 ans = (Integer[]) a;
704             }
705             else {
706                 int[] ia = (int[]) a;
707                 ans = new Integer[ia.length];
708                 for (int i = 0; i < ia.length; i++) {
709                     int e = ia[i];
710                     ans[i] = integerValue(e);
711                 }
712             }
713         }
714         else if (elemType.equals("char")) {
715             if (a.getClass().getName().equals("[Ljava.lang.Character;")) {
716                 ans = (Character[]) a;
717             }
718             else {
719                 char[] ia = (char[]) a;
720                 ans = new Character[ia.length];
721                 for (int i = 0; i < ia.length; i++) {
722                     char e = ia[i];
723                     ans[i] = new Character(e);
724                 }
725             }
726         }
727         else if (elemType.equals("boolean")) {
728             if (a.getClass().getName().equals("[Ljava.lang.Boolean;")) {
729                 ans = (Boolean[]) a;
730             }
731             else {
732                 boolean[] ia = (boolean[]) a;
733                 ans = new Boolean[ia.length];
734                 for (int i = 0; i < ia.length; i++) {
735                     boolean e = ia[i];
736                     ans[i] = new Boolean(e);
737                 }
738             }
739         }
740         else if (elemType.equals("byte")) {
741             if (a.getClass().getName().equals("[Ljava.lang.Byte;")) {
742                 ans = (Byte[]) a;
743             }
744             else {
745                 byte[] ia = (byte[]) a;
746                 ans = new Byte[ia.length];
747                 for (int i = 0; i < ia.length; i++) {
748                     byte e = ia[i];
749                     ans[i] = new Byte(e);
750                 }
751             }
752         }
753         else if (elemType.equals("short")) {
754             if (a.getClass().getName().equals("[Ljava.lang.Short;")) {
755                 ans = (Short[]) a;
756             }
757             else {
758                 short[] ia = (short[]) a;
759                 ans = new Short[ia.length];
760                 for (int i = 0; i < ia.length; i++) {
761                     short e = ia[i];
762                     ans[i] = new Short(e);
763                 }
764             }
765         }
766         else if (elemType.equals("float")) {
767             if (a.getClass().getName().equals("[Ljava.lang.Float;")) {
768                 ans = (Float[]) a;
769             }
770             else {
771                 float[] ia = (float[]) a;
772                 ans = new Float[ia.length];
773                 for (int i = 0; i < ia.length; i++) {
774                     float e = ia[i];
775                     ans[i] = new Float(e);
776                 }
777             }
778         }
779         else if (elemType.equals("long")) {
780             if (a.getClass().getName().equals("[Ljava.lang.Long;")) {
781                 ans = (Long[]) a;
782             }
783             else {
784                 long[] ia = (long[]) a;
785                 ans = new Long[ia.length];
786                 for (int i = 0; i < ia.length; i++) {
787                     long e = ia[i];
788                     ans[i] = new Long(e);
789                 }
790             }
791         }
792         else if (elemType.equals("double")) {
793             if (a.getClass().getName().equals("[Ljava.lang.Double;")) {
794                 ans = (Double[]) a;
795             }
796             else {
797                 double[] ia = (double[]) a;
798                 ans = new Double[ia.length];
799                 for (int i = 0; i < ia.length; i++) {
800                     double e = ia[i];
801                     ans[i] = new Double(e);
802                 }
803             }
804         }
805         return ans;
806     }
807 
808     public static int[] convertToIntArray(Object a) {
809         int[] ans = null;
810 
811         // conservative coding
812         if (a.getClass().getName().equals("[I")) {
813             ans = (int[]) a;
814         }
815         else {
816             Object[] ia = (Object[]) a;
817             ans = new int[ia.length];
818             for (int i = 0; i < ia.length; i++) {
819                 if (ia[i] == null) {
820                     continue;
821                 }
822                 ans[i] = ((Number) ia[i]).intValue();
823             }
824         }
825         return ans;
826     }
827 
828     public static boolean[] convertToBooleanArray(Object a) {
829         boolean[] ans = null;
830 
831         // conservative coding
832         if (a.getClass().getName().equals("[Z")) {
833             ans = (boolean[]) a;
834         }
835         else {
836             Object[] ia = (Object[]) a;
837             ans = new boolean[ia.length];
838             for (int i = 0; i < ia.length; i++) {
839                 if (ia[i] == null) {
840                     continue;
841                 }
842                 ans[i] = ((Boolean) ia[i]).booleanValue();
843             }
844         }
845         return ans;
846     }
847 
848     public static byte[] convertToByteArray(Object a) {
849         byte[] ans = null;
850 
851         // conservative coding
852         if (a.getClass().getName().equals("[B")) {
853             ans = (byte[]) a;
854         }
855         else {
856             Object[] ia = (Object[]) a;
857             ans = new byte[ia.length];
858             for (int i = 0; i < ia.length; i++) {
859                 if (ia[i] != null) {
860                     ans[i] = ((Number) ia[i]).byteValue();
861                 }
862             }
863         }
864         return ans;
865     }
866 
867     public static short[] convertToShortArray(Object a) {
868         short[] ans = null;
869 
870         // conservative coding
871         if (a.getClass().getName().equals("[S")) {
872             ans = (short[]) a;
873         }
874         else {
875             Object[] ia = (Object[]) a;
876             ans = new short[ia.length];
877             for (int i = 0; i < ia.length; i++) {
878                 ans[i] = ((Number) ia[i]).shortValue();
879             }
880         }
881         return ans;
882     }
883 
884     public static char[] convertToCharArray(Object a) {
885         char[] ans = null;
886 
887         // conservative coding
888         if (a.getClass().getName().equals("[C")) {
889             ans = (char[]) a;
890         }
891         else {
892             Object[] ia = (Object[]) a;
893             ans = new char[ia.length];
894             for (int i = 0; i < ia.length; i++) {
895                 if (ia[i] == null) {
896                     continue;
897                 }
898                 ans[i] = ((Character) ia[i]).charValue();
899             }
900         }
901         return ans;
902     }
903 
904     public static long[] convertToLongArray(Object a) {
905         long[] ans = null;
906 
907         // conservative coding
908         if (a.getClass().getName().equals("[J")) {
909             ans = (long[]) a;
910         }
911         else {
912             Object[] ia = (Object[]) a;
913             ans = new long[ia.length];
914             for (int i = 0; i < ia.length; i++) {
915                 if (ia[i] == null) {
916                     continue;
917                 }
918                 ans[i] = ((Number) ia[i]).longValue();
919             }
920         }
921         return ans;
922     }
923 
924     public static float[] convertToFloatArray(Object a) {
925         float[] ans = null;
926 
927         // conservative coding
928         if (a.getClass().getName().equals("[F")) {
929             ans = (float[]) a;
930         }
931         else {
932             Object[] ia = (Object[]) a;
933             ans = new float[ia.length];
934             for (int i = 0; i < ia.length; i++) {
935                 if (ia[i] == null) {
936                     continue;
937                 }
938                 ans[i] = ((Number) ia[i]).floatValue();
939             }
940         }
941         return ans;
942     }
943 
944     public static double[] convertToDoubleArray(Object a) {
945         double[] ans = null;
946 
947         // conservative coding
948         if (a.getClass().getName().equals("[D")) {
949             ans = (double[]) a;
950         }
951         else {
952             Object[] ia = (Object[]) a;
953             ans = new double[ia.length];
954             for (int i = 0; i < ia.length; i++) {
955                 if (ia[i] == null) {
956                     continue;
957                 }
958                 ans[i] = ((Number) ia[i]).doubleValue();
959             }
960         }
961         return ans;
962     }
963 
964     public static Object convertToPrimitiveArray(Object a, Class type) {
965         if (type == Byte.TYPE) {
966             return convertToByteArray(a);
967         }
968         if (type == Boolean.TYPE) {
969             return convertToBooleanArray(a);
970         }
971         if (type == Short.TYPE) {
972             return convertToShortArray(a);
973         }
974         if (type == Character.TYPE) {
975             return convertToCharArray(a);
976         }
977         if (type == Integer.TYPE) {
978             return convertToIntArray(a);
979         }
980         if (type == Long.TYPE) {
981             return convertToLongArray(a);
982         }
983         if (type == Float.TYPE) {
984             return convertToFloatArray(a);
985         }
986         if (type == Double.TYPE) {
987             return convertToDoubleArray(a);
988         }
989         else {
990             return a;
991         }
992     }
993 
994     /***
995      * get the Integer object from an int. Cached version is used for small ints.
996      *
997      * @param v
998      * @return
999      */
1000     public static Integer integerValue(int v) {
1001         int index = v + INT_CACHE_OFFSET;
1002         if (index >= 0 && index < INT_CACHE_LEN) {
1003             return SMALL_INTEGERS[index];
1004         }
1005         else {
1006             return new Integer(v);
1007         }
1008     }
1009 
1010     private static Integer[] SMALL_INTEGERS;
1011     private static int INT_CACHE_OFFSET = 128, INT_CACHE_LEN = 256;
1012 
1013     static {
1014         SMALL_INTEGERS = new Integer[INT_CACHE_LEN];
1015         for (int i = 0; i < SMALL_INTEGERS.length; i++) {
1016             SMALL_INTEGERS[i] = new Integer(i - INT_CACHE_OFFSET);
1017         }
1018     }
1019 }