View Javadoc

1   /*
2    $Id: InvokerHelper.java,v 1.56 2004/07/10 03:31:42 bran 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.Binding;
49  import groovy.lang.GroovyObject;
50  import groovy.lang.GroovyRuntimeException;
51  import groovy.lang.IntRange;
52  import groovy.lang.MetaClass;
53  import groovy.lang.ObjectRange;
54  import groovy.lang.Script;
55  import groovy.lang.Tuple;
56  import groovy.lang.Writable;
57  
58  import java.io.IOException;
59  import java.io.InputStream;
60  import java.io.InputStreamReader;
61  import java.io.Reader;
62  import java.io.Writer;
63  import java.lang.reflect.Array;
64  import java.math.BigDecimal;
65  import java.math.BigInteger;
66  import java.util.ArrayList;
67  import java.util.Collection;
68  import java.util.HashMap;
69  import java.util.Iterator;
70  import java.util.List;
71  import java.util.Map;
72  import java.util.regex.Matcher;
73  import java.util.regex.Pattern;
74  
75  /***
76   * A static helper class to make bytecode generation easier and act as a facade over the Invoker
77   * 
78   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
79   * @version $Revision: 1.56 $
80   */
81  public class InvokerHelper {
82      public static final Object[] EMPTY_ARGS = {
83      };
84  
85      private static final Object[] EMPTY_MAIN_ARGS = new Object[] { new String[0] };
86  
87      private static final Invoker singleton = new Invoker();
88  
89      private static final Integer ZERO = new Integer(0);
90      private static final Integer MINUS_ONE = new Integer(-1);
91      private static final Integer ONE = new Integer(1);
92  
93      public static MetaClass getMetaClass(Object object) {
94          return getInstance().getMetaClass(object);
95      }
96  
97      public static Invoker getInstance() {
98          return singleton;
99      }
100 
101     public static Object invokeNoArgumentsMethod(Object object, String methodName) {
102         return getInstance().invokeMethod(object, methodName, EMPTY_ARGS);
103     }
104 
105     public static Object invokeMethod(Object object, String methodName, Object arguments) {
106         return getInstance().invokeMethod(object, methodName, arguments);
107     }
108 
109     public static Object invokeSuperMethod(Object object, String methodName, Object arguments) {
110         return getInstance().invokeSuperMethod(object, methodName, arguments);
111     }
112 
113     public static Object invokeMethodSafe(Object object, String methodName, Object arguments) {
114         if (object != null) {
115             return getInstance().invokeMethod(object, methodName, arguments);
116         }
117         return null;
118     }
119 
120     public static Object invokeStaticMethod(String type, String methodName, Object arguments) {
121         return getInstance().invokeStaticMethod(type, methodName, arguments);
122     }
123 
124     public static Object invokeStaticNoArgumentsMethod(String type, String methodName) {
125         return getInstance().invokeStaticMethod(type, methodName, EMPTY_ARGS);
126     }
127 
128     public static Object invokeConstructor(String type, Object arguments) {
129         return getInstance().invokeConstructor(type, arguments);
130     }
131 
132     public static Object invokeConstructorOf(Class type, Object arguments) {
133         return getInstance().invokeConstructorOf(type, arguments);
134     }
135 
136     public static Object invokeNoArgumentsConstructorOf(Class type) {
137         return getInstance().invokeConstructorOf(type, EMPTY_ARGS);
138     }
139 
140     public static Object invokeClosure(Object closure, Object arguments) {
141         return getInstance().invokeMethod(closure, "doCall", arguments);
142     }
143 
144     public static Iterator asIterator(Object collection) {
145         return getInstance().asIterator(collection);
146     }
147 
148     public static Collection asCollection(Object collection) {
149         return getInstance().asCollection(collection);
150     }
151 
152     public static List asList(Object args) {
153         return getInstance().asList(args);
154     }
155 
156     public static String toString(Object arguments) {
157         return getInstance().toString(arguments);
158     }
159 
160     public static String toTypeString(Object[] arguments) {
161         return getInstance().toTypeString(arguments);
162     }
163 
164     public static String inspect(Object self) {
165         return getInstance().inspect(self);
166     }
167 
168     public static Object getProperty(Object object, String property) {
169         return getInstance().getProperty(object, property);
170     }
171 
172     public static Object getPropertySafe(Object object, String property) {
173         if (object != null) {
174             return getInstance().getProperty(object, property);
175         }
176         return null;
177     }
178 
179     public static void setProperty(Object object, String property, Object newValue) {
180         getInstance().setProperty(object, property, newValue);
181     }
182 
183     /***
184      * This is so we don't have to reorder the stack when we call this method.
185      * At some point a better name might be in order.
186      */
187     public static void setProperty2(Object newValue, Object object, String property) {
188         getInstance().setProperty(object, property, newValue);
189     }
190 
191 
192     /***
193      * This is so we don't have to reorder the stack when we call this method.
194      * At some point a better name might be in order.
195      */
196     public static void setGroovyObjectProperty(Object newValue, GroovyObject object, String property) {
197         object.setProperty(property, newValue);
198     }
199     
200     public static Object getGroovyObjectProperty(GroovyObject object, String property) {
201         return object.getProperty(property);
202     }
203     
204     
205     /***
206      * This is so we don't have to reorder the stack when we call this method.
207      * At some point a better name might be in order.
208      */
209     public static void setPropertySafe2(Object newValue, Object object, String property) {
210         if (object != null) {
211             setProperty2(newValue, object, property);
212         }
213     }
214 
215     /***
216      * Provides a hook for type coercion of the given object to the required type
217      * @param type of object to convert the given object to
218      * @param object the object to be converted
219      * @return the original object or a new converted value
220      */
221     public static Object asType(Object object, Class type) {
222         return getInstance().asType(object, type);
223     }
224 
225     public static boolean asBool(Object object) {
226         return getInstance().asBool(object);
227     }
228 
229     public static boolean notObject(Object object) {
230         return !asBool(object);
231     }
232 
233     public static boolean notBoolean(boolean bool) {
234         return !bool;
235     }
236 
237     public static Object negate(Object value) {
238         if (value instanceof Integer) {
239             Integer number = (Integer) value;
240             return integerValue(-number.intValue());
241         }
242         else if (value instanceof Long) {
243             Long number = (Long) value;
244             return new Long(-number.longValue());
245         }
246         else if (value instanceof BigInteger) {
247             return ((BigInteger)value).negate();
248         }
249         else if (value instanceof BigDecimal) {
250             return ((BigDecimal)value).negate();
251         }
252         else if (value instanceof Double) {
253             Double number = (Double) value;
254             return new Double(-number.doubleValue());
255         }
256         else if (value instanceof Float) {
257             Float number = (Float) value;
258             return new Float(-number.floatValue());
259         }
260         else {
261             throw new GroovyRuntimeException(
262                     "Cannot negate type " + value.getClass().getName() + ", value "+value);
263         }
264     }
265 
266     public static boolean isCase(Object switchValue, Object caseExpression) {
267         return asBool(invokeMethod(caseExpression, "isCase", new Object[] { switchValue }));
268     }
269 
270     public static boolean compareIdentical(Object left, Object right) {
271         return left == right;
272     }
273 
274     public static boolean compareEqual(Object left, Object right) {
275         return getInstance().objectsEqual(left, right);
276     }
277 
278     public static Matcher findRegex(Object left, Object right) {
279         return getInstance().objectFindRegex(left, right);
280     }
281 
282     public static boolean matchRegex(Object left, Object right) {
283         return getInstance().objectMatchRegex(left, right);
284     }
285 
286     public static Pattern regexPattern(Object regex) {
287         return getInstance().regexPattern(regex);
288     }
289 
290     public static boolean compareNotEqual(Object left, Object right) {
291         return !getInstance().objectsEqual(left, right);
292     }
293 
294     public static boolean compareLessThan(Object left, Object right) {
295         return getInstance().compareTo(left, right) < 0;
296     }
297 
298     public static boolean compareLessThanEqual(Object left, Object right) {
299         return getInstance().compareTo(left, right) <= 0;
300     }
301 
302     public static boolean compareGreaterThan(Object left, Object right) {
303         return getInstance().compareTo(left, right) > 0;
304     }
305 
306     public static boolean compareGreaterThanEqual(Object left, Object right) {
307         return getInstance().compareTo(left, right) >= 0;
308     }
309 
310     public static Integer compareTo(Object left, Object right) {
311         int answer = getInstance().compareTo(left, right);
312         if (answer == 0) {
313             return ZERO;
314         }
315         else {
316             return answer > 0 ? ONE : MINUS_ONE;
317         }
318     }
319 
320     public static Tuple createTuple(Object[] array) {
321         return new Tuple(array);
322     }
323 
324     public static List createList(Object[] values) {
325         ArrayList answer = new ArrayList(values.length);
326         for (int i = 0; i < values.length; i++) {
327             answer.add(values[i]);
328         }
329         return answer;
330     }
331 
332     public static Map createMap(Object[] values) {
333         Map answer = new HashMap(values.length / 2);
334         int i = 0;
335         while (i < values.length) {
336             answer.put(values[i++], values[i++]);
337         }
338         return answer;
339     }
340 
341     public static List createRange(Object from, Object to, boolean inclusive) {
342         if (!inclusive) {
343             if (compareGreaterThan(from, to)) {
344                 to = invokeMethod(to, "next", EMPTY_ARGS);
345             }
346             else {
347                 to = invokeMethod(to, "previous", EMPTY_ARGS);
348             }
349         }
350         if (from instanceof Integer && to instanceof Integer) {
351             return new IntRange(asInt(from), asInt(to));
352         }
353         else {
354             return new ObjectRange((Comparable) from, (Comparable) to);
355         }
356     }
357 
358     public static int asInt(Object value) {
359         return getInstance().asInt(value);
360     }
361 
362     public static void assertFailed(Object expression, Object message) {
363         if (message == null || "".equals(message)) {
364             throw new AssertionError("Expression: " + expression);
365         }
366         else {
367             throw new AssertionError("" + message + ". Expression: " + expression);
368         }
369     }
370 
371     public static Object runScript(Class scriptClass, String[] args) {
372         Binding context = new Binding(args);
373         Script script = createScript(scriptClass, context);
374         return invokeMethod(script, "run", EMPTY_ARGS);
375     }
376 
377     public static Script createScript(Class scriptClass, Binding context) {
378         try {
379             final GroovyObject object = (GroovyObject) scriptClass.newInstance();
380             Script script = null;
381             if (object instanceof Script) {
382                 script = (Script) object;
383             }
384             else {
385                 // it could just be a class, so lets wrap it in a Script wrapper
386                 // though the bindings will be ignored
387                 script = new Script() {
388                     public Object run() {
389                         object.invokeMethod("main", EMPTY_MAIN_ARGS);
390                         return null;
391                     }
392                 };
393                 setProperties(object, context.getVariables());
394             }
395             script.setBinding(context);
396             return script;
397         }
398         catch (Exception e) {
399             throw new GroovyRuntimeException(
400                 "Failed to create Script instance for class: " + scriptClass + ". Reason: " + e,
401                 e);
402         }
403     }
404 
405     /***
406      * Sets the properties on the given object
407      * 
408      * @param object
409      * @param map
410      */
411     public static void setProperties(Object object, Map map) {
412         getMetaClass(object).setProperties(object, map);
413     }
414 
415     public static String getVersion() {
416         String version = null;
417         Package p = Package.getPackage("groovy.lang");
418         if (p != null) {
419             version = p.getImplementationVersion();
420         }
421         if (version == null) {
422             version = "";
423         }
424         return version;
425     }
426 
427     /***
428      * Allows conversion of arrays into a mutable List
429      * 
430      * @return the array as a List
431      */
432     protected static List primitiveArrayToList(Object array) {
433         int size = Array.getLength(array);
434         List list = new ArrayList(size);
435         for (int i = 0; i < size; i++) {
436             list.add(Array.get(array, i));
437         }
438         return list;
439     }
440 
441     /***
442      * Writes the given object to the given stream
443      */
444     public static void write(Writer out, Object object) throws IOException {
445         if (object instanceof String) {
446             out.write((String) object);
447         }
448         else if (object instanceof Writable) {
449             Writable writable = (Writable) object;
450             writable.writeTo(out);
451         }
452         else if (object instanceof InputStream || object instanceof Reader) {
453             // Copy stream to stream
454             Reader reader;
455             if (object instanceof InputStream) {
456                 reader = new InputStreamReader((InputStream)object);
457             } else {
458                 reader = (Reader) object;
459             }
460             char[] chars = new char[8192];
461             int i;
462             while ((i = reader.read(chars)) != -1) {
463                 out.write(chars, 0, i);
464             }
465             reader.close();
466         }
467         else {
468             out.write(toString(object));
469         }
470     }
471 
472     public static Object box(boolean value) {
473         return value ? Boolean.TRUE : Boolean.FALSE;
474     }
475 
476     public static Object box(byte value) {
477         return new Byte(value);
478     }
479 
480     public static Object box(char value) {
481         return new Character(value);
482     }
483     
484     public static Object box(short value) {
485         return new Short(value);
486     }
487     
488     public static Object box(int value) {
489         return integerValue(value);
490     }
491     
492     public static Object box(long value) {
493         return new Long(value);
494     }
495     
496     public static Object box(float value) {
497         return new Float(value);
498     }
499     
500     public static Object box(double value) {
501         return new Double(value);
502     }
503     
504     public static byte byteUnbox(Object value) {
505         Number n = (Number) asType(value, Byte.class);
506         return n.byteValue();
507     }
508     
509     public static char charUnbox(Object value) {
510         Character n = (Character) asType(value, Character.class);
511         return n.charValue();
512     }
513     
514     public static short shortUnbox(Object value) {
515         Number n = (Number) asType(value, Short.class);
516         return n.shortValue();
517     }
518     
519     public static int intUnbox(Object value) {
520         Number n = (Number) asType(value, Integer.class);
521         return n.intValue();
522     }
523     
524     public static boolean booleanUnbox(Object value) {
525         Boolean n = (Boolean) asType(value, Boolean.class);
526         return n.booleanValue();
527     }
528     
529     public static long longUnbox(Object value) {
530         Number n = (Number) asType(value, Long.class);
531         return n.longValue();
532     }
533     
534     public static float floatUnbox(Object value) {
535         Number n = (Number) asType(value, Float.class);
536         return n.floatValue();
537     }
538     
539     public static double doubleUnbox(Object value) {
540         Number n = (Number) asType(value, Double.class);
541         return n.doubleValue();
542     }
543 
544     /***
545      *
546      * @param a array of primitives
547      * @param type component type of the array
548      * @return
549      */
550     public static Object[] convertPrimitiveArray(Object a, Class type) {
551 //        System.out.println("a.getClass() = " + a.getClass());
552         Object[] ans = null;
553         String elemType = type.getName();
554         if (elemType.equals("int")) {
555             // conservative coding
556             if (a.getClass().getName().equals("[Ljava.lang.Integer;")) {
557                 ans = (Integer[])a;
558             }
559             else {
560                 int[] ia = (int[])a;
561                 ans = new Integer[ia.length];
562                 for (int i = 0; i < ia.length; i++) {
563                     int e = ia[i];
564                     ans[i] = integerValue(e);
565                 }
566             }
567         }
568         else if(elemType.equals("char")) {
569             if (a.getClass().getName().equals("[Ljava.lang.Character;")) {
570                 ans = (Character[])a;
571             }
572             else {
573                 char[] ia = (char[])a;
574                 ans = new Character[ia.length];
575                 for (int i = 0; i < ia.length; i++) {
576                     char e = ia[i];
577                     ans[i] = new Character(e);
578                 }
579             }
580         }
581         else if(elemType.equals("boolean")) {
582             if (a.getClass().getName().equals("[Ljava.lang.Boolean;")) {
583                 ans = (Boolean[])a;
584             }
585             else {
586                 boolean[] ia = (boolean[])a;
587                 ans = new Boolean[ia.length];
588                 for (int i = 0; i < ia.length; i++) {
589                     boolean e = ia[i];
590                     ans[i] = new Boolean(e);
591                 }
592             }
593         }
594         else if(elemType.equals("byte")) {
595             if (a.getClass().getName().equals("[Ljava.lang.Byte;")) {
596                 ans = (Byte[])a;
597             }
598             else {
599                 byte[] ia = (byte[])a;
600                 ans = new Byte[ia.length];
601                 for (int i = 0; i < ia.length; i++) {
602                     byte e = ia[i];
603                     ans[i] = new Byte(e);
604                 }
605             }
606         }
607         else if(elemType.equals("short")) {
608             if (a.getClass().getName().equals("[Ljava.lang.Short;")) {
609                 ans = (Short[])a;
610             }
611             else {
612                 short[] ia = (short[])a;
613                 ans = new Short[ia.length];
614                 for (int i = 0; i < ia.length; i++) {
615                     short e = ia[i];
616                     ans[i] = new Short(e);
617                 }
618             }
619         }
620         else if(elemType.equals("float")) {
621             if (a.getClass().getName().equals("[Ljava.lang.Float;")) {
622                 ans = (Float[])a;
623             }
624             else {
625                 float[] ia = (float[])a;
626                 ans = new Float[ia.length];
627                 for (int i = 0; i < ia.length; i++) {
628                     float e = ia[i];
629                     ans[i] = new Float(e);
630                 }
631             }
632         }
633         else if(elemType.equals("long")) {
634             if (a.getClass().getName().equals("[Ljava.lang.Long;")) {
635                 ans = (Long[])a;
636             }
637             else {
638                 long[] ia = (long[])a;
639                 ans = new Long[ia.length];
640                 for (int i = 0; i < ia.length; i++) {
641                     long e = ia[i];
642                     ans[i] = new Long(e);
643                 }
644             }
645         }
646         else if(elemType.equals("double")) {
647             if (a.getClass().getName().equals("[Ljava.lang.Double;")) {
648                 ans = (Double[])a;
649             }
650             else {
651                 double[] ia = (double[])a;
652                 ans = new Double[ia.length];
653                 for (int i = 0; i < ia.length; i++) {
654                     double e = ia[i];
655                     ans[i] = new Double(e);
656                 }
657             }
658         }
659         return ans;
660     }
661 
662     public static int[] convertToIntArray(Object a){
663         int[] ans = null;
664 
665         // conservative coding
666         if (a.getClass().getName().equals("[I")) {
667             ans = (int[])a;
668         }
669         else {
670             Object[] ia = (Object[])a;
671             ans = new int[ia.length];
672             for (int i = 0; i < ia.length; i++) {
673                 ans[i] = ((Number)ia[i]).intValue();
674             }
675         }
676         return ans;
677     }
678 
679     public static boolean[] convertToBooleanArray(Object a){
680         boolean[] ans = null;
681 
682         // conservative coding
683         if (a.getClass().getName().equals("[Z")) {
684             ans = (boolean[])a;
685         }
686         else {
687             Object[] ia = (Object[])a;
688             ans = new boolean[ia.length];
689             for (int i = 0; i < ia.length; i++) {
690                 ans[i] = ((Boolean)ia[i]).booleanValue();
691             }
692         }
693         return ans;
694     }
695     public static byte[] convertToByteArray(Object a){
696         byte[] ans = null;
697 
698         // conservative coding
699         if (a.getClass().getName().equals("[B")) {
700             ans = (byte[])a;
701         }
702         else {
703             Object[] ia = (Object[])a;
704             ans = new byte[ia.length];
705             for (int i = 0; i < ia.length; i++) {
706                 ans[i] = ((Number)ia[i]).byteValue();
707             }
708         }
709         return ans;
710     }
711     public static short[] convertToShortArray(Object a){
712         short[] ans = null;
713 
714         // conservative coding
715         if (a.getClass().getName().equals("[S")) {
716             ans = (short[])a;
717         }
718         else {
719             Object[] ia = (Object[])a;
720             ans = new short[ia.length];
721             for (int i = 0; i < ia.length; i++) {
722                 ans[i] = ((Number)ia[i]).shortValue();
723             }
724         }
725         return ans;
726     }
727 
728     public static char[] convertToCharArray(Object a){
729         char[] ans = null;
730 
731         // conservative coding
732         if (a.getClass().getName().equals("[C")) {
733             ans = (char[])a;
734         }
735         else {
736             Object[] ia = (Object[])a;
737             ans = new char[ia.length];
738             for (int i = 0; i < ia.length; i++) {
739                 ans[i] = ((Character)ia[i]).charValue();
740             }
741         }
742         return ans;
743     }
744 
745     public static long[] convertToLongArray(Object a){
746         long[] ans = null;
747 
748         // conservative coding
749         if (a.getClass().getName().equals("[J")) {
750             ans = (long[])a;
751         }
752         else {
753             Object[] ia = (Object[])a;
754             ans = new long[ia.length];
755             for (int i = 0; i < ia.length; i++) {
756                 ans[i] = ((Number)ia[i]).longValue();
757             }
758         }
759         return ans;
760     }
761 
762     public static float[] convertToFloatArray(Object a){
763         float[] ans = null;
764 
765         // conservative coding
766         if (a.getClass().getName().equals("[F")) {
767             ans = (float[])a;
768         }
769         else {
770             Object[] ia = (Object[])a;
771             ans = new float[ia.length];
772             for (int i = 0; i < ia.length; i++) {
773                 ans[i] = ((Number)ia[i]).floatValue();
774             }
775         }
776         return ans;
777     }
778 
779     public static double[] convertToDoubleArray(Object a){
780         double[] ans = null;
781 
782         // conservative coding
783         if (a.getClass().getName().equals("[D")) {
784             ans = (double[])a;
785         }
786         else {
787             Object[] ia = (Object[])a;
788             ans = new double[ia.length];
789             for (int i = 0; i < ia.length; i++) {
790                 ans[i] = ((Number)ia[i]).doubleValue();
791             }
792         }
793         return ans;
794     }
795 
796     public static Object convertToPrimitiveArray(Object a, Class type) {
797         if (type == Byte.TYPE)
798             return convertToByteArray(a);
799         if (type == Boolean.TYPE)
800             return convertToBooleanArray(a);
801         if (type == Short.TYPE)
802             return convertToShortArray(a);
803         if (type == Character.TYPE)
804             return convertToCharArray(a);
805         if (type == Integer.TYPE)
806             return convertToIntArray(a);
807         if (type == Long.TYPE)
808             return convertToLongArray(a);
809         if (type == Float.TYPE)
810             return convertToFloatArray(a);
811         if (type == Double.TYPE)
812             return convertToDoubleArray(a);
813         else
814             return a;
815     }
816 
817     /***
818      * get the Integer object from an int. Cached version is used for small ints.
819      * @param v
820      * @return
821      */
822     public static Integer integerValue(int v) {
823         int index = v + INT_CACHE_OFFSET;
824         if (index >= 0 && index < INT_CACHE_LEN ) {
825             return SMALL_INTEGERS[index];
826         }
827         else {
828             return new Integer(v);
829         }
830     }
831 
832     private static Integer[] SMALL_INTEGERS;
833     private static int INT_CACHE_OFFSET = 128, INT_CACHE_LEN = 256;
834     static {
835         SMALL_INTEGERS = new Integer[INT_CACHE_LEN];
836         for (int i = 0; i < SMALL_INTEGERS.length; i++) {
837             SMALL_INTEGERS[i] = new Integer(i - INT_CACHE_OFFSET);
838         }
839     }
840 }