Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.jexl.parser.ASTMethod |
60% |
83% |

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;
19 |  |
     import java.math.BigDecimal;
20 |  |
     import java.math.BigInteger;
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 | 5 |
         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 | 0 |
             super(id);
41 | 0 |
         }
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 | 44 |
             super(p, id);
51 | 44 |
         }
52 |  |
53 |  |
         /** {@inheritDoc} */
54 |  |
         public Object jjtAccept(ParserVisitor visitor, Object data) {
55 | 0 |
             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 execute(Object obj, JexlContext jc) throws Exception {
69 | 39 |
             String methodName = ((ASTIdentifier) jjtGetChild(0)).val;
70 |  |
71 | 39 |
             int paramCount = jjtGetNumChildren() - 1;
72 |  |
73 |  |
             /*
74 |  |
              * get our params
75 |  |
              */
76 |  |
77 | 39 |
             Object[] params = new Object[paramCount];
78 |  |
79 |  |
             try {
80 | 71 |
                 for (int i = 0; i < paramCount; i++) {
81 | 32 |
                     params[i] = ((SimpleNode) jjtGetChild(i + 1)).value(jc);
82 |  |
                 }
83 |  |
84 | 39 |
                 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 | 39 |
                 if (vm == null) {
90 |  |
91 |  |
                     // replace all numbers with the smallest type that will fit
92 | 16 |
                     for (int i = 0; i < params.length; i++) {
93 | 10 |
                         Object param = params[i];
94 | 10 |
                         if (param instanceof Number) {
95 | 10 |
                             params[i] = narrow((Number) param);
96 |  |
                         }
97 |  |
                     }
98 | 6 |
                     vm = Introspector.getUberspect().getMethod(obj, methodName, params, DUMMY);
99 | 6 |
                     if (vm == null) {
100 | 0 |
                         return null;
101 |  |
                     }
102 |  |
                 }
103 |  |
104 | 39 |
                 return vm.invoke(obj, params);
105 |  |
             } catch (InvocationTargetException e) {
106 | 0 |
                 Throwable t = e.getTargetException();
107 |  |
108 | 0 |
                 if (t instanceof Exception) {
109 | 0 |
                     throw (Exception) t;
110 |  |
                 }
111 |  |
112 | 0 |
                 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 narrow(Number original) {
128 | 10 |
             if (original == null || original instanceof BigDecimal || original instanceof BigInteger) {
129 | 0 |
                 return original;
130 |  |
             }
131 | 10 |
             Number result = original;
132 | 10 |
             if (original instanceof Double || original instanceof Float) {
133 | 0 |
                 double value = original.class="keyword">doubleValue();
134 | 0 |
                 if (value <= Float.MAX_VALUE && value >= Float.MIN_VALUE) {
135 | 0 |
                     result = new Float(result.floatValue());
136 |  |
                 }
137 |  |
                 // else it was already a double
138 |  |
             } else {
139 | 10 |
                 long value = original.class="keyword">longValue();
140 | 10 |
                 if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) {
141 |  |
                     // it will fit in a byte
142 | 10 |
                     result = new Byte((byte) value);
143 | 0 |
                 } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) {
144 | 0 |
                     result = new Short((short) value);
145 | 0 |
                 } else if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
146 | 0 |
                     result = new Integer((int) value);
147 |  |
                 }
148 |  |
                 // else it was already a long
149 |  |
             }
150 | 10 |
             return result;
151 |  |
         }
152 |  |
153 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.