You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ni...@apache.org on 2004/07/05 02:48:12 UTC

cvs commit: jakarta-commons/beanutils/src/test/org/apache/commons/beanutils LazyDynaBeanTestCase.java LazyDynaClassTestCase.java

niallp      2004/07/04 17:48:12

  Added:       beanutils/src/java/org/apache/commons/beanutils
                        LazyDynaBean.java LazyDynaClass.java
               beanutils/src/test/org/apache/commons/beanutils
                        LazyDynaBeanTestCase.java
                        LazyDynaClassTestCase.java
  Log:
  Add LazyDynaBean, LazyDynaClass and Test Cases
  
  Revision  Changes    Path
  1.1                  jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/LazyDynaBean.java
  
  Index: LazyDynaBean.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.commons.beanutils;
  
  import java.util.List;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.HashMap;
  import java.lang.reflect.Array;
  
  /**
   * <p>DynaBean which automatically adds properties to the <code>DynaClass</code>
   * if they don't exist.</p>
   *
   * <p><strong>N.B.</strong> Must be used with a <code>DynaClass</code> that
   * implements the <code>MutableDynaClass</code> interface - if not specified
   * the <code>LazyDynaClass</code> is used by default.</p>
   *
   * <p>DynaBeans deal with three types of properties - <i>simple</i>, <i>indexed</i> and <i>mapped</i> and
   *    have the following <code>get()</code> and <code>set()</code> methods for
   *    each of these types:</p>
   *    <ul>
   *        <li><i>Simple</i> property methods - <code>get(name)</code> and <code>set(name, value)</code></li>
   *        <li><i>Indexed</i> property methods - <code>get(name, index)</code> and <code>set(name, index, value)</code></li>
   *        <li><i>Mapped</i> property methods - <code>get(name, key)</code> and <code>set(name, key, value)</code></li>
   *    </ul>
   *
   * <p><b><u>Getting Property Values</u></b></p>
   * <p>Calling any of the <code>get()</code> methods, for a property which
   *    doesn't exist, returns <code>null</code> in this implementation.</p>
   *
   * <p><b><u>Setting Simple Properties</u></b></p>
   *    <p>The <code>LazyDynaBean</code> will automatically add a property to the <code>DynaClass</code>
   *       if it doesn't exist when the <code>set(name, value)</code> method is called.</p>
   *
   *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
   *     <code>myBean.set("myProperty", "myValue");</code></br>
   *
   * <p><b><u>Setting Indexed Properties</u></b></p>
   *    <p>If the property <b>doesn't</b> exist, the <code>LazyDynaBean</code> will automatically add
   *       a property with an <code>ArrayList</code> type to the <code>DynaClass</code> when
   *       the <code>set(name, index, value)</code> method is called.
   *       It will also instantiate a new <code>ArrayList</code> and automatically <i>grow</i>
   *       the <code>List</code> so that it is big enough to accomodate the index being set.
   *       <code>ArrayList</code> is the default indexed property that LazyDynaBean uses but
   *       this can be easily changed by overriding the <code>newIndexedProperty(name)</code>
   *       method.</p>
   *
   *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
   *     <code>myBean.set("myIndexedProperty", 0, "myValue1");</code></br>
   *     <code>myBean.set("myIndexedProperty", 1, "myValue2");</code></br>
   *
   *    <p>If the indexed property <b>does</b> exist in the <code>DynaClass</code> but is set to
   *      <code>null</code> in the <code>LazyDynaBean</code>, then it will instantiate a
   *      new <code>List</code> or <code>Array</code> as specified by the property's type
   *      in the <code>DynaClass</code> and automatically <i>grow</i> the <code>List</code>
   *      or <code>Array</code> so that it is big enough to accomodate the index being set.</p>
   *
   *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
   *     <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();</code></br>
   *     <code>myClass.add("myIndexedProperty", int[].class);</code></br>
   *     <code>myBean.set("myIndexedProperty", 0, new Integer(10));</code></br>
   *     <code>myBean.set("myIndexedProperty", 1, new Integer(20));</code></br>
   *
   * <p><b><u>Setting Mapped Properties</u></b></p>
   *    <p>If the property <b>doesn't</b> exist, the <code>LazyDynaBean</code> will automatically add
   *       a property with a <code>HashMap</code> type to the <code>DynaClass</code> and
   *       instantiate a new <code>HashMap</code> in the DynaBean when the
   *       <code>set(name, key, value)</code> method is called. <code>HashMap</code> is the default
   *       mapped property that LazyDynaBean uses but this can be easily changed by overriding
   *       the <code>newMappedProperty(name)</code> method.</p>
   *
   *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
   *     <code>myBean.set("myMappedProperty", "myKey", "myValue");</code></br>
   *
   *    <p>If the mapped property <b>does</b> exist in the <code>DynaClass</code> but is set to
   *      <code>null</code> in the <code>LazyDynaBean</code>, then it will instantiate a
   *      new <code>Map</code> as specified by the property's type in the <code>DynaClass</code>.</p>
   *
   *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
   *     <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();</code></br>
   *     <code>myClass.add("myMappedProperty", TreeMap.class);</code></br>
   *     <code>myBean.set("myMappedProperty", "myKey", "myValue");</code></br>
   *
   * <p><b><u><i>Restricted</i> DynaClass</u></b></p>
   *    <p><code>MutableDynaClass</code> have a facility to <i>restrict</i> the <code>DynaClass</code>
   *       so that its properties cannot be modified. If the <code>MutableDynaClass</code> is
   *       restricted then calling any of the <code>set()</code> methods for a property which
   *       doesn't exist will result in a <code>IllegalArgumentException</code> being thrown.</p>
   *
   * @see LazyDynaClass
   * @author Niall Pemberton
   */
  public class LazyDynaBean extends BasicDynaBean {
  
      /**
       * The <code>MutableDynaClass</code> "base class" that this DynaBean
       * is associated with.
       */
      protected MutableDynaClass mutableDynaClass;
  
      /**
       * Construct a new <code>LazyDynaBean</code> with a <code>LazyDynaClass</code> instance.
       */
      public LazyDynaBean() {
  
          this(new LazyDynaClass());
  
      }
  
      /**
       * Construct a new <code>LazyDynaBean</code> with a <code>LazyDynaClass</code> instance.
       *
       * @param name Name of this DynaBean class
       */
      public LazyDynaBean(String name) {
  
          this(new LazyDynaClass(name));
  
      }
  
      /**
       * Construct a new <code>DynaBean</code> associated with the specified
       * <code>DynaClass</code> instance - must be <code>MutableDynaClass</code>.
       *
       * @param dynaClass The DynaClass we are associated with
       */
      public LazyDynaBean(DynaClass dynaClass) {
  
          super(dynaClass);
  
          if (!(dynaClass instanceof MutableDynaClass))
              throw new IllegalArgumentException("DynaClass must be a MutableDynaClass type: " +
                                                  dynaClass.getClass().getName());
  
          mutableDynaClass = (MutableDynaClass)dynaClass;
  
      }
  
      /**
       * <p>Return the value of a simple property with the specified name.</p>
       *
       * <p><strong>N.B.</strong> Returns <code>null</code> if there is no property
       *  of the specified name.</p>
       *
       * @param name Name of the property whose value is to be retrieved.
       */
      public Object get(String name) {
  
          if (isDynaProperty(name)) {
  
              return super.get(name);
  
          } else {
  
              return null;
  
          }
  
      }
  
      /**
       * <p>Return the value of an indexed property with the specified name.</p>
       *
       * <p><strong>N.B.</strong> Returns <code>null</code> if there is no 'indexed'
       * property of the specified name.</p>
       *
       * @param name Name of the property whose value is to be retrieved
       * @param index Index of the value to be retrieved
       *
       * @exception IllegalArgumentException if the specified property
       *  exists, but is not indexed
       * @exception IndexOutOfBoundsException if the specified index
       *  is outside the range of the underlying property
       */
      public Object get(String name, int index) {
  
          if (get(name) == null) {
  
              return null;
  
          } else {
  
              return super.get(name, index);
  
          }
  
      }
  
      /**
       * <p>Return the value of a mapped property with the specified name.</p>
       *
       * <p><strong>N.B.</strong> Returns <code>null</code> if there is no 'mapped'
       * property of the specified name.</p>
       *
       * @param name Name of the property whose value is to be retrieved
       * @param key Key of the value to be retrieved
       *
       * @exception IllegalArgumentException if the specified property
       *  exists, but is not mapped
       */
      public Object get(String name, String key) {
  
          if (get(name) == null) {
  
              return null;
  
          } else {
  
              return super.get(name, key);
  
          }
  
      }
  
      /**
       * Set the value of a simple property with the specified name.
       *
       * @param name Name of the property whose value is to be set
       * @param value Value to which this property is to be set
       *
       * @exception IllegalArgumentException if this is not an existing property
       *  name for our DynaClass and the MutableDynaClass is restricted
       * @exception ConversionException if the specified value cannot be
       *  converted to the type required for this property
       * @exception NullPointerException if an attempt is made to set a
       *  primitive property to null
       */
      public void set(String name, Object value) {
  
          // If the property doesn't exist, then add it
          if (!isDynaProperty(name)) {
  
              if (mutableDynaClass.isRestricted()) {
                  throw new IllegalArgumentException
                      ("Invalid property name '" + name + "' (DynaClass is restricted)");
              }
  
              if (value == null) {
                  mutableDynaClass.add(name);
              } else {
                  mutableDynaClass.add(name, value.getClass());
              }
  
          }
  
          // Set the property's value
          super.set(name, value);
  
      }
  
      /**
       * Set the value of an indexed property with the specified name.
       *
       * @param name Name of the property whose value is to be set
       * @param index Index of the property to be set
       * @param value Value to which this property is to be set
       *
       * @exception ConversionException if the specified value cannot be
       *  converted to the type required for this property
       * @exception IllegalArgumentException if there is no property
       *  of the specified name
       * @exception IllegalArgumentException if the specified property
       *  exists, but is not indexed
       * @exception IndexOutOfBoundsException if the specified index
       *  is outside the range of the underlying property
       */
      public void set(String name, int index, Object value) {
  
          // If the 'indexed' property doesn't exist, then add it
          if (!isDynaProperty(name)) {
              set(name, newIndexedProperty(name));
          }
  
          // Check if its an Indexed Property
          DynaProperty dynaProperty = mutableDynaClass.getDynaProperty(name);
          if (!dynaProperty.isIndexed()) {
              throw new IllegalArgumentException
                      ("Non-indexed property for '" + name + "[" + index + "]', type is '" +
                           dynaProperty.getType().getName()+"'");
          }
  
  
          // Instantiate the indexed property
          Object prop = get(name);
          if (prop == null) {
              Class type = dynaProperty.getType();
              if (List.class.isAssignableFrom(type)) {
  
                  try {
                      prop = type.newInstance();
                      set(name, prop);
                  }
                  catch (Exception ex) {
                      throw new IllegalArgumentException
                          ("Error instantiating List of type '" + type.getName() +
                                        "' for '" + name + "[" + index + "]'");
                  }
  
              } else if (type.isArray()) {
  
                  prop = Array.newInstance(type.getComponentType(), index+1);
                  set(name, prop);
  
              } else {
  
                  throw new IllegalArgumentException
                     ("Non-indexed property for '" + name + "[" + index + "]'");
              }
          }
  
          // Grow the List or Array dynamically
          if (prop instanceof List) {
  
              List list = (List)prop;
              while (index >= list.size()) {
                  list.add(null);
              }
  
          } else if ((prop.getClass().isArray())) {
  
              int length = Array.getLength(prop);
              if (index >= length) {
                  Object newArray = Array.newInstance(prop.getClass().getComponentType(), (index + 1));
                  System.arraycopy(prop, 0, newArray, 0, length);
                  set(name, newArray);
              }
          }
  
          super.set(name, index, value);
  
      }
  
      /**
       * <p>Creates a new <code>ArrayList</code> for an 'indexed' property
       *    which doesn't exist.</p>
       *
       * <p>This method shouls be overriden if an alternative <code>List</code>
       *    or <code>Array</code> implementation is required for 'indexed' properties.</p>
       *
       * @param name Name of the 'indexed property.
       */
      protected Object newIndexedProperty(String name) {
  
          return new ArrayList();
  
      }
  
      /**
       * Set the value of a mapped property with the specified name.
       *
       * @param name Name of the property whose value is to be set
       * @param key Key of the property to be set
       * @param value Value to which this property is to be set
       *
       * @exception ConversionException if the specified value cannot be
       *  converted to the type required for this property
       * @exception IllegalArgumentException if there is no property
       *  of the specified name
       * @exception IllegalArgumentException if the specified property
       *  exists, but is not mapped
       */
      public void set(String name, String key, Object value) {
  
          // If the 'mapped' property doesn't exist, then add it
          if (!isDynaProperty(name)) {
              set(name, newMappedProperty(name));
          }
  
          // Check if its an Indexed Property
          DynaProperty dynaProperty = mutableDynaClass.getDynaProperty(name);
          if (!dynaProperty.isMapped()) {
              throw new IllegalArgumentException("Non-mapped property for '" +
                   name + "(" + key + ")', type is '" + dynaProperty.getType().getName()+"'");
          }
  
          // Instantiate the mapped property
          Object prop = get(name);
          if (prop == null) {
              Class type = dynaProperty.getType();
              try {
                  set(name, type.newInstance());
              }
              catch (Exception ex) {
                  throw new IllegalArgumentException
                      ("Error instantiating Map of type '" + type.getName() +
                                        "' for '" + name + "(" + key + ")'");
              }
          }
  
  
          // Set the 'mapped' property's value
          super.set(name, key, value);
  
  
      }
  
      /**
       * <p>Creates a new <code>HashMap</code> for a 'mapped' property
       *    which doesn't exist.</p>
       *
       * <p>This method can be overriden if an alternative <code>Map</code>
       *    implementation is required for 'mapped' properties.</p>
       *
       * @param name Name of the 'mapped property.
       */
      protected Map newMappedProperty(String name) {
  
          return new HashMap();
  
      }
  
      /**
       * Indicates if there is a property with the specified name.
       */
      protected boolean isDynaProperty(String name) {
  
          // Handle LazyDynaClasses
          if (mutableDynaClass instanceof LazyDynaClass) {
              return ((LazyDynaClass)mutableDynaClass).isDynaProperty(name);
          }
  
          // Handle other MutableDynaClass
          return mutableDynaClass.getDynaProperty(name) == null ? false : true;
  
      }
  
  }
  
  
  
  1.1                  jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/LazyDynaClass.java
  
  Index: LazyDynaClass.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.commons.beanutils;
  
  /**
   * <p>DynaClass which implements the <code>MutableDynaClass</code> interface.</p>
   *
   * <p>A <code>MutableDynaClass</code> is a specialized extension to <code>DynaClass</code>
   *    that allows properties to be added or removed dynamically.</p>
   *
   * <p>This implementation has one slightly unusual default behaviour - calling
   *    the <code>getDynaProperty(name)</code> method for a property which doesn't
   *    exist returns a <code>DynaProperty</code> rather than <code>null</code>. The
   *    reason for this is that <code>BeanUtils</code> calls this method to check if
   *    a property exists before trying to set the value. This would defeat the object
   *    of the <code>LazyDynaBean</code> which automatically adds missing properties
   *    when any of its <code>set()</code> methods are called. For this reason the
   *    <code>isDynaProperty(name)</code> method has been added to this implementation
   *    in order to determine if a property actually exists. If the more <i>normal</i>
   *    behaviour of returning <code>null</code> is required, then this can be achieved
   *    by calling the <code>setReturnNull(true)</code>.</p>
   *
   * <p>The <code>add(name, type, readable, writable)</code> method is not implemented
   *    and always throws an <code>UnsupportedOperationException</code>. I believe
   *    this attributes need to be added to the <code>DynaProperty</code> class
   *    in order to control read/write facilities.</p>
   *
   * @see LazyDynaBean
   * @see MutableDynaClass
   * @author Niall Pemberton
   */
  public class LazyDynaClass extends BasicDynaClass implements MutableDynaClass  {
  
      /**
       * Controls whether changes to this DynaClass's properties are allowed.
       */
      protected boolean restricted;
  
      /**
       * <p>Controls whether the <code>getDynaProperty()</code> method returns
       * null if a property doesn't exist - or creates a new one.</p>
       *
       * <p>Default is <code>false</code>.
       */
      protected boolean returnNull = false;
  
      /**
       * Construct a new LazyDynaClass with default parameters.
       */
      public LazyDynaClass() {
          super(null, LazyDynaBean.class);
      }
  
      /**
       * Construct a new LazyDynaClass with the specified parameters.
       *
       * @param name Name of this DynaBean class
       * @param dynaBeanClass The implementation class for new instances
       */
      public LazyDynaClass(String name) {
          super(name, LazyDynaBean.class);
      }
  
      /**
       * Construct a new LazyDynaClass with the specified parameters.
       *
       * @param name Name of this DynaBean class
       * @param dynaBeanClass The implementation class for new instances
       */
      public LazyDynaClass(String name, Class dynaBeanClass) {
          super(name, dynaBeanClass);
      }
  
      /**
       * Construct a new LazyDynaClass with the specified parameters.
       *
       * @param name Name of this DynaBean class
       * @param dynaBeanClass The implementation class for new intances
       * @param properties Property descriptors for the supported properties
       */
      public LazyDynaClass(String name, Class dynaBeanClass,
                            DynaProperty properties[]) {
          super(name, dynaBeanClass, properties);
      }
  
      /**
       * Is this DynaClass currently restricted, if so, no changes to the
       * existing registration of property names, data types, readability, or
       * writeability are allowed.
       */
      public boolean isRestricted() {
          return restricted;
      }
  
      /**
       * Set whether this DynaClass is currently restricted. if so, no changes to the
       * existing registration of property names, data types, readability, or
       * writeability are allowed.
       */
      public void setRestricted(boolean restricted) {
          this.restricted = restricted;
      }
  
      /**
       * Should this DynaClass return a <code>null</code> from
       * the <code>getDynaProperty(name)</code> method if the property
       * doesn't exist.
       */
      public boolean isReturnNull() {
          return returnNull;
      }
  
      /**
       * Set whether this DynaClass should return a <code>null</code> from
       * the <code>getDynaProperty(name)</code> method if the property
       * doesn't exist.
       */
      public void setReturnNull(boolean returnNull) {
          this.returnNull = returnNull;
      }
  
      /**
       * Add a new dynamic property with no restrictions on data type,
       * readability, or writeability.
       *
       * @param name Name of the new dynamic property
       *
       * @exception IllegalArgumentException if name is null
       * @exception IllegalStateException if this DynaClass is currently
       *  restricted, so no new properties can be added
       */
      public void add(String name) {
          add(new DynaProperty(name));
      }
  
      /**
       * Add a new dynamic property with the specified data type, but with
       * no restrictions on readability or writeability.
       *
       * @param name Name of the new dynamic property
       * @param type Data type of the new dynamic property (null for no
       *  restrictions)
       *
       * @exception IllegalArgumentException if name is null
       * @exception IllegalStateException if this DynaClass is currently
       *  restricted, so no new properties can be added
       */
      public void add(String name, Class type) {
          add(new DynaProperty(name, type));
      }
  
      /**
       * <p>Add a new dynamic property with the specified data type, readability,
       * and writeability.</p>
       *
       * <p><strong>N.B.</strong>Support for readable/writeable properties has not been implemented
       *    and this method always throws a <code>UnsupportedOperationException</code>.</p>
       *
       * <p>I'm not sure the intention of the original authors for this method, but it seems to
       *    me that readable/writable should be attributes of the <code>DynaProperty</code> class
       *    (which they are not) and is the reason this method has not been implemented.</p>
       *
       * @param name Name of the new dynamic property
       * @param type Data type of the new dynamic property (null for no
       *  restrictions)
       * @param readable Set to <code>true</code> if this property value
       *  should be readable
       * @param writeable Set to <code>true</code> if this property value
       *  should be writeable
       *
       * @exception UnsupportedOperationException anytime this method is called
       */
      public void add(String name, Class type, boolean readable, boolean writeable) {
          throw new java.lang.UnsupportedOperationException("readable/writable properties not supported");
      }
  
      /**
       * Add a new dynamic property.
       *
       * @param name Name of the new dynamic property
       * @param type Property the new dynamic property
       *
       * @exception IllegalArgumentException if name is null
       * @exception IllegalStateException if this DynaClass is currently
       *  restricted, so no new properties can be added
       */
      protected void add(DynaProperty property) {
  
          if (property.getName() == null)
              throw new IllegalArgumentException("Property name is missing.");
  
          if (isRestricted())
              throw new IllegalStateException("DynaClass is currently restricted. No new properties can be added.");
  
          // Check if property already exists
          if (propertiesMap.get(name) != null)
             return;
  
          // Create a new property array with the specified property
          DynaProperty[] oldProperties = getDynaProperties();
          DynaProperty[] newProperties = new DynaProperty[oldProperties.length+1];
          System.arraycopy(oldProperties, 0, newProperties, 0, oldProperties.length);
          newProperties[oldProperties.length] = property;
  
         // Update the properties
         setProperties(newProperties);
  
      }
  
      /**
       * Remove the specified dynamic property, and any associated data type,
       * readability, and writeability, from this dynamic class.
       * <strong>NOTE</strong> - This does <strong>NOT</strong> cause any
       * corresponding property values to be removed from DynaBean instances
       * associated with this DynaClass.
       *
       * @param name Name of the dynamic property to remove
       *
       * @exception IllegalArgumentException if name is null
       * @exception IllegalStateException if this DynaClass is currently
       *  restricted, so no properties can be removed
       */
      public void remove(String name) {
  
          if (name == null)
              throw new IllegalArgumentException("Property name is missing.");
  
          if (isRestricted())
              throw new IllegalStateException("DynaClass is currently restricted. No properties can be removed.");
  
          // Ignore if property doesn't exist
          if (propertiesMap.get(name) == null)
              return;
  
  
          // Create a new property array of without the specified property
          DynaProperty[] oldProperties = getDynaProperties();
          DynaProperty[] newProperties = new DynaProperty[oldProperties.length-1];
          int j = 0;
          for (int i = 0; i < oldProperties.length; i++) {
              if (!(name.equals(oldProperties[i].getName()))) {
                  newProperties[j] = oldProperties[i];
                  j++;
              }
          }
  
          // Update the properties
          setProperties(newProperties);
  
      }
  
      /**
       * <p>Return a property descriptor for the specified property.</p>
       *
       * <p>If the property is not found and the <code>returnNull</code> indicator is
       *    <code>true</code>, this method always returns <code>null</code>.</p>
       *
       * <p>If the property is not found and the <code>returnNull</code> indicator is
       *    <code>false</code> a new property descriptor is created and returned (although
       *    its not actually added to the DynaClass's properties). This is the default
       *    beahviour.</p>
       *
       * <p>The reason for not returning a <code>null</code> property descriptor is that
       *    <code>BeanUtils</code> uses this method to check if a property exists
       *    before trying to set it - since these <i>Lazy</i> implementations automatically
       *    add any new properties when they are set, returning <code>null</code> from
       *    this method would defeat their purpose.</p>
       *
       * @param name Name of the dynamic property for which a descriptor
       *  is requested
       *
       * @exception IllegalArgumentException if no property name is specified
       */
      public DynaProperty getDynaProperty(String name) {
  
          if (name == null)
              throw new IllegalArgumentException("Property name is missing.");
  
          DynaProperty dynaProperty = (DynaProperty)propertiesMap.get(name);
  
          // If it doesn't exist and returnNull is false
          // create a new DynaProperty
          if (dynaProperty == null && !isReturnNull() && !isRestricted()) {
              dynaProperty = new DynaProperty(name);
          }
  
          return dynaProperty;
  
      }
  
      /**
       * <p>Indicate whether a property actually exists.</p>
       *
       * <p><strong>N.B.</strong> Using <code>getDynaProperty(name) == null</code>
       * doesn't work in this implementation because that method might
       * return a DynaProperty if it doesn't exist (depending on the
       * <code>returnNull</code> indicator).</p>
       *
       * @exception IllegalArgumentException if no property name is specified
       */
      public boolean isDynaProperty(String name) {
  
          if (name == null)
              throw new IllegalArgumentException("Property name is missing.");
  
          return propertiesMap.get(name) ==  null ? false : true;
  
      }
  
  }
  
  
  1.1                  jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/LazyDynaBeanTestCase.java
  
  Index: LazyDynaBeanTestCase.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.commons.beanutils;
  
  import java.util.HashMap;
  import java.util.TreeMap;
  import java.util.ArrayList;
  import java.util.LinkedList;
  import java.lang.reflect.InvocationTargetException;
  import junit.framework.TestCase;
  import junit.framework.Test;
  import junit.framework.TestSuite;
  
  /**
   * <p>Test Case for the <code>LazyDynaBean</code> implementation class.</p>
   *
   * @author Niall Pemberton
   */
  public class LazyDynaBeanTestCase extends TestCase {
  
      protected LazyDynaBean  bean      = null;
      protected LazyDynaClass dynaClass = null;
      protected String testProperty     = "myProperty";
      protected String testString1      = "myStringValue-1";
      protected String testString2      = "myStringValue-2";
      protected Integer testInteger1    = new Integer(30);
      protected Integer testInteger2    = new Integer(40);
      protected String testKey          = "myKey";
  
      // ---------------------------------------------------------- Constructors
  
      /**
       * Construct a new instance of this test case.
       *
       * @param name Name of the test case
       */
      public LazyDynaBeanTestCase(String name) {
          super(name);
      }
  
      // -------------------------------------------------- Overall Test Methods
  
      /**
       * Run thus Test
       */
      public static void main(String[] args) {
          junit.textui.TestRunner.run(suite());
      }
  
      /**
       * Return the tests included in this test suite.
       */
      public static Test suite() {
          return (new TestSuite(LazyDynaBeanTestCase.class));
      }
  
      /**
       * Set up instance variables required by this test case.
       */
      public void setUp() throws Exception {
          bean = new LazyDynaBean();
          dynaClass = (LazyDynaClass)bean.getDynaClass();
          dynaClass.setReturnNull(true);
      }
  
      /**
       * Tear down instance variables required by this test case.
       */
      public void tearDown() {
        bean = null;
      }
  
      // ------------------------------------------------ Individual Test Methods
  
      /**
       * Test Getting/Setting a Simple Property
       */
      public void testSimpleProperty() {
  
          // Check the property & value doesn't exist
          assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Value is null", bean.get(testProperty));
  
          // Set a new property - should add new property and set value
          bean.set(testProperty, testInteger1);
          assertEquals("Check First Value is correct", testInteger1, bean.get(testProperty));
          assertEquals("Check Property type is correct", Integer.class, dynaClass.getDynaProperty(testProperty).getType());
  
          // Set the property again - should set the new value
          bean.set(testProperty, testInteger2);
          assertEquals("Check Second Value is correct", testInteger2, bean.get(testProperty));
  
          // Set the property again - with a different type, should fail
          try {
              bean.set(testProperty, testString1);
              fail("expected ConversionException trying to set an Integer property to a String");
          } catch (ConversionException expected) {
              // expected result
          }
  
      }
  
      /**
       * Test Setting a Simple Property when MutableDynaClass is set to restricted
       */
      public void testSimplePropertyRestricted() {
  
          // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
          dynaClass.setRestricted(true);
          assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
  
          // Check the property & value doesn't exist
          assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Value is null", bean.get(testProperty));
  
          // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
          try {
              bean.set(testProperty, testString1);
              fail("expected IllegalArgumentException trying to add new property to restricted DynaClass");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
  
      }
  
      /**
       * Test Getting/Setting a 'Mapped' Property - default HashMap property
       */
      public void testMappedPropertyDefault() {
  
          // Check the property & value doesn't exist
          assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Map is null", bean.get(testProperty));
          assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
  
          // Set a new mapped property - should add new HashMap property and set the mapped value
          bean.set(testProperty, testKey, testInteger1);
          assertEquals("Check Mapped Property exists", HashMap.class, bean.get(testProperty).getClass());
          assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
          assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((HashMap)bean.get(testProperty)).get(testKey));
  
          // Set the property again - should set the new value
          bean.set(testProperty, testKey, testInteger2);
          assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
          assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((HashMap)bean.get(testProperty)).get(testKey));
      }
  
      /**
       * Test Getting/Setting a 'Mapped' Property - use TreeMap property
       */
      public void testMappedPropertyTreeMap() {
  
          // Check the property & value doesn't exist
          assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Map is null", bean.get(testProperty));
          assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
  
          // Add a 'TreeMap' property to the DynaClass
          dynaClass.add(testProperty, TreeMap.class);
          assertTrue("Check Property is mapped", dynaClass.getDynaProperty(testProperty).isMapped());
          assertEquals("Check Property is correct type", TreeMap.class, dynaClass.getDynaProperty(testProperty).getType());
          assertNull("Check mapped property is null", bean.get(testProperty));
  
          // Set a new mapped property - should instatiate a new TreeMap property and set the mapped value
          bean.set(testProperty, testKey, testInteger1);
          assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
          assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
          assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((TreeMap)bean.get(testProperty)).get(testKey));
  
          // Set the property again - should set the new value
          bean.set(testProperty, testKey, testInteger2);
          assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
          assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((TreeMap)bean.get(testProperty)).get(testKey));
      }
  
      /**
       * Test Setting a 'Mapped' Property using PropertyUtils
       */
      public void testMappedPropertyUtils() {
  
          dynaClass.setReturnNull(false);
  
          // Check the property & value doesn't exist
          assertFalse("Check Mapped Property doesn't exist", dynaClass.isDynaProperty(testProperty));
          assertNull("Check Map is null", bean.get(testProperty));
          assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
  
          // Set the mapped property using PropertyUtils
          try {
            PropertyUtils.setProperty(bean, testProperty+"("+testKey+")", testString1);
          }
          catch (NoSuchMethodException ex) {
              fail("testIndexedPropertyUtils threw "+ex);
          }
          catch (InvocationTargetException ex) {
              fail("testIndexedPropertyUtils threw "+ex);
          }
          catch (IllegalAccessException ex) {
              fail("testIndexedPropertyUtils threw "+ex);
          }
  
          // Check property value correctly set
          assertEquals("Check Mapped Bean Value is correct", testString1, bean.get(testProperty, testKey));
  
      }
  
      /**
       * Test Setting a Mapped Property when MutableDynaClass is set to restricted
       */
      public void testMappedPropertyRestricted() {
  
          // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
          dynaClass.setRestricted(true);
          assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
  
          // Check the property & value doesn't exist
          assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Value is null", bean.get(testProperty));
  
          // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
          try {
              bean.set(testProperty, testKey, testInteger1);
              fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
  
      }
  
      /**
       * Test setting mapped property for type which is not Map
       */
      public void testMappedInvalidType() {
          dynaClass.add(testProperty, String.class);
          assertFalse("Check Property is not mapped", dynaClass.getDynaProperty(testProperty).isMapped());
          try {
              bean.set(testProperty, testKey, testInteger1);
              fail("set(property, key, value) should have thrown IllegalArgumentException");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
      }
  
      /**
       * Test Getting/Setting an 'Indexed' Property - default ArrayList property
       */
      public void testIndexedPropertyDefault() {
  
          int index = 3;
  
          // Check the property & value doesn't exist
          assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Indexed Property is null", bean.get(testProperty));
          assertNull("Check Indexed value is null", bean.get(testProperty, index));
  
          // Set the property, should create new ArrayList and set appropriate indexed value
          bean.set(testProperty, index, testInteger1);
          assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
          assertEquals("Check Indexed Property is correct type", ArrayList.class, bean.get(testProperty).getClass());
          assertEquals("Check First Indexed Value is correct", testInteger1, bean.get(testProperty, index));
          assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((ArrayList)bean.get(testProperty)).size()));
  
          // Set a second indexed value, should automatically grow the ArrayList and set appropriate indexed value
          index = index + 2;
          bean.set(testProperty, index, testString1);
          assertEquals("Check Second Indexed Value is correct", testString1, bean.get(testProperty, index));
          assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((ArrayList)bean.get(testProperty)).size()));
      }
  
      /**
       * Test Getting/Setting a List 'Indexed' Property - use alternative List (LinkedList)
       */
      public void testIndexedLinkedList() {
  
          int   index     = 3;
  
          // Check the property & value doesn't exist
          assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Indexed Property is null", bean.get(testProperty));
          assertNull("Check Indexed value is null", bean.get(testProperty, index));
  
          // Add a 'LinkedList' property to the DynaClass
          dynaClass.add(testProperty, LinkedList.class);
          assertTrue("Check Property is indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
          assertEquals("Check Property is correct type", LinkedList.class, dynaClass.getDynaProperty(testProperty).getType());
          assertNull("Check Indexed property is null", bean.get(testProperty));
  
          // Set the property, should instantiate a new LinkedList and set appropriate indexed value
          bean.set(testProperty, index, testString1);
          assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());
          assertEquals("Check First Indexed Value is correct", testString1, bean.get(testProperty, index));
          assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((LinkedList)bean.get(testProperty)).size()));
  
          // Set a second indexed value, should automatically grow the LinkedList and set appropriate indexed value
          index = index + 2;
          bean.set(testProperty, index, testInteger1);
          assertEquals("Check Second Indexed Value is correct", testInteger1, bean.get(testProperty, index));
          assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((LinkedList)bean.get(testProperty)).size()));
      }
  
      /**
       * Test Getting/Setting a primitive array 'Indexed' Property - use int[]
       */
      public void testIndexedPrimitiveArray() {
  
          int   index     = 3;
          int[] primitiveArray = new int[0];
  
          // Check the property & value doesn't exist
          assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Indexed Property is null", bean.get(testProperty));
          assertNull("Check Indexed value is null", bean.get(testProperty, index));
  
          // Add a DynaProperty of type int[]
          dynaClass.add(testProperty, primitiveArray.getClass());
          assertEquals("Check Indexed Property exists", primitiveArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
          assertNull("Check Indexed Property is null", bean.get(testProperty));
  
          // Set an indexed value
          bean.set(testProperty, index, testInteger1);
          assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
          assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());
          assertEquals("Check First Indexed Value is correct(a)", testInteger1, bean.get(testProperty, index));
          assertEquals("Check First Indexed Value is correct(b)", testInteger1, new Integer(((int[])bean.get(testProperty))[index]));
          assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((int[])bean.get(testProperty)).length));
  
          // Set a second indexed value, should automatically grow the int[] and set appropriate indexed value
          index = index + 2;
          bean.set(testProperty, index, testInteger2);
          assertEquals("Check Second Indexed Value is correct(a)", testInteger2, bean.get(testProperty, index));
          assertEquals("Check Second Indexed Value is correct(b)", testInteger2, new Integer(((int[])bean.get(testProperty))[index]));
          assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((int[])bean.get(testProperty)).length));
  
      }
  
      /**
       * Test Getting/Setting an Object array 'Indexed' Property - use String[]
       */
      public void testIndexedObjectArray() {
  
          int   index     = 3;
          Object objectArray = new String[0];
  
          // Check the property & value doesn't exist
          assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Indexed Property is null", bean.get(testProperty));
          assertNull("Check Indexed value is null", bean.get(testProperty, index));
  
          // Add a DynaProperty of type String[]
          dynaClass.add(testProperty, objectArray.getClass());
          assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
          assertNull("Check Indexed Property is null", bean.get(testProperty));
  
          // Set an indexed value
          bean.set(testProperty, index, testString1);
          assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
          assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
          assertEquals("Check First Indexed Value is correct(a)", testString1, bean.get(testProperty, index));
          assertEquals("Check First Indexed Value is correct(b)", testString1, ((String[])bean.get(testProperty))[index]);
          assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((String[])bean.get(testProperty)).length));
  
          // Set a second indexed value, should automatically grow the String[] and set appropriate indexed value
          index = index + 2;
          bean.set(testProperty, index, testString2);
          assertEquals("Check Second Indexed Value is correct(a)", testString2, bean.get(testProperty, index));
          assertEquals("Check Second Indexed Value is correct(b)", testString2, ((String[])bean.get(testProperty))[index]);
          assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((String[])bean.get(testProperty)).length));
      }
  
      /**
       * Test Setting an 'Indexed' Property using PropertyUtils
       */
      public void testIndexedPropertyUtils() {
  
          int   index     = 3;
          dynaClass.setReturnNull(false);
  
          // Check the property & value doesn't exist
          assertFalse("Check Indexed Property doesn't exist", dynaClass.isDynaProperty(testProperty));
          assertNull("Check Indexed Property is null", bean.get(testProperty));
          assertNull("Check Indexed value is null", bean.get(testProperty, index));
  
          // Use PropertyUtils to set the indexed value
          try {
            PropertyUtils.setProperty(bean, testProperty+"["+index+"]", testString1);
          }
          catch (NoSuchMethodException ex) {
              fail("testIndexedPropertyUtils threw "+ex);
          }
          catch (InvocationTargetException ex) {
              fail("testIndexedPropertyUtils threw "+ex);
          }
          catch (IllegalAccessException ex) {
              fail("testIndexedPropertyUtils threw "+ex);
          }
  
          // Check property value correctly set
          assertEquals("Check Indexed Bean Value is correct", testString1, bean.get(testProperty, index));
  
      }
  
      /**
       * Test Setting an Indexed Property when MutableDynaClass is set to restricted
       */
      public void testIndexedPropertyRestricted() {
  
          int   index     = 3;
  
          // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
          dynaClass.setRestricted(true);
          assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
  
          // Check the property & value doesn't exist
          assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
          assertNull("Check Value is null", bean.get(testProperty));
  
          // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
          try {
              bean.set(testProperty, index, testInteger1);
              fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
  
      }
  
      /**
       * Test setting indexed property for type which is not List or Array
       */
      public void testIndexedInvalidType() {
          int   index     = 3;
          dynaClass.add(testProperty, String.class);
          assertFalse("Check Property is not indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
          try {
              bean.set(testProperty, index, testString1);
              fail("set(property, index, value) should have thrown IllegalArgumentException");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
      }
  
  }
  
  
  1.1                  jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/LazyDynaClassTestCase.java
  
  Index: LazyDynaClassTestCase.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.commons.beanutils;
  
  import junit.framework.TestCase;
  import junit.framework.Test;
  import junit.framework.TestSuite;
  
  /**
   * <p>Test Case for the <code>LazyDynaClass</code> implementation class.</p>
   *
   * @author Niall Pemberton
   */
  public class LazyDynaClassTestCase extends TestCase {
  
      protected LazyDynaClass dynaClass = null;
      protected String testProperty     = "myProperty";
  
      // ---------------------------------------------------------- Constructors
  
      /**
       * Construct a new instance of this test case.
       *
       * @param name Name of the test case
       */
      public LazyDynaClassTestCase(String name) {
          super(name);
      }
  
      // -------------------------------------------------- Overall Test Methods
  
      /**
       * Run this Test
       */
      public static void main(String[] args) {
        junit.textui.TestRunner.run(suite());
      }
  
      /**
       * Set up instance variables required by this test case.
       */
      public void setUp() throws Exception {
          dynaClass = new LazyDynaClass();
      }
  
      /**
       * Return the tests included in this test suite.
       */
      public static Test suite() {
          return (new TestSuite(LazyDynaClassTestCase.class));
      }
  
      /**
       * Tear down instance variables required by this test case.
       */
      public void tearDown() {
          dynaClass = null;
      }
  
      // ------------------------------------------------ Individual Test Methods
  
      /**
       * Test add(name) method
       */
      public void testAddProperty1() {
          dynaClass.add(testProperty);
          DynaProperty dynaProperty = dynaClass.getDynaProperty(testProperty);
          assertEquals("name is correct", testProperty, dynaProperty.getName());
          assertEquals("type is correct", Object.class, dynaProperty.getType());
      }
  
      /**
       * Test add(name, type) method
       */
      public void testAddProperty2() {
          dynaClass.add(testProperty, String.class);
          DynaProperty dynaProperty = dynaClass.getDynaProperty(testProperty);
          assertEquals("name is correct", testProperty, dynaProperty.getName());
          assertEquals("type is correct", String.class, dynaProperty.getType());
      }
  
      /**
       * Test add(name, type, readable, writable) method
       */
      public void testAddProperty3() {
          try {
              dynaClass.add(testProperty, String.class, true, true);
              fail("add(name, type, readable, writable) did not throw UnsupportedOperationException");
          } catch (UnsupportedOperationException expected) {
              // expected result
          }
      }
  
      /**
       * Test add(name) method with 'null' name
       */
      public void testAddPropertyNullName1() {
          try {
              dynaClass.add((String)null);
              fail("null property name not prevented");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
      }
  
      /**
       * Test add(name, type) method with 'null' name
       */
      public void testAddPropertyNullName2() {
          try {
              dynaClass.add(null, String.class);
              fail("null property name not prevented");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
      }
  
      /**
       * Test add(name, type, readable, writable) method with 'null' name
       */
      public void testAddPropertyNullName3() {
          try {
              dynaClass.add(null, String.class, true, true);
              fail("add(name, type, readable, writable) did not throw UnsupportedOperationException");
          } catch (UnsupportedOperationException expected) {
              // expected result
          }
      }
  
      /**
       * Test add(name) method when restricted is set to 'true'
       */
      public void testAddPropertyRestricted1() {
          dynaClass.setRestricted(true);
          assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
          try {
              dynaClass.add(testProperty);
              fail("add(name) did not throw IllegalStateException");
          } catch (IllegalStateException expected) {
              // expected result
          }
      }
  
      /**
       * Test add(name, type) method when restricted is set to 'true'
       */
      public void testAddPropertyRestricted2() {
          dynaClass.setRestricted(true);
          assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
          try {
              dynaClass.add(testProperty, String.class);
              fail("add(name, type) did not throw IllegalStateException");
          } catch (IllegalStateException expected) {
              // expected result
          }
      }
  
      /**
       * Test add(name, type, readable, writable) method when restricted is set to 'true'
       */
      public void testAddPropertyRestricted3() {
          dynaClass.setRestricted(true);
          assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
          try {
              dynaClass.add(testProperty, String.class, true, true);
              fail("add(name, type, readable, writable) did not throw UnsupportedOperationException");
          } catch (UnsupportedOperationException t) {
              // expected result
          }
      }
  
      /**
       * Test retrieving a property which doesn't exist (returnNull is 'false')
       */
      public void testGetPropertyDoesntExist1() {
          dynaClass.setReturnNull(false);
          assertFalse("returnNull is 'false'", dynaClass.isReturnNull());
          DynaProperty dynaProperty = dynaClass.getDynaProperty(testProperty);
          assertEquals("name is correct", testProperty, dynaProperty.getName());
          assertEquals("type is correct", Object.class, dynaProperty.getType());
          assertFalse("property doesnt exist", dynaClass.isDynaProperty(testProperty));
      }
  
  
      /**
       * Test retrieving a property which doesn't exist (returnNull is 'true')
       */
      public void testGetPropertyDoesntExist2() {
          dynaClass.setReturnNull(true);
          assertTrue("returnNull is 'true'", dynaClass.isReturnNull());
          assertNull("property is null", dynaClass.getDynaProperty(testProperty));
      }
  
      /**
       * Test removing a property
       */
      public void testRemoveProperty() {
          dynaClass.setReturnNull(true);
          dynaClass.add(testProperty);
          assertTrue("Property exists", dynaClass.isDynaProperty(testProperty));
          assertNotNull("property is Not null", dynaClass.getDynaProperty(testProperty));
          dynaClass.remove(testProperty);
          assertFalse("Property doesn't exist", dynaClass.isDynaProperty(testProperty));
          assertNull("property is null", dynaClass.getDynaProperty(testProperty));
      }
  
      /**
       * Test removing a property, name is null
       */
      public void testRemovePropertyNullName() {
          try {
              dynaClass.remove(null);
              fail("remove(null) did not throw IllegalArgumentException");
          } catch (IllegalArgumentException expected) {
              // expected result
          }
      }
  
      /**
       * Test removing a property, DynaClass is restricted
       */
      public void testRemovePropertyRestricted() {
          dynaClass.add(testProperty);
          assertTrue("Property exists", dynaClass.isDynaProperty(testProperty));
          dynaClass.setRestricted(true);
          assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
          try {
              dynaClass.remove(testProperty);
              fail("remove property when MutableDynaClassis restricted did not throw IllegalStateException");
          } catch (IllegalStateException expected) {
              // expected result
          }
      }
  
      /**
       * Test removing a property which doesn't exist
       */
      public void testRemovePropertyDoesntExist() {
          assertFalse("property doesn't exist", dynaClass.isDynaProperty(testProperty));
          dynaClass.remove(testProperty);
          assertFalse("property still doesn't exist", dynaClass.isDynaProperty(testProperty));
      }
  }
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org