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.