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