Coverage Report - org.apache.commons.beanutils.BasicDynaClass
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicDynaClass
78%
36/46
87%
14/16
2.6
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 
 19  
 package org.apache.commons.beanutils;
 20  
 
 21  
 
 22  
 import java.io.Serializable;
 23  
 import java.lang.reflect.Constructor;
 24  
 import java.lang.reflect.InvocationTargetException;
 25  
 import java.util.HashMap;
 26  
 
 27  
 
 28  
 /**
 29  
  * <p>Minimal implementation of the <code>DynaClass</code> interface.  Can be
 30  
  * used as a convenience base class for more sophisticated implementations.</p> *
 31  
  * <p><strong>IMPLEMENTATION NOTE</strong> - The <code>DynaBean</code>
 32  
  * implementation class supplied to our constructor MUST have a one-argument
 33  
  * constructor of its own that accepts a <code>DynaClass</code>.  This is
 34  
  * used to associate the DynaBean instance with this DynaClass.</p>
 35  
  *
 36  
  * @author Craig McClanahan
 37  
  * @version $Revision: 926529 $ $Date: 2010-03-23 07:44:24 -0400 (Tue, 23 Mar 2010) $
 38  
  */
 39  
 
 40  
 public class BasicDynaClass implements DynaClass, Serializable {
 41  
 
 42  
 
 43  
     // ----------------------------------------------------------- Constructors
 44  
 
 45  
 
 46  
     /**
 47  
      * Construct a new BasicDynaClass with default parameters.
 48  
      */
 49  
     public BasicDynaClass() {
 50  
 
 51  1
         this(null, null, null);
 52  
 
 53  1
     }
 54  
 
 55  
 
 56  
     /**
 57  
      * Construct a new BasicDynaClass with the specified parameters.
 58  
      *
 59  
      * @param name Name of this DynaBean class
 60  
      * @param dynaBeanClass The implementation class for new instances
 61  
      */
 62  
     public BasicDynaClass(String name, Class dynaBeanClass) {
 63  
 
 64  0
         this(name, dynaBeanClass, null);
 65  
 
 66  0
     }
 67  
 
 68  
 
 69  
     /**
 70  
      * Construct a new BasicDynaClass with the specified parameters.
 71  
      *
 72  
      * @param name Name of this DynaBean class
 73  
      * @param dynaBeanClass The implementation class for new intances
 74  
      * @param properties Property descriptors for the supported properties
 75  
      */
 76  
     public BasicDynaClass(String name, Class dynaBeanClass,
 77  
                           DynaProperty[] properties) {
 78  
 
 79  344
         super();
 80  344
         if (name != null) {
 81  246
             this.name = name;
 82  
         }
 83  344
         if (dynaBeanClass == null) {
 84  124
             dynaBeanClass = BasicDynaBean.class;
 85  
         }
 86  344
         setDynaBeanClass(dynaBeanClass);
 87  344
         if (properties != null) {
 88  246
             setProperties(properties);
 89  
         }
 90  
 
 91  344
     }
 92  
 
 93  
 
 94  
     // ----------------------------------------------------- Instance Variables
 95  
 
 96  
 
 97  
     /**
 98  
      * The constructor of the <code>dynaBeanClass</code> that we will use
 99  
      * for creating new instances.
 100  
      */
 101  344
     protected transient Constructor constructor = null;
 102  
 
 103  
 
 104  
     /**
 105  
      * The method signature of the constructor we will use to create
 106  
      * new DynaBean instances.
 107  
      */
 108  1
     protected static Class[] constructorTypes = { DynaClass.class };
 109  
 
 110  
 
 111  
     /**
 112  
      * The argument values to be passed to the constructore we will use
 113  
      * to create new DynaBean instances.
 114  
      */
 115  344
     protected Object[] constructorValues = { this };
 116  
 
 117  
 
 118  
     /**
 119  
      * The <code>DynaBean</code> implementation class we will use for
 120  
      * creating new instances.
 121  
      */
 122  344
     protected Class dynaBeanClass = BasicDynaBean.class;
 123  
 
 124  
 
 125  
     /**
 126  
      * The "name" of this DynaBean class.
 127  
      */
 128  344
     protected String name = this.getClass().getName();
 129  
 
 130  
 
 131  
     /**
 132  
      * The set of dynamic properties that are part of this DynaClass.
 133  
      */
 134  344
     protected DynaProperty[] properties = new DynaProperty[0];
 135  
 
 136  
 
 137  
     /**
 138  
      * The set of dynamic properties that are part of this DynaClass,
 139  
      * keyed by the property name.  Individual descriptor instances will
 140  
      * be the same instances as those in the <code>properties</code> list.
 141  
      */
 142  344
     protected HashMap propertiesMap = new HashMap();
 143  
 
 144  
 
 145  
     // ------------------------------------------------------ DynaClass Methods
 146  
 
 147  
 
 148  
     /**
 149  
      * Return the name of this DynaClass (analogous to the
 150  
      * <code>getName()</code> method of <code>java.lang.Class</code), which
 151  
      * allows the same <code>DynaClass</code> implementation class to support
 152  
      * different dynamic classes, with different sets of properties.
 153  
      *
 154  
      * @return the name of the DynaClass
 155  
      */
 156  
     public String getName() {
 157  
 
 158  0
         return (this.name);
 159  
 
 160  
     }
 161  
 
 162  
 
 163  
     /**
 164  
      * Return a property descriptor for the specified property, if it exists;
 165  
      * otherwise, return <code>null</code>.
 166  
      *
 167  
      * @param name Name of the dynamic property for which a descriptor
 168  
      *  is requested
 169  
      * @return The descriptor for the specified property
 170  
      *
 171  
      * @exception IllegalArgumentException if no property name is specified
 172  
      */
 173  
     public DynaProperty getDynaProperty(String name) {
 174  
 
 175  3117
         if (name == null) {
 176  5
             throw new IllegalArgumentException
 177  
                     ("No property name specified");
 178  
         }
 179  3112
         return ((DynaProperty) propertiesMap.get(name));
 180  
 
 181  
     }
 182  
 
 183  
 
 184  
     /**
 185  
      * <p>Return an array of <code>ProperyDescriptors</code> for the properties
 186  
      * currently defined in this DynaClass.  If no properties are defined, a
 187  
      * zero-length array will be returned.</p>
 188  
      *
 189  
      * <p><strong>FIXME</strong> - Should we really be implementing
 190  
      * <code>getBeanInfo()</code> instead, which returns property descriptors
 191  
      * and a bunch of other stuff?</p>
 192  
      *
 193  
      * @return the set of properties for this DynaClass
 194  
      */
 195  
     public DynaProperty[] getDynaProperties() {
 196  
 
 197  44
         return (properties);
 198  
 
 199  
     }
 200  
 
 201  
 
 202  
     /**
 203  
      * Instantiate and return a new DynaBean instance, associated
 204  
      * with this DynaClass.
 205  
      *
 206  
      * @return A new <code>DynaBean</code> instance
 207  
      * @exception IllegalAccessException if the Class or the appropriate
 208  
      *  constructor is not accessible
 209  
      * @exception InstantiationException if this Class represents an abstract
 210  
      *  class, an array class, a primitive type, or void; or if instantiation
 211  
      *  fails for some other reason
 212  
      */
 213  
     public DynaBean newInstance()
 214  
             throws IllegalAccessException, InstantiationException {
 215  
 
 216  
         try {
 217  
             // Refind the constructor after a deserialization (if needed)
 218  146
             if (constructor == null) {
 219  1
                 setDynaBeanClass(this.dynaBeanClass);
 220  
             }
 221  
             // Invoke the constructor to create a new bean instance
 222  146
             return ((DynaBean) constructor.newInstance(constructorValues));
 223  0
         } catch (InvocationTargetException e) {
 224  0
             throw new InstantiationException
 225  
                     (e.getTargetException().getMessage());
 226  
         }
 227  
 
 228  
     }
 229  
 
 230  
 
 231  
     // --------------------------------------------------------- Public Methods
 232  
 
 233  
 
 234  
     /**
 235  
      * Return the Class object we will use to create new instances in the
 236  
      * <code>newInstance()</code> method.  This Class <strong>MUST</strong>
 237  
      * implement the <code>DynaBean</code> interface.
 238  
      *
 239  
      * @return The class of the {@link DynaBean}
 240  
      */
 241  
     public Class getDynaBeanClass() {
 242  
 
 243  0
         return (this.dynaBeanClass);
 244  
 
 245  
     }
 246  
 
 247  
 
 248  
     // ------------------------------------------------------ Protected Methods
 249  
 
 250  
 
 251  
     /**
 252  
      * Set the Class object we will use to create new instances in the
 253  
      * <code>newInstance()</code> method.  This Class <strong>MUST</strong>
 254  
      * implement the <code>DynaBean</code> interface.
 255  
      *
 256  
      * @param dynaBeanClass The new Class object
 257  
      *
 258  
      * @exception IllegalArgumentException if the specified Class does not
 259  
      *  implement the <code>DynaBean</code> interface
 260  
      */
 261  
     protected void setDynaBeanClass(Class dynaBeanClass) {
 262  
 
 263  
         // Validate the argument type specified
 264  345
         if (dynaBeanClass.isInterface()) {
 265  0
             throw new IllegalArgumentException
 266  
                     ("Class " + dynaBeanClass.getName() +
 267  
                     " is an interface, not a class");
 268  
         }
 269  345
         if (!DynaBean.class.isAssignableFrom(dynaBeanClass)) {
 270  0
             throw new IllegalArgumentException
 271  
                     ("Class " + dynaBeanClass.getName() +
 272  
                     " does not implement DynaBean");
 273  
         }
 274  
 
 275  
         // Identify the Constructor we will use in newInstance()
 276  
         try {
 277  345
             this.constructor = dynaBeanClass.getConstructor(constructorTypes);
 278  0
         } catch (NoSuchMethodException e) {
 279  0
             throw new IllegalArgumentException
 280  
                     ("Class " + dynaBeanClass.getName() +
 281  
                     " does not have an appropriate constructor");
 282  345
         }
 283  345
         this.dynaBeanClass = dynaBeanClass;
 284  
 
 285  345
     }
 286  
 
 287  
 
 288  
     /**
 289  
      * Set the list of dynamic properties supported by this DynaClass.
 290  
      *
 291  
      * @param properties List of dynamic properties to be supported
 292  
      */
 293  
     protected void setProperties(DynaProperty[] properties) {
 294  
 
 295  270
         this.properties = properties;
 296  270
         propertiesMap.clear();
 297  2976
         for (int i = 0; i < properties.length; i++) {
 298  2706
             propertiesMap.put(properties[i].getName(), properties[i]);
 299  
         }
 300  
 
 301  270
     }
 302  
 
 303  
 
 304  
 }