Coverage report

  %line %branch
org.apache.commons.jelly.tags.bean.BeanPropertyTag
81% 
78% 

 1  
 /*
 2  
  * Copyright 2002,2004 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  
 
 17  
 package org.apache.commons.jelly.tags.bean;
 18  
 
 19  
 import java.lang.reflect.Method;
 20  
 import java.lang.reflect.Modifier;
 21  
 import java.util.Map;
 22  
 
 23  
 import org.apache.commons.beanutils.MethodUtils;
 24  
 
 25  
 import org.apache.commons.jelly.JellyTagException;
 26  
 import org.apache.commons.jelly.XMLOutput;
 27  
 
 28  
 /**
 29  
  * Creates a nested property via calling a beans createFoo() method then
 30  
  * either calling the setFoo(value) or addFoo(value) methods in a similar way
 31  
  * to how Ant tags construct themselves.
 32  
  *
 33  
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 34  
  * @author Christian Sell
 35  
  * @version $Revision: 155420 $
 36  
  */
 37  
 public class BeanPropertyTag extends BeanTag {
 38  
 
 39  
     /** empty arguments constant */
 40  3
     private static final Object[] EMPTY_ARGS = {};
 41  
 
 42  
     /** empty argument types constant */
 43  3
     private static final Class[] EMPTY_ARG_TYPES = {};
 44  
 
 45  
     /** the name of the create method */
 46  
     private String createMethodName;
 47  
 
 48  
 
 49  
     public BeanPropertyTag(String tagName) {
 50  96
         super(Object.class, tagName);
 51  
 
 52  90
         if (tagName.length() > 0) {
 53  90
             createMethodName = "create"
 54  
                 + tagName.substring(0,1).toUpperCase()
 55  
                 + tagName.substring(1);
 56  
         }
 57  90
     }
 58  
 
 59  
     /**
 60  
      * Creates a new instance by calling a create method on the parent bean
 61  
      */
 62  
     protected Object newInstance(Class theClass, Map attributes, XMLOutput output) throws JellyTagException {
 63  90
         Object parentObject = getParentObject();
 64  90
         if (parentObject != null) {
 65  
             // now lets try call the create method...
 66  90
             Class parentClass = parentObject.getClass();
 67  90
             Method method = findCreateMethod(parentClass);
 68  90
             if (method != null) {
 69  
                 try {
 70  45
                     return method.invoke(parentObject, EMPTY_ARGS);
 71  
                 }
 72  0
                 catch (Exception e) {
 73  0
                     throw new JellyTagException( "failed to invoke method: " + method + " on bean: " + parentObject + " reason: " + e, e );
 74  
                 }
 75  
             }
 76  
             else {
 77  45
                 Class tagClass = theClass;
 78  45
                 if(tagClass == Object.class)
 79  45
                     tagClass = findAddMethodClass(parentClass);
 80  45
                 if(tagClass == null)
 81  0
                     throw new JellyTagException("unable to infer element class for tag "+getTagName());
 82  
 
 83  45
                 return super.newInstance(tagClass, attributes, output) ;
 84  
             }
 85  
         }
 86  0
         throw new JellyTagException("The " + getTagName() + " tag must be nested within a tag which maps to a BeanSource implementor");
 87  
     }
 88  
 
 89  
     /**
 90  
      * finds the parameter type of the first public method in the parent class whose name
 91  
      * matches the add{tag name} pattern, whose return type is void and which takes
 92  
      * one argument only.
 93  
      * @param parentClass
 94  
      * @return the class of the first and only parameter
 95  
      */
 96  
     protected Class findAddMethodClass(Class parentClass) {
 97  45
         Method[] methods = parentClass.getMethods();
 98  90
         for (int i = 0; i < methods.length; i++) {
 99  90
             Method method = methods[i];
 100  90
             if(Modclass="keyword">ifier.isPublic(method.getModclass="keyword">ifiers())) {
 101  90
                 Class[] args = method.getParameterTypes();
 102  90
                 if (method.getName().equals(addMethodName)
 103  
                       && java.lang.Void.TYPE.equals(method.getReturnType())
 104  
                       && args.length == 1
 105  
                       && !java.lang.String.class.equals(args[0])
 106  
                       && !args[0].isArray()
 107  
                       && !args[0].isPrimitive())
 108  45
                     return args[0];
 109  
             }
 110  
         }
 111  0
         return null;
 112  
     }
 113  
 
 114  
     /**
 115  
      * Finds the Method to create a new property object
 116  
      */
 117  
     protected Method findCreateMethod(Class theClass) {
 118  90
         if (createMethodName == null) {
 119  0
             return null;
 120  
         }
 121  90
         return MethodUtils.getAccessibleMethod(
 122  
             theClass, createMethodName, EMPTY_ARG_TYPES
 123  
         );
 124  
     }
 125  
 }

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