1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.runtime;
47
48 import groovy.lang.Closure;
49 import groovy.lang.GroovyObject;
50 import groovy.lang.GroovyRuntimeException;
51 import groovy.lang.MetaClass;
52 import groovy.lang.MetaClassRegistry;
53 import groovy.lang.MissingMethodException;
54 import groovy.lang.Range;
55 import groovy.lang.SpreadList;
56 import groovy.lang.Tuple;
57 import org.apache.xml.serialize.OutputFormat;
58 import org.apache.xml.serialize.XMLSerializer;
59 import org.w3c.dom.Element;
60 import org.w3c.dom.Node;
61 import org.w3c.dom.NodeList;
62
63 import java.io.File;
64 import java.io.IOException;
65 import java.io.StringWriter;
66 import java.lang.reflect.Array;
67 import java.lang.reflect.Method;
68 import java.math.BigDecimal;
69 import java.security.AccessController;
70 import java.security.PrivilegedAction;
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.Collection;
74 import java.util.Collections;
75 import java.util.Enumeration;
76 import java.util.Iterator;
77 import java.util.List;
78 import java.util.Map;
79 import java.util.NoSuchElementException;
80 import java.util.regex.Matcher;
81 import java.util.regex.Pattern;
82
83 /***
84 * A helper class to invoke methods or extract properties on arbitrary Java objects dynamically
85 *
86 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
87 * @version $Revision: 1.71 $
88 */
89 public class Invoker {
90
91 protected static final Object[] EMPTY_ARGUMENTS = {
92 };
93 protected static final Class[] EMPTY_TYPES = {
94 };
95
96 public MetaClassRegistry getMetaRegistry() {
97 return metaRegistry;
98 }
99
100 private MetaClassRegistry metaRegistry = new MetaClassRegistry();
101
102 public MetaClass getMetaClass(Object object) {
103 return metaRegistry.getMetaClass(object.getClass());
104 }
105
106 /***
107 * Invokes the given method on the object.
108 *
109 * @param object
110 * @param methodName
111 * @param arguments
112 * @return
113 */
114 public Object invokeMethod(Object object, String methodName, Object arguments) {
115
116
117
118
119
120
121
122
123
124
125
126
127 if (object == null) {
128 throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
129 }
130
131
132 if (object instanceof Class) {
133 Class theClass = (Class) object;
134 MetaClass metaClass = metaRegistry.getMetaClass(theClass);
135 return metaClass.invokeStaticMethod(object, methodName, asArray(arguments));
136 }
137 else
138 {
139
140 if (!(object instanceof GroovyObject)) {
141 Class theClass = object.getClass();
142 MetaClass metaClass = metaRegistry.getMetaClass(theClass);
143 return metaClass.invokeMethod(object, methodName, asArray(arguments));
144 }
145
146 else {
147
148 if (object instanceof Closure) {
149 Closure closure = (Closure) object;
150 return closure.invokeMethod(methodName, asArray(arguments));
151 }
152
153
154 else {
155 GroovyObject groovy = (GroovyObject) object;
156 try {
157
158 return groovy.getMetaClass().invokeMethod(object, methodName, asArray(arguments));
159 }
160 catch (MissingMethodException e) {
161 if (e.getMethod().equals(methodName) && object.getClass() == e.getType()) {
162
163 return groovy.invokeMethod(methodName, asArray(arguments));
164 }
165 else {
166 throw e;
167 }
168 }
169 }
170 }
171 }
172 }
173
174 public Object invokeSuperMethod(Object object, String methodName, Object arguments) {
175 if (object == null) {
176 throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
177 }
178
179 Class theClass = object.getClass();
180
181 MetaClass metaClass = metaRegistry.getMetaClass(theClass.getSuperclass());
182 return metaClass.invokeMethod(object, methodName, asArray(arguments));
183 }
184
185 public Object invokeStaticMethod(String type, String method, Object arguments) {
186 MetaClass metaClass = metaRegistry.getMetaClass(loadClass(type));
187 List argumentList = asList(arguments);
188 return metaClass.invokeStaticMethod(null, method, asArray(arguments));
189 }
190
191 public Object invokeConstructor(String type, Object arguments) {
192
193 return invokeConstructorOf(loadClass(type), arguments);
194 }
195
196 public Object invokeConstructorOf(Class type, Object arguments) {
197 MetaClass metaClass = metaRegistry.getMetaClass(type);
198 return metaClass.invokeConstructor(asArray(arguments));
199 }
200
201 /***
202 * Converts the given object into an array; if its an array then just
203 * cast otherwise wrap it in an array
204 */
205 public Object[] asArray(Object arguments) {
206 if (arguments == null) {
207 return EMPTY_ARGUMENTS;
208 }
209 else if (arguments instanceof Tuple) {
210 Tuple tuple = (Tuple) arguments;
211 Object[] objects = tuple.toArray();
212 ArrayList array = new ArrayList();
213 for (int i = 0; i < objects.length; i++) {
214 if (objects[i] instanceof SpreadList) {
215 SpreadList slist = (SpreadList) objects[i];
216 for (int j = 0; j < slist.size(); j++) {
217 array.add(slist.get(j));
218 }
219 }
220 else {
221 array.add(objects[i]);
222 }
223 }
224 return array.toArray();
225 }
226 else if (arguments instanceof Object[]) {
227 Object[] objects = (Object[]) arguments;
228 ArrayList array = new ArrayList();
229 for (int i = 0; i < objects.length; i++) {
230 if (objects[i] instanceof SpreadList) {
231 SpreadList slist = (SpreadList) objects[i];
232 for (int j = 0; j < slist.size(); j++) {
233 array.add(slist.get(j));
234 }
235 }
236 else {
237 array.add(objects[i]);
238 }
239 }
240 return array.toArray();
241 }
242 else {
243 if (arguments instanceof SpreadList) {
244 ArrayList array = new ArrayList();
245 SpreadList slist = (SpreadList) arguments;
246 for (int j = 0; j < slist.size(); j++) {
247 array.add(slist.get(j));
248 }
249 return array.toArray();
250 }
251 else {
252 return new Object[]{arguments};
253 }
254 }
255 }
256
257 public List asList(Object value) {
258 if (value == null) {
259 return Collections.EMPTY_LIST;
260 }
261 else if (value instanceof List) {
262 return (List) value;
263 }
264 else if (value.getClass().isArray()) {
265 return Arrays.asList((Object[]) value);
266 }
267 else if (value instanceof Enumeration) {
268 List answer = new ArrayList();
269 for (Enumeration e = (Enumeration) value; e.hasMoreElements();) {
270 answer.add(e.nextElement());
271 }
272 return answer;
273 }
274 else {
275
276 return Collections.singletonList(value);
277 }
278 }
279
280 /***
281 * @param arguments
282 * @return
283 */
284 public Collection asCollection(Object value) {
285 if (value == null) {
286 return Collections.EMPTY_LIST;
287 }
288 else if (value instanceof Collection) {
289 return (Collection) value;
290 }
291 else if (value instanceof Map) {
292 Map map = (Map) value;
293 return map.entrySet();
294 }
295 else if (value.getClass().isArray()) {
296 if (value.getClass().getComponentType().isPrimitive()) {
297 return InvokerHelper.primitiveArrayToList(value);
298 }
299 return Arrays.asList((Object[]) value);
300 }
301 else if (value instanceof MethodClosure) {
302 MethodClosure method = (MethodClosure) value;
303 IteratorClosureAdapter adapter = new IteratorClosureAdapter(method.getDelegate());
304 method.call(adapter);
305 return adapter.asList();
306 }
307 else if (value instanceof String) {
308 return DefaultGroovyMethods.toList((String) value);
309 }
310 else if (value instanceof File) {
311 try {
312 return DefaultGroovyMethods.readLines((File) value);
313 }
314 catch (IOException e) {
315 throw new GroovyRuntimeException("Error reading file: " + value, e);
316 }
317 }
318 else {
319
320 return Collections.singletonList(value);
321 }
322 }
323
324 public Iterator asIterator(Object value) {
325 if (value == null) {
326 return Collections.EMPTY_LIST.iterator();
327 }
328 if (value instanceof Iterator) {
329 return (Iterator) value;
330 }
331 if (value instanceof NodeList) {
332 final NodeList nodeList = (NodeList) value;
333 return new Iterator() {
334 private int current = 0;
335
336 public boolean hasNext() {
337 return current < nodeList.getLength();
338 }
339
340 public Object next() {
341 Node node = nodeList.item(current++);
342 return node;
343 }
344
345 public void remove() {
346 throw new UnsupportedOperationException("Cannot remove() from an Enumeration");
347 }
348 };
349 }
350 else if (value instanceof Enumeration) {
351 final Enumeration enumeration = (Enumeration) value;
352 return new Iterator() {
353 private Object last;
354
355 public boolean hasNext() {
356 return enumeration.hasMoreElements();
357 }
358
359 public Object next() {
360 last = enumeration.nextElement();
361 return last;
362 }
363
364 public void remove() {
365 throw new UnsupportedOperationException("Cannot remove() from an Enumeration");
366 }
367 };
368 }
369 else if (value instanceof Matcher) {
370 final Matcher matcher = (Matcher) value;
371 return new Iterator() {
372 private boolean found = false;
373 private boolean done = false;
374
375 public boolean hasNext() {
376 if (done) {
377 return false;
378 }
379 if (!found) {
380 found = matcher.find();
381 if (!found) {
382 done = true;
383 }
384 }
385 return found;
386 }
387
388 public Object next() {
389 if (!found) {
390 if (!hasNext()) {
391 throw new NoSuchElementException();
392 }
393 }
394 found = false;
395 return matcher.group();
396 }
397
398 public void remove() {
399 throw new UnsupportedOperationException();
400 }
401 };
402 }
403 else {
404 try {
405
406 final Method method = value.getClass().getMethod("iterator", EMPTY_TYPES);
407
408 if (method != null) {
409 AccessController.doPrivileged(new PrivilegedAction() {
410 public Object run() {
411 method.setAccessible(true);
412 return null;
413 }
414 });
415
416 return (Iterator) method.invoke(value, EMPTY_ARGUMENTS);
417 }
418 }
419 catch (Exception e) {
420
421 }
422 }
423 return asCollection(value).iterator();
424 }
425
426 /***
427 * @return true if the two objects are null or the objects are equal
428 */
429 public boolean objectsEqual(Object left, Object right) {
430 if (left == right) {
431 return true;
432 }
433 if (left != null) {
434 if (right == null) {
435 return false;
436 }
437 if (left instanceof Comparable) {
438 return compareTo(left, right) == 0;
439 }
440 else {
441 return left.equals(right);
442 }
443 }
444 return false;
445 }
446
447 public String inspect(Object self) {
448 return format(self, true);
449 }
450
451 /***
452 * Compares the two objects handling nulls gracefully and performing numeric type coercion if required
453 */
454 public int compareTo(Object left, Object right) {
455
456 if (left == right) {
457 return 0;
458 }
459 if (left == null) {
460 return -1;
461 }
462 else if (right == null) {
463 return 1;
464 }
465 if (left instanceof Comparable) {
466 if (left instanceof Number) {
467 if (isValidCharacterString(right)) {
468 return asCharacter((Number) left).compareTo(asCharacter((String) right));
469 }
470 return DefaultGroovyMethods.compareTo((Number) left, asNumber(right));
471 }
472 else if (left instanceof Character) {
473 if (isValidCharacterString(right)) {
474 return ((Character) left).compareTo(asCharacter((String) right));
475 }
476 else if (right instanceof Number) {
477 return ((Character) left).compareTo(asCharacter((Number) right));
478 }
479 }
480 else if (right instanceof Number) {
481 if (isValidCharacterString(left)) {
482 return asCharacter((String) left).compareTo(asCharacter((Number) right));
483 }
484 return DefaultGroovyMethods.compareTo(asNumber(left), (Number) right);
485 }
486 else if (left instanceof String && right instanceof Character) {
487 return ((String) left).compareTo(right.toString());
488 }
489 Comparable comparable = (Comparable) left;
490 return comparable.compareTo(right);
491 }
492 if (left.getClass().isArray()) {
493 Collection leftList = asCollection(left);
494 if (right.getClass().isArray()) {
495 right = asCollection(right);
496 }
497 return ((Comparable) leftList).compareTo(right);
498 }
499 /*** todo we might wanna do some type conversion here */
500 throw new GroovyRuntimeException("Cannot compare values: " + left + " and " + right);
501 }
502
503 /***
504 * A helper method to provide some better toString() behaviour such as turning arrays
505 * into tuples
506 */
507 public String toString(Object arguments) {
508 return format(arguments, false);
509 }
510
511 /***
512 * A helper method to format the arguments types as a comma-separated list
513 */
514 public String toTypeString(Object[] arguments) {
515 if (arguments == null) {
516 return "null";
517 }
518 StringBuffer argBuf = new StringBuffer();
519 for (int i = 0; i < arguments.length; i++) {
520 if (i > 0) {
521 argBuf.append(", ");
522 }
523 argBuf.append(arguments[i] != null ? arguments[i].getClass().getName() : "null");
524 }
525 return argBuf.toString();
526 }
527
528 protected String format(Object arguments, boolean verbose) {
529 if (arguments == null) {
530 return "null";
531 }
532 else if (arguments.getClass().isArray()) {
533 return format(asCollection(arguments), verbose);
534 }
535 else if (arguments instanceof Range) {
536 Range range = (Range) arguments;
537 if (verbose) {
538 return range.inspect();
539 }
540 else {
541 return range.toString();
542 }
543 }
544 else if (arguments instanceof List) {
545 List list = (List) arguments;
546 StringBuffer buffer = new StringBuffer("[");
547 boolean first = true;
548 for (Iterator iter = list.iterator(); iter.hasNext();) {
549 if (first) {
550 first = false;
551 }
552 else {
553 buffer.append(", ");
554 }
555 buffer.append(format(iter.next(), verbose));
556 }
557 buffer.append("]");
558 return buffer.toString();
559 }
560 else if (arguments instanceof Map) {
561 Map map = (Map) arguments;
562 if (map.isEmpty()) {
563 return "[:]";
564 }
565 StringBuffer buffer = new StringBuffer("[");
566 boolean first = true;
567 for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
568 if (first) {
569 first = false;
570 }
571 else {
572 buffer.append(", ");
573 }
574 Map.Entry entry = (Map.Entry) iter.next();
575 buffer.append(format(entry.getKey(), verbose));
576 buffer.append(":");
577 buffer.append(format(entry.getValue(), verbose));
578 }
579 buffer.append("]");
580 return buffer.toString();
581 }
582 else if (arguments instanceof Element) {
583 Element node = (Element) arguments;
584 OutputFormat format = new OutputFormat(node.getOwnerDocument());
585 format.setOmitXMLDeclaration(true);
586 format.setIndenting(true);
587 format.setLineWidth(0);
588 format.setPreserveSpace(true);
589 StringWriter sw = new StringWriter();
590 XMLSerializer serializer = new XMLSerializer(sw, format);
591 try {
592 serializer.asDOMSerializer();
593 serializer.serialize(node);
594 }
595 catch (IOException e) {
596 }
597 return sw.toString();
598 }
599 else if (arguments instanceof String) {
600 if (verbose) {
601 return "\"" + arguments + "\"";
602 }
603 else {
604 return (String) arguments;
605 }
606 }
607 else {
608 return arguments.toString();
609 }
610 }
611
612 /***
613 * Looks up the given property of the given object
614 */
615 public Object getProperty(Object object, String property) {
616 if (object == null) {
617 throw new NullPointerException("Cannot get property: " + property + " on null object");
618 }
619 else if (object instanceof GroovyObject) {
620 GroovyObject pogo = (GroovyObject) object;
621 return pogo.getProperty(property);
622 }
623 else if (object instanceof Map) {
624 Map map = (Map) object;
625 return map.get(property);
626 }
627 else {
628 return metaRegistry.getMetaClass(object.getClass()).getProperty(object, property);
629 }
630 }
631
632 /***
633 * Sets the property on the given object
634 */
635 public void setProperty(Object object, String property, Object newValue) {
636 if (object == null) {
637 throw new GroovyRuntimeException("Cannot set property on null object");
638 }
639 else if (object instanceof GroovyObject) {
640 GroovyObject pogo = (GroovyObject) object;
641 pogo.setProperty(property, newValue);
642 }
643 else if (object instanceof Map) {
644 Map map = (Map) object;
645 map.put(property, newValue);
646 }
647 else {
648 metaRegistry.getMetaClass(object.getClass()).setProperty(object, property, newValue);
649 }
650 }
651
652 /***
653 * Looks up the given attribute (field) on the given object
654 */
655 public Object getAttribute(Object object, String attribute) {
656 if (object == null) {
657 throw new NullPointerException("Cannot get attribute: " + attribute + " on null object");
658
659 /***
660 } else if (object instanceof GroovyObject) {
661 GroovyObject pogo = (GroovyObject) object;
662 return pogo.getAttribute(attribute);
663 } else if (object instanceof Map) {
664 Map map = (Map) object;
665 return map.get(attribute);
666 */
667 }
668 else {
669 return metaRegistry.getMetaClass(object.getClass()).getAttribute(object, attribute);
670 }
671 }
672
673 /***
674 * Sets the given attribute (field) on the given object
675 */
676 public void setAttribute(Object object, String attribute, Object newValue) {
677 if (object == null) {
678 throw new GroovyRuntimeException("Cannot set attribute on null object");
679
680
681
682
683
684
685
686
687 }
688 else {
689 metaRegistry.getMetaClass(object.getClass()).setAttribute(object, attribute, newValue);
690 }
691 }
692
693 /***
694 * Returns the method pointer for the given object name
695 */
696 public Closure getMethodPointer(Object object, String methodName) {
697 if (object == null) {
698 throw new NullPointerException("Cannot access method pointer for '" + methodName + "' on null object");
699 }
700 return metaRegistry.getMetaClass(object.getClass()).getMethodPointer(object, methodName);
701 }
702
703
704 /***
705 * Attempts to load the given class via name using the current class loader
706 * for this code or the thread context class loader
707 */
708 protected Class loadClass(String type) {
709 try {
710 return getClass().getClassLoader().loadClass(type);
711 }
712 catch (ClassNotFoundException e) {
713 try {
714 return Thread.currentThread().getContextClassLoader().loadClass(type);
715 }
716 catch (ClassNotFoundException e2) {
717 try {
718 return Class.forName(type);
719 }
720 catch (ClassNotFoundException e3) {
721 }
722 }
723 throw new GroovyRuntimeException("Could not load type: " + type, e);
724 }
725 }
726
727 /***
728 * Find the right hand regex within the left hand string and return a matcher.
729 *
730 * @param left string to compare
731 * @param right regular expression to compare the string to
732 * @return
733 */
734 public Matcher objectFindRegex(Object left, Object right) {
735 String stringToCompare;
736 if (left instanceof String) {
737 stringToCompare = (String) left;
738 }
739 else {
740 stringToCompare = toString(left);
741 }
742 String regexToCompareTo;
743 if (right instanceof String) {
744 regexToCompareTo = (String) right;
745 }
746 else if (right instanceof Pattern) {
747 Pattern pattern = (Pattern) right;
748 return pattern.matcher(stringToCompare);
749 }
750 else {
751 regexToCompareTo = toString(right);
752 }
753 Matcher matcher = Pattern.compile(regexToCompareTo).matcher(stringToCompare);
754 return matcher;
755 }
756
757 /***
758 * Find the right hand regex within the left hand string and return a matcher.
759 *
760 * @param left string to compare
761 * @param right regular expression to compare the string to
762 * @return
763 */
764 public boolean objectMatchRegex(Object left, Object right) {
765 Pattern pattern;
766 if (right instanceof Pattern) {
767 pattern = (Pattern) right;
768 }
769 else {
770 pattern = Pattern.compile(toString(right));
771 }
772 String stringToCompare = toString(left);
773 Matcher matcher = pattern.matcher(stringToCompare);
774 RegexSupport.setLastMatcher(matcher);
775 return matcher.matches();
776 }
777
778 /***
779 * Compile a regular expression from a string.
780 *
781 * @param regex
782 * @return
783 */
784 public Pattern regexPattern(Object regex) {
785 return Pattern.compile(regex.toString());
786 }
787
788 public Object asType(Object object, Class type) {
789 if (object == null) {
790 return null;
791 }
792
793
794 if (type.isArray()) {
795 return asArray(object, type);
796
797 }
798 if (type.isInstance(object)) {
799 return object;
800 }
801 if (type.isAssignableFrom(Collection.class)) {
802 if (object.getClass().isArray()) {
803
804
805 Collection answer = null;
806 try {
807 answer = (Collection) type.newInstance();
808 }
809 catch (Exception e) {
810 throw new ClassCastException("Could not instantiate instance of: " + type.getName() + ". Reason: " + e);
811 }
812
813
814 int length = Array.getLength(object);
815 for (int i = 0; i < length; i++) {
816 Object element = Array.get(object, i);
817 answer.add(element);
818 }
819 return answer;
820 }
821 }
822 if (type.equals(String.class)) {
823 return object.toString();
824 }
825 if (type.equals(Character.class)) {
826 if (object instanceof Number) {
827 return asCharacter((Number) object);
828 }
829 else {
830 String text = object.toString();
831 if (text.length() == 1) {
832 return new Character(text.charAt(0));
833 }
834 else {
835 throw new ClassCastException("Cannot cast: " + text + " to a Character");
836 }
837 }
838 }
839 if (Number.class.isAssignableFrom(type)) {
840 if (object instanceof Character) {
841 return new Integer(((Character) object).charValue());
842 }
843 else if (object instanceof String) {
844 String c = (String) object;
845 if (c.length() == 1) {
846 return new Integer(c.charAt(0));
847 }
848 else {
849 throw new ClassCastException("Cannot cast: '" + c + "' to an Integer");
850 }
851 }
852 }
853 if (object instanceof Number) {
854 Number n = (Number) object;
855 if (type.isPrimitive()) {
856 if (type == byte.class) {
857 return new Byte(n.byteValue());
858 }
859 if (type == char.class) {
860 return new Character((char) n.intValue());
861 }
862 if (type == short.class) {
863 return new Short(n.shortValue());
864 }
865 if (type == int.class) {
866 return new Integer(n.intValue());
867 }
868 if (type == long.class) {
869 return new Long(n.longValue());
870 }
871 if (type == float.class) {
872 return new Float(n.floatValue());
873 }
874 if (type == double.class) {
875 Double answer = new Double(n.doubleValue());
876
877 if (!(n instanceof Double) && (answer.doubleValue() == Double.NEGATIVE_INFINITY
878 || answer.doubleValue() == Double.POSITIVE_INFINITY)) {
879 throw new GroovyRuntimeException("Automatic coercion of " + n.getClass().getName()
880 + " value " + n + " to double failed. Value is out of range.");
881 }
882 return answer;
883 }
884 }
885 else {
886 if (Number.class.isAssignableFrom(type)) {
887 if (type == Byte.class) {
888 return new Byte(n.byteValue());
889 }
890 if (type == Character.class) {
891 return new Character((char) n.intValue());
892 }
893 if (type == Short.class) {
894 return new Short(n.shortValue());
895 }
896 if (type == Integer.class) {
897 return new Integer(n.intValue());
898 }
899 if (type == Long.class) {
900 return new Long(n.longValue());
901 }
902 if (type == Float.class) {
903 return new Float(n.floatValue());
904 }
905 if (type == Double.class) {
906 Double answer = new Double(n.doubleValue());
907
908 if (!(n instanceof Double) && (answer.doubleValue() == Double.NEGATIVE_INFINITY
909 || answer.doubleValue() == Double.POSITIVE_INFINITY)) {
910 throw new GroovyRuntimeException("Automatic coercion of " + n.getClass().getName()
911 + " value " + n + " to double failed. Value is out of range.");
912 }
913 return answer;
914 }
915
916 }
917 }
918 }
919 if (type == Boolean.class) {
920 return asBool(object) ? Boolean.TRUE : Boolean.FALSE;
921 }
922 Object[] args = null;
923 if (object instanceof Collection) {
924 Collection list = (Collection) object;
925 args = list.toArray();
926 }
927 else if (object instanceof Object[]) {
928 args = (Object[]) object;
929 }
930 if (args != null) {
931
932
933 try {
934 return invokeConstructorOf(type, args);
935 }
936 catch (Exception e) {
937
938
939
940 }
941
942 }
943 return object;
944 }
945
946 public Object asArray(Object object, Class type) {
947 Collection list = asCollection(object);
948 int size = list.size();
949 Class elementType = type.getComponentType();
950 Object array = Array.newInstance(elementType, size);
951 int idx = 0;
952
953 if (boolean.class.equals(elementType)) {
954 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
955 Object element = iter.next();
956 Array.setBoolean(array, idx, asBool(element));
957 }
958 }
959 else if (byte.class.equals(elementType)) {
960 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
961 Object element = iter.next();
962 Array.setByte(array, idx, asByte(element));
963 }
964 }
965 else if (char.class.equals(elementType)) {
966 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
967 Object element = iter.next();
968 Array.setChar(array, idx, asChar(element));
969 }
970 }
971 else if (double.class.equals(elementType)) {
972 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
973 Object element = iter.next();
974 Array.setDouble(array, idx, asDouble(element));
975 }
976 }
977 else if (float.class.equals(elementType)) {
978 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
979 Object element = iter.next();
980 Array.setFloat(array, idx, asFloat(element));
981 }
982 }
983 else if (int.class.equals(elementType)) {
984 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
985 Object element = iter.next();
986 Array.setInt(array, idx, asInt(element));
987 }
988 }
989 else if (long.class.equals(elementType)) {
990 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
991 Object element = iter.next();
992 Array.setLong(array, idx, asLong(element));
993 }
994 }
995 else if (short.class.equals(elementType)) {
996 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
997 Object element = iter.next();
998 Array.setShort(array, idx, asShort(element));
999 }
1000 }
1001 else {
1002 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1003 Object element = iter.next();
1004 Object coercedElement = asType(element, elementType);
1005 Array.set(array, idx, coercedElement);
1006 }
1007 }
1008 return array;
1009 }
1010
1011 public Number asNumber(Object value) {
1012 if (value instanceof Number) {
1013 return (Number) value;
1014 }
1015 else if (value instanceof String) {
1016 String s = (String) value;
1017
1018 if (s.length() == 1) {
1019 return new Integer(s.charAt(0));
1020 }
1021 else {
1022 return new BigDecimal(s);
1023 }
1024 }
1025 else if (value instanceof Character) {
1026 return new Integer(((Character) value).charValue());
1027 }
1028 else {
1029 throw new GroovyRuntimeException("Could not convert object: " + value + " into a Number");
1030 }
1031 }
1032
1033 public byte asByte(Object element) {
1034 return asNumber(element).byteValue();
1035 }
1036
1037 public char asChar(Object element) {
1038 if (element instanceof String) {
1039 return asCharacter((String) element).charValue();
1040 }
1041 return asCharacter(asNumber(element)).charValue();
1042 }
1043
1044 public float asFloat(Object element) {
1045 return asNumber(element).floatValue();
1046 }
1047
1048 public double asDouble(Object element) {
1049 return asNumber(element).doubleValue();
1050 }
1051
1052 public short asShort(Object element) {
1053 return asNumber(element).shortValue();
1054 }
1055
1056 public int asInt(Object element) {
1057 return asNumber(element).intValue();
1058 }
1059
1060 public long asLong(Object element) {
1061 return asNumber(element).longValue();
1062 }
1063
1064 public boolean asBool(Object object) {
1065 if (object instanceof Boolean) {
1066 Boolean booleanValue = (Boolean) object;
1067 return booleanValue.booleanValue();
1068 }
1069 else if (object instanceof Matcher) {
1070 Matcher matcher = (Matcher) object;
1071 RegexSupport.setLastMatcher(matcher);
1072 return matcher.find();
1073 }
1074 else if (object instanceof Collection) {
1075 Collection collection = (Collection) object;
1076 return !collection.isEmpty();
1077 }
1078 else if (object instanceof Number) {
1079 Number n = (Number) object;
1080 return n.doubleValue() != 0;
1081 }
1082 else {
1083 return object != null;
1084 }
1085 }
1086
1087 protected Character asCharacter(Number value) {
1088 return new Character((char) value.intValue());
1089 }
1090
1091 protected Character asCharacter(String text) {
1092 return new Character(text.charAt(0));
1093 }
1094
1095 /***
1096 * @return true if the given value is a valid character string (i.e. has length of 1)
1097 */
1098 protected boolean isValidCharacterString(Object value) {
1099 if (value instanceof String) {
1100 String s = (String) value;
1101 if (s.length() == 1) {
1102 return true;
1103 }
1104 }
1105 return false;
1106 }
1107
1108 public void removeMetaClass(Class clazz) {
1109 getMetaRegistry().removeMetaClass(clazz);
1110 }
1111 }