alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Commons Beanutils example source code file (LazyDynaBean.java)

This example Commons Beanutils source code file (LazyDynaBean.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Commons Beanutils tags/keywords

class, class, illegalargumentexception, illegalargumentexception, io, lazydynabean, list, map, map, math, no, non-indexed, non-mapped, object, object, reflection, string, util

The Commons Beanutils LazyDynaBean.java source code

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.util.Date;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.io.Serializable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <p>DynaBean which automatically adds properties to the DynaClass
 *   and provides <i>Lazy List and Lazy Map features.

* * <p>DynaBeans deal with three types of properties - simple, indexed and mapped and * have the following <code>get() and set() methods for * each of these types:</p> * <ul> * <li>Simple property methods - get(name) and * <code>set(name, value) * <li>Indexed property methods - get(name, index) and * <code>set(name, index, value) * <li>Mapped property methods - get(name, key) and * <code>set(name, key, value) * </ul> * * <p>Getting Property Values

* <p>Calling any of the get() methods, for a property which * doesn't exist, returns <code>null in this implementation.

* * <p>Setting Simple Properties

* <p>The LazyDynaBean will automatically add a property to the DynaClass * if it doesn't exist when the <code>set(name, value) method is called.

* * <code>DynaBean myBean = new LazyDynaBean();
* <code>myBean.set("myProperty", "myValue");
* * <p>Setting Indexed Properties

* <p>If the property doesn't exist, the LazyDynaBean will automatically add * a property with an <code>ArrayList type to the DynaClass when * the <code>set(name, index, value) method is called. * It will also instantiate a new <code>ArrayList and automatically grow * the <code>List so that it is big enough to accomodate the index being set. * <code>ArrayList is the default indexed property that LazyDynaBean uses but * this can be easily changed by overriding the <code>defaultIndexedProperty(name) * method.</p> * * <code>DynaBean myBean = new LazyDynaBean();
* <code>myBean.set("myIndexedProperty", 0, "myValue1");
* <code>myBean.set("myIndexedProperty", 1, "myValue2");
* * <p>If the indexed property does exist in the DynaClass but is set to * <code>null in the LazyDynaBean, then it will instantiate a * new <code>List or Array as specified by the property's type * in the <code>DynaClass and automatically grow the List * or <code>Array so that it is big enough to accomodate the index being set.

* * <code>DynaBean myBean = new LazyDynaBean();
* <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();
* <code>myClass.add("myIndexedProperty", int[].class);
* <code>myBean.set("myIndexedProperty", 0, new Integer(10));
* <code>myBean.set("myIndexedProperty", 1, new Integer(20));
* * <p>Setting Mapped Properties

* <p>If the property doesn't exist, the LazyDynaBean will automatically add * a property with a <code>HashMap type to the DynaClass and * instantiate a new <code>HashMap in the DynaBean when the * <code>set(name, key, value) method is called. HashMap is the default * mapped property that LazyDynaBean uses but this can be easily changed by overriding * the <code>defaultMappedProperty(name) method.

* * <code>DynaBean myBean = new LazyDynaBean();
* <code>myBean.set("myMappedProperty", "myKey", "myValue");
* * <p>If the mapped property does exist in the DynaClass but is set to * <code>null in the LazyDynaBean, then it will instantiate a * new <code>Map as specified by the property's type in the DynaClass.

* * <code>DynaBean myBean = new LazyDynaBean();
* <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();
* <code>myClass.add("myMappedProperty", TreeMap.class);
* <code>myBean.set("myMappedProperty", "myKey", "myValue");
* * <p>Restricted DynaClass

* <p>MutableDynaClass have a facility to restrict the DynaClass * so that its properties cannot be modified. If the <code>MutableDynaClass is * restricted then calling any of the <code>set() methods for a property which * doesn't exist will result in a <code>IllegalArgumentException being thrown.

* * @see LazyDynaClass * @author Niall Pemberton */ public class LazyDynaBean implements DynaBean, Serializable { /** * Commons Logging */ private transient Log logger = LogFactory.getLog(LazyDynaBean.class); /** BigInteger Zero */ protected static final BigInteger BigInteger_ZERO = new BigInteger("0"); /** BigDecimal Zero */ protected static final BigDecimal BigDecimal_ZERO = new BigDecimal("0"); /** Character Space */ protected static final Character Character_SPACE = new Character(' '); /** Byte Zero */ protected static final Byte Byte_ZERO = new Byte((byte)0); /** Short Zero */ protected static final Short Short_ZERO = new Short((short)0); /** Integer Zero */ protected static final Integer Integer_ZERO = new Integer(0); /** Long Zero */ protected static final Long Long_ZERO = new Long(0); /** Float Zero */ protected static final Float Float_ZERO = new Float((byte)0); /** Double Zero */ protected static final Double Double_ZERO = new Double((byte)0); /** * The <code>MutableDynaClass "base class" that this DynaBean * is associated with. */ protected Map values; /** Map decorator for this DynaBean */ private transient Map mapDecorator; /** * The <code>MutableDynaClass "base class" that this DynaBean * is associated with. */ protected MutableDynaClass dynaClass; // ------------------- Constructors ---------------------------------- /** * Construct a new <code>LazyDynaBean with a LazyDynaClass instance. */ public LazyDynaBean() { this(new LazyDynaClass()); } /** * Construct a new <code>LazyDynaBean with a LazyDynaClass instance. * * @param name Name of this DynaBean class */ public LazyDynaBean(String name) { this(new LazyDynaClass(name)); } /** * Construct a new <code>DynaBean associated with the specified * <code>DynaClass instance - if its not a MutableDynaClass * then a new <code>LazyDynaClass is created and the properties copied. * * @param dynaClass The DynaClass we are associated with */ public LazyDynaBean(DynaClass dynaClass) { values = newMap(); if (dynaClass instanceof MutableDynaClass) { this.dynaClass = (MutableDynaClass)dynaClass; } else { this.dynaClass = new LazyDynaClass(dynaClass.getName(), dynaClass.getDynaProperties()); } } // ------------------- Public Methods ---------------------------------- /** * Return a Map representation of this DynaBean. * </p> * This, for example, could be used in JSTL in the following way to access * a DynaBean's <code>fooProperty: * <ul>
  • ${myDynaBean.map.fooProperty}
  • * * @return a Map representation of this DynaBean */ public Map getMap() { // cache the Map if (mapDecorator == null) { mapDecorator = new DynaBeanMapDecorator(this); } return mapDecorator; } /** * <p>Return the size of an indexed or mapped property.

    * * @param name Name of the property * @return The indexed or mapped property size * @exception IllegalArgumentException if no property name is specified */ public int size(String name) { if (name == null) { throw new IllegalArgumentException("No property name specified"); } Object value = values.get(name); if (value == null) { return 0; } if (value instanceof Map) { return ((Map)value).size(); } if (value instanceof List) { return ((List)value).size(); } if ((value.getClass().isArray())) { return Array.getLength(value); } return 0; } // ------------------- DynaBean Methods ---------------------------------- /** * Does the specified mapped property contain a value for the specified * key value? * * @param name Name of the property to check * @param key Name of the key to check * @return <code>true if the mapped property contains a value for * the specified key, otherwise <code>false * * @exception IllegalArgumentException if no property name is specified */ public boolean contains(String name, String key) { if (name == null) { throw new IllegalArgumentException("No property name specified"); } Object value = values.get(name); if (value == null) { return false; } if (value instanceof Map) { return (((Map) value).containsKey(key)); } return false; } /** * <p>Return the value of a simple property with the specified name.

    * * <p>N.B. Returns null if there is no property * of the specified name.</p> * * @param name Name of the property whose value is to be retrieved. * @return The property's value * @exception IllegalArgumentException if no property name is specified */ public Object get(String name) { if (name == null) { throw new IllegalArgumentException("No property name specified"); } // Value found Object value = values.get(name); if (value != null) { return value; } // Property doesn't exist if (!isDynaProperty(name)) { return null; } // Property doesn't exist value = createProperty(name, dynaClass.getDynaProperty(name).getType()); if (value != null) { set(name, value); } return value; } /** * <p>Return the value of an indexed property with the specified name.

    * * <p>N.B. Returns null 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 * @return The indexed property's value * * @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 its not a property, then create default indexed property if (!isDynaProperty(name)) { set(name, defaultIndexedProperty(name)); } // Get the indexed property Object indexedProperty = get(name); // Check that the property is indexed if (!dynaClass.getDynaProperty(name).isIndexed()) { throw new IllegalArgumentException ("Non-indexed property for '" + name + "[" + index + "]' " + dynaClass.getDynaProperty(name).getName()); } // Grow indexed property to appropriate size indexedProperty = growIndexedProperty(name, indexedProperty, index); // Return the indexed value if (indexedProperty.getClass().isArray()) { return Array.get(indexedProperty, index); } else if (indexedProperty instanceof List) { return ((List)indexedProperty).get(index); } else { throw new IllegalArgumentException ("Non-indexed property for '" + name + "[" + index + "]' " + indexedProperty.getClass().getName()); } } /** * <p>Return the value of a mapped property with the specified name.

    * * <p>N.B. Returns null 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 * @return The mapped property's value * * @exception IllegalArgumentException if the specified property * exists, but is not mapped */ public Object get(String name, String key) { // If its not a property, then create default mapped property if (!isDynaProperty(name)) { set(name, defaultMappedProperty(name)); } // Get the mapped property Object mappedProperty = get(name); // Check that the property is mapped if (!dynaClass.getDynaProperty(name).isMapped()) { throw new IllegalArgumentException ("Non-mapped property for '" + name + "(" + key + ")' " + dynaClass.getDynaProperty(name).getType().getName()); } // Get the value from the Map if (mappedProperty instanceof Map) { return (((Map) mappedProperty).get(key)); } else { throw new IllegalArgumentException ("Non-mapped property for '" + name + "(" + key + ")'" + mappedProperty.getClass().getName()); } } /** * Return the <code>DynaClass instance that describes the set of * properties available for this DynaBean. * * @return The associated DynaClass */ public DynaClass getDynaClass() { return dynaClass; } /** * Remove any existing value for the specified key on the * specified mapped property. * * @param name Name of the property for which a value is to * be removed * @param key Key of the value to be removed * * @exception IllegalArgumentException if there is no property * of the specified name */ public void remove(String name, String key) { if (name == null) { throw new IllegalArgumentException("No property name specified"); } Object value = values.get(name); if (value == null) { return; } if (value instanceof Map) { ((Map) value).remove(key); } else { throw new IllegalArgumentException ("Non-mapped property for '" + name + "(" + key + ")'" + value.getClass().getName()); } } /** * 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 (dynaClass.isRestricted()) { throw new IllegalArgumentException ("Invalid property name '" + name + "' (DynaClass is restricted)"); } if (value == null) { dynaClass.add(name); } else { dynaClass.add(name, value.getClass()); } } DynaProperty descriptor = dynaClass.getDynaProperty(name); if (value == null) { if (descriptor.getType().isPrimitive()) { throw new NullPointerException ("Primitive value for '" + name + "'"); } } else if (!isAssignable(descriptor.getType(), value.getClass())) { throw new ConversionException ("Cannot assign value of type '" + value.getClass().getName() + "' to property '" + name + "' of type '" + descriptor.getType().getName() + "'"); } // Set the property's value values.put(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 its not a property, then create default indexed property if (!isDynaProperty(name)) { set(name, defaultIndexedProperty(name)); } // Get the indexed property Object indexedProperty = get(name); // Check that the property is indexed if (!dynaClass.getDynaProperty(name).isIndexed()) { throw new IllegalArgumentException ("Non-indexed property for '" + name + "[" + index + "]'" + dynaClass.getDynaProperty(name).getType().getName()); } // Grow indexed property to appropriate size indexedProperty = growIndexedProperty(name, indexedProperty, index); // Set the value in an array if (indexedProperty.getClass().isArray()) { Array.set(indexedProperty, index, value); } else if (indexedProperty instanceof List) { ((List)indexedProperty).set(index, value); } else { throw new IllegalArgumentException ("Non-indexed property for '" + name + "[" + index + "]' " + indexedProperty.getClass().getName()); } } /** * 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, defaultMappedProperty(name)); } // Get the mapped property Object mappedProperty = get(name); // Check that the property is mapped if (!dynaClass.getDynaProperty(name).isMapped()) { throw new IllegalArgumentException ("Non-mapped property for '" + name + "(" + key + ")'" + dynaClass.getDynaProperty(name).getType().getName()); } // Set the value in the Map ((Map)mappedProperty).put(key, value); } // ------------------- protected Methods ---------------------------------- /** * Grow the size of an indexed property * @param name The name of the property * @param indexedProperty The current property value * @param index The indexed value to grow the property to (i.e. one less than * the required size) * @return The new property value (grown to the appropriate size) */ protected Object growIndexedProperty(String name, Object indexedProperty, int index) { // Grow a List to the appropriate size if (indexedProperty instanceof List) { List list = (List)indexedProperty; while (index >= list.size()) { Class contentType = getDynaClass().getDynaProperty(name).getContentType(); Object value = null; if (contentType != null) { value = createProperty(name+"["+list.size()+"]", contentType); } list.add(value); } } // Grow an Array to the appropriate size if ((indexedProperty.getClass().isArray())) { int length = Array.getLength(indexedProperty); if (index >= length) { Class componentType = indexedProperty.getClass().getComponentType(); Object newArray = Array.newInstance(componentType, (index + 1)); System.arraycopy(indexedProperty, 0, newArray, 0, length); indexedProperty = newArray; set(name, indexedProperty); int newLength = Array.getLength(indexedProperty); for (int i = length; i < newLength; i++) { Array.set(indexedProperty, i, createProperty(name+"["+i+"]", componentType)); } } } return indexedProperty; } /** * Create a new Instance of a Property * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createProperty(String name, Class type) { if (type == null) { return null; } // Create Lists, arrays or DynaBeans if (type.isArray() || List.class.isAssignableFrom(type)) { return createIndexedProperty(name, type); } if (Map.class.isAssignableFrom(type)) { return createMappedProperty(name, type); } if (DynaBean.class.isAssignableFrom(type)) { return createDynaBeanProperty(name, type); } if (type.isPrimitive()) { return createPrimitiveProperty(name, type); } if (Number.class.isAssignableFrom(type)) { return createNumberProperty(name, type); } return createOtherProperty(name, type); } /** * Create a new Instance of an 'Indexed' Property * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createIndexedProperty(String name, Class type) { // Create the indexed object Object indexedProperty = null; if (type == null) { indexedProperty = defaultIndexedProperty(name); } else if (type.isArray()) { indexedProperty = Array.newInstance(type.getComponentType(), 0); } else if (List.class.isAssignableFrom(type)) { if (type.isInterface()) { indexedProperty = defaultIndexedProperty(name); } else { try { indexedProperty = type.newInstance(); } catch (Exception ex) { throw new IllegalArgumentException ("Error instantiating indexed property of type '" + type.getName() + "' for '" + name + "' " + ex); } } } else { throw new IllegalArgumentException ("Non-indexed property of type '" + type.getName() + "' for '" + name + "'"); } return indexedProperty; } /** * Create a new Instance of a 'Mapped' Property * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createMappedProperty(String name, Class type) { // Create the mapped object Object mappedProperty = null; if (type == null) { mappedProperty = defaultMappedProperty(name); } else if (type.isInterface()) { mappedProperty = defaultMappedProperty(name); } else if (Map.class.isAssignableFrom(type)) { try { mappedProperty = type.newInstance(); } catch (Exception ex) { throw new IllegalArgumentException ("Error instantiating mapped property of type '" + type.getName() + "' for '" + name + "' " + ex); } } else { throw new IllegalArgumentException ("Non-mapped property of type '" + type.getName() + "' for '" + name + "'"); } return mappedProperty; } /** * Create a new Instance of a 'DynaBean' Property. * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createDynaBeanProperty(String name, Class type) { try { return type.newInstance(); } catch (Exception ex) { if (logger().isWarnEnabled()) { logger().warn("Error instantiating DynaBean property of type '" + type.getName() + "' for '" + name + "' " + ex); } return null; } } /** * Create a new Instance of a 'Primitive' Property. * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createPrimitiveProperty(String name, Class type) { if (type == Boolean.TYPE) { return Boolean.FALSE; } else if (type == Integer.TYPE) { return Integer_ZERO; } else if (type == Long.TYPE) { return Long_ZERO; } else if (type == Double.TYPE) { return Double_ZERO; } else if (type == Float.TYPE) { return Float_ZERO; } else if (type == Byte.TYPE) { return Byte_ZERO; } else if (type == Short.TYPE) { return Short_ZERO; } else if (type == Character.TYPE) { return Character_SPACE; } else { return null; } } /** * Create a new Instance of a <code>java.lang.Number Property. * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createNumberProperty(String name, Class type) { return null; } /** * Create a new Instance of other Property types * @param name The name of the property * @param type The class of the property * @return The new value */ protected Object createOtherProperty(String name, Class type) { if (type == Object.class || type == String.class || type == Boolean.class || type == Character.class || Date.class.isAssignableFrom(type)) { return null; } try { return type.newInstance(); } catch (Exception ex) { if (logger().isWarnEnabled()) { logger().warn("Error instantiating property of type '" + type.getName() + "' for '" + name + "' " + ex); } return null; } } /** * <p>Creates a new ArrayList for an 'indexed' property * which doesn't exist.</p> * * <p>This method shouls be overriden if an alternative List * or <code>Array implementation is required for 'indexed' properties.

    * * @param name Name of the 'indexed property. * @return The default value for an indexed property (java.util.ArrayList) */ protected Object defaultIndexedProperty(String name) { return new ArrayList(); } /** * <p>Creates a new HashMap for a 'mapped' property * which doesn't exist.</p> * * <p>This method can be overriden if an alternative Map * implementation is required for 'mapped' properties.</p> * * @param name Name of the 'mapped property. * @return The default value for a mapped property (java.util.HashMap) */ protected Map defaultMappedProperty(String name) { return new HashMap(); } /** * Indicates if there is a property with the specified name. * @param name The name of the property to check * @return <code>true if there is a property of the * specified name, otherwise <code>false */ protected boolean isDynaProperty(String name) { if (name == null) { throw new IllegalArgumentException("No property name specified"); } // Handle LazyDynaClasses if (dynaClass instanceof LazyDynaClass) { return ((LazyDynaClass)dynaClass).isDynaProperty(name); } // Handle other MutableDynaClass return dynaClass.getDynaProperty(name) == null ? false : true; } /** * Is an object of the source class assignable to the destination class? * * @param dest Destination class * @param source Source class * @return <code>true if the source class is assignable to the * destination class, otherwise <code>false */ protected boolean isAssignable(Class dest, Class source) { if (dest.isAssignableFrom(source) || ((dest == Boolean.TYPE) && (source == Boolean.class)) || ((dest == Byte.TYPE) && (source == Byte.class)) || ((dest == Character.TYPE) && (source == Character.class)) || ((dest == Double.TYPE) && (source == Double.class)) || ((dest == Float.TYPE) && (source == Float.class)) || ((dest == Integer.TYPE) && (source == Integer.class)) || ((dest == Long.TYPE) && (source == Long.class)) || ((dest == Short.TYPE) && (source == Short.class))) { return (true); } else { return (false); } } /** * <p>Creates a new instance of the Map.

    * @return a new Map instance */ protected Map newMap() { return new HashMap(); } /** * <p>Returns the Log. */ private Log logger() { if (logger == null) { logger = LogFactory.getLog(LazyDynaBean.class); } return logger; } }

    Other Commons Beanutils examples (source code examples)

    Here is a short list of links related to this Commons Beanutils LazyDynaBean.java source code file:

    ... this post is sponsored by my books ...

    #1 New Release!

    FP Best Seller

     

    new blog posts

     

    Copyright 1998-2021 Alvin Alexander, alvinalexander.com
    All Rights Reserved.

    A percentage of advertising revenue from
    pages under the /java/jwarehouse URI on this website is
    paid back to open source projects.