KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jexl > parser > ASTMethod


1 /*
2  * Copyright 2002-2006 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.jexl.parser;
17
18 import java.lang.reflect.InvocationTargetException JavaDoc;
19 import java.math.BigDecimal JavaDoc;
20 import java.math.BigInteger JavaDoc;
21
22 import org.apache.commons.jexl.JexlContext;
23 import org.apache.commons.jexl.util.Introspector;
24 import org.apache.commons.jexl.util.introspection.VelMethod;
25 import org.apache.commons.jexl.util.introspection.Info;
26
27 /**
28  * Method execution.
29  */

30 public class ASTMethod extends SimpleNode {
31     /** dummy velocity info. */
32     private static final Info DUMMY = new Info("", 1, 1);
33
34     /**
35      * Create the node given an id.
36      *
37      * @param id node id.
38      */

39     public ASTMethod(int id) {
40         super(id);
41     }
42
43     /**
44      * Create a node with the given parser and id.
45      *
46      * @param p a parser.
47      * @param id node id.
48      */

49     public ASTMethod(Parser p, int id) {
50         super(p, id);
51     }
52
53     /** {@inheritDoc} */
54     public Object JavaDoc jjtAccept(ParserVisitor visitor, Object JavaDoc data) {
55         return visitor.visit(this, data);
56     }
57
58     /**
59      * evaluate a method invocation upon a base object.
60      *
61      * foo.bar(2)
62      *
63      * @param jc the {@link JexlContext} to evaluate against.
64      * @param obj The object to have the method invoked.
65      * @return the value of the method invocation.
66      * @throws Exception on any error
67      */

68     public Object JavaDoc execute(Object JavaDoc obj, JexlContext jc) throws Exception JavaDoc {
69         String JavaDoc methodName = ((ASTIdentifier) jjtGetChild(0)).val;
70
71         int paramCount = jjtGetNumChildren() - 1;
72
73         /*
74          * get our params
75          */

76
77         Object JavaDoc[] params = new Object JavaDoc[paramCount];
78
79         try {
80             for (int i = 0; i < paramCount; i++) {
81                 params[i] = ((SimpleNode) jjtGetChild(i + 1)).value(jc);
82             }
83
84             VelMethod vm = Introspector.getUberspect().getMethod(obj, methodName, params, DUMMY);
85             /*
86              * DG: If we can't find an exact match, narrow the parameters and
87              * try again!
88              */

89             if (vm == null) {
90
91                 // replace all numbers with the smallest type that will fit
92
for (int i = 0; i < params.length; i++) {
93                     Object JavaDoc param = params[i];
94                     if (param instanceof Number JavaDoc) {
95                         params[i] = narrow((Number JavaDoc) param);
96                     }
97                 }
98                 vm = Introspector.getUberspect().getMethod(obj, methodName, params, DUMMY);
99                 if (vm == null) {
100                     return null;
101                 }
102             }
103
104             return vm.invoke(obj, params);
105         } catch (InvocationTargetException JavaDoc e) {
106             Throwable JavaDoc t = e.getTargetException();
107
108             if (t instanceof Exception JavaDoc) {
109                 throw (Exception JavaDoc) t;
110             }
111
112             throw e;
113         }
114     }
115
116     /**
117      * Given a Number, return back the value using the smallest type the result
118      * will fit into. This works hand in hand with parameter 'widening' in java
119      * method calls, e.g. a call to substring(int,int) with an int and a long
120      * will fail, but a call to substring(int,int) with an int and a short will
121      * succeed.
122      *
123      * @param original the original number.
124      * @return a value of the smallest type the original number will fit into.
125      * @since 1.1
126      */

127     private Number JavaDoc narrow(Number JavaDoc original) {
128         if (original == null || original instanceof BigDecimal JavaDoc || original instanceof BigInteger JavaDoc) {
129             return original;
130         }
131         Number JavaDoc result = original;
132         if (original instanceof Double JavaDoc || original instanceof Float JavaDoc) {
133             double value = original.doubleValue();
134             if (value <= Float.MAX_VALUE && value >= Float.MIN_VALUE) {
135                 result = new Float JavaDoc(result.floatValue());
136             }
137             // else it was already a double
138
} else {
139             long value = original.longValue();
140             if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) {
141                 // it will fit in a byte
142
result = new Byte JavaDoc((byte) value);
143             } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) {
144                 result = new Short JavaDoc((short) value);
145             } else if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
146                 result = new Integer JavaDoc((int) value);
147             }
148             // else it was already a long
149
}
150         return result;
151     }
152
153 }
154
Popular Tags