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 2007/05/22 06:52:14 UTC

svn commit: r540419 - in /jakarta/commons/proper/beanutils/trunk: build.xml src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java

Author: niallp
Date: Mon May 21 21:52:13 2007
New Revision: 540419

URL: http://svn.apache.org/viewvc?view=rev&rev=540419
Log:
BEANUTILS-185 Provide a Map decorator for a DynaBean (enables DynaBean to be used with other teechnologies such as JSTL)

Added:
    jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java   (with props)
    jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java   (with props)
Modified:
    jakarta/commons/proper/beanutils/trunk/build.xml

Modified: jakarta/commons/proper/beanutils/trunk/build.xml
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/beanutils/trunk/build.xml?view=diff&rev=540419&r1=540418&r2=540419
==============================================================================
--- jakarta/commons/proper/beanutils/trunk/build.xml (original)
+++ jakarta/commons/proper/beanutils/trunk/build.xml Mon May 21 21:52:13 2007
@@ -271,6 +271,7 @@
                                 test.lazy.dynabean,
                                 test.lazy.dynamap,
                                 test.lazy.dynalist,
+                                test.dynabean.mapdecorator,
                                 test.indexed.properties,
                                 test.mapped.properties
                                "
@@ -500,6 +501,21 @@
       <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
                  value="${test.level}"/>
       <arg value="org.apache.commons.beanutils.LazyDynaListTestCase"/>
+      <classpath refid="test.classpath"/>
+    </java>
+  </target>
+
+  <target name="test.dynabean.mapdecorator" depends="compile.tests">
+    <echo message="Running DynaBeanMapDecorator tests ..."/>
+    <java classname="${test.runner}" fork="yes"
+        failonerror="${test.failonerror}">
+      <sysproperty key="org.apache.commons.logging.LogFactory"
+                 value="${test.factory}"/>
+      <sysproperty key="org.apache.commons.logging.Log"
+                 value="${test.log}"/>
+      <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+                 value="${test.level}"/>
+      <arg value="org.apache.commons.beanutils.DynaBeanMapDecoratorTestCase"/>
       <classpath refid="test.classpath"/>
     </java>
   </target>

Added: jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java?view=auto&rev=540419
==============================================================================
--- jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java (added)
+++ jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java Mon May 21 21:52:13 2007
@@ -0,0 +1,394 @@
+/*
+ * 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.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.LinkedHashSet;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * <p>Decorates a {@link DynaBean} to provide <code>Map</code> behaviour.</p>
+ *
+ * <p>The motivation for this implementation is to provide access to {@link DynaBean}
+ *    properties in technologies that are unaware of BeanUtils and {@link DynaBean}s -
+ *    such as the expression languages of JSTL and JSF.</p>
+ *
+ * <p>This can be achieved either by wrapping the {@link DynaBean} prior to
+ *    providing it to the technolody to process or by providing a <code>Map</code>
+ *    accessor method on the DynaBean implementation:
+ *    <pre><code>
+ *         public Map getMap() {
+ *             return new DynaBeanMapDecorator(this);
+ *         }</code></pre>
+ *   </ul>
+ * </p>
+ *
+ * <p>This, for example, could be used in JSTL in the following way to access
+ *    a DynaBean's <code>fooProperty</code>:
+ *    <ul><li><code>${myDynaBean.<b>map</b>.fooProperty}</code></li></ul>
+ * </p>
+ *
+ * <h3>Usage</h3>
+ *
+ * <p>To decorate a {@link DynaBean} simply instantiate this class with the
+ *    target {@link DynaBean}:</p>
+ *
+ * <ul><li><code>Map fooMap = new DynaBeanMapDecorator(fooDynaBean);</code></li></ul>
+ *
+ * <p>The above example creates a <b><i>read only</i></b> <code>Map</code>.
+ *    To create  a <code>Map</code> which can be modified, construct a
+ *    <code>DynaBeanMapDecorator</code> with the <b><i>read only</i></b>
+ *    attribute set to <code>false</code>:</p>
+ *
+ * <ul><li><code>Map fooMap = new DynaBeanMapDecorator(fooDynaBean, false);</code></li></ul>
+ *
+ * <h3>Limitations</h3>
+ * <p>In this implementation the <code>entrySet()</code>, <code>keySet()</code>
+ *    and <code>values()</code> methods create an <b><i>unmodifiable</i></b>
+ *    <code>Set</code> and it does not support the Map's <code>clear()</code>
+ *    and <code>remove()</code> operations.</p>
+ *
+ * @since BeanUtils 1.8.0
+ * @version $Revision$ $Date$
+ */
+public class DynaBeanMapDecorator implements Map {
+
+    private DynaBean dynaBean;
+    private boolean readOnly;
+    private Set keySet;
+
+    // ------------------- Constructors ----------------------------------
+
+    /**
+     * Constructs a  read only Map for the specified
+     * {@link DynaBean}.
+     *
+     * @param dynaBean The dyna bean being decorated
+     * @throws IllegalArgumentException if the {@link DynaBean} is null.
+     */
+    public DynaBeanMapDecorator(DynaBean dynaBean) {
+        this(dynaBean, true);
+    }
+
+    /**
+     * Construct a Map for the specified {@link DynaBean}.
+     *
+     * @param dynaBean The dyna bean being decorated
+     * @param readOnly <code>true</code> if the Mpa is read only
+     * otherwise <code>false</code>
+     * @throws IllegalArgumentException if the {@link DynaBean} is null.
+     */
+    public DynaBeanMapDecorator(DynaBean dynaBean, boolean readOnly) {
+        if (dynaBean == null) {
+            throw new IllegalArgumentException("DynaBean is null");
+        }
+        this.dynaBean = dynaBean;
+        this.readOnly = readOnly;
+    }
+
+
+    // ------------------- public Methods --------------------------------
+
+
+    /**
+     * Indicate whether the Map is read only.
+     *
+     * @return <code>true</code> if the Map is read only,
+     * otherwise <code>false</code>.
+     */
+    public boolean isReadOnly() {
+        return readOnly;
+    }
+
+    // ------------------- java.util.Map Methods -------------------------
+
+    /**
+     * clear() operation is not supported.
+     *
+     * @throws UnsupportedOperationException
+     */
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Indicate whether the {@link DynaBean} contains a specified
+     * value for one (or more) of its properties.
+     *
+     * @param key The {@link DynaBean}'s property name
+     * @return <code>true</code> if one of the {@link DynaBean}'s
+     * properties contains a specified value.
+     */
+    public boolean containsKey(Object key) {
+        DynaClass dynaClass = getDynaBean().getDynaClass();
+        DynaProperty dynaProperty = dynaClass.getDynaProperty(toString(key));
+        return (dynaProperty == null ? false : true);
+    }
+
+    /**
+     * Indicates whether the decorated {@link DynaBean} contains
+     * a specified value.
+     *
+     * @param value The value to check for.
+     * @return <code>true</code> if one of the the {@link DynaBean}'s
+     * properties contains the specified value, otherwise
+     * <code>false</code>.
+     */
+    public boolean containsValue(Object value) {
+        DynaProperty[] properties = getDynaProperties();
+        for (int i = 0; i < properties.length; i++) {
+            String key = properties[i].getName();
+            Object prop = getDynaBean().get(key);
+            if (value == null) {
+                if (prop == null) {
+                    return true;
+                }
+            } else {
+                if (value.equals(prop)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * <p>Returns the Set of the property/value mappings
+     * in the decorated {@link DynaBean}.</p>
+     *
+     * <p>Each element in the Set is a <code>Map.Entry</code>
+     * type.</p>
+     *
+     * @return An unmodifiable set of the DynaBean
+     * property name/value pairs
+     */
+    public Set entrySet() {
+        DynaProperty[] properties = getDynaProperties();
+        Set set = new LinkedHashSet(properties.length);
+        for (int i = 0; i < properties.length; i++) {
+            String key = properties[i].getName();
+            Object value = getDynaBean().get(key);
+            set.add(new MapEntry(key, value));
+        }
+        return Collections.unmodifiableSet(set);
+    }
+
+    /**
+     * Return the value for the specified key from
+     * the decorated {@link DynaBean}.
+     *
+     * @param key The {@link DynaBean}'s property name
+     * @return The value for the specified property.
+     */
+    public Object get(Object key) {
+        return getDynaBean().get(toString(key));
+    }
+
+    /**
+     * Indicate whether the decorated {@link DynaBean} has
+     * any properties.
+     *
+     * @return <code>true</code> if the {@link DynaBean} has
+     * no properties, otherwise <code>false</code>.
+     */
+    public boolean isEmpty() {
+        return (getDynaProperties().length == 0);
+    }
+
+    /**
+     * <p>Returns the Set of the property
+     * names in the decorated {@link DynaBean}.</p>
+     *
+     * <p><b>N.B.</b>For {@link DynaBean}s whose associated {@link DynaClass}
+     * is a {@link MutableDynaClass} a new Set is created every
+     * time, otherwise the Set is created only once and cached.</p>
+     *
+     * @return An unmodifiable set of the {@link DynaBean}s
+     * property names.
+     */
+    public Set keySet() {
+        if (keySet != null) {
+            return keySet;
+        }
+
+        // Create a Set of the keys
+        DynaProperty[] properties = getDynaProperties();
+        Set set = new LinkedHashSet(properties.length);
+        for (int i = 0; i < properties.length; i++) {
+            set.add(properties[i].getName());
+        }
+        set = Collections.unmodifiableSet(set);
+
+        // Cache the keySet if Not a MutableDynaClass
+        DynaClass dynaClass = getDynaBean().getDynaClass();
+        if (!(dynaClass instanceof MutableDynaClass)) {
+            keySet = set;
+        }
+
+        return set;
+
+    }
+
+    /**
+     * Set the value for the specified property in
+     * the decorated {@link DynaBean}.
+     *
+     * @param key The {@link DynaBean}'s property name
+     * @param value The value for the specified property.
+     * @return The previous property's value.
+     * @throws UnsupportedOperationException if
+     * <code>isReadOnly()</code> is true.
+     */
+    public Object put(Object key, Object value) {
+        if (isReadOnly()) {
+            throw new UnsupportedOperationException("Map is read only");
+        }
+        String property = toString(key);
+        Object previous = getDynaBean().get(property);
+        getDynaBean().set(property, value);
+        return previous;
+    }
+
+    /**
+     * Copy the contents of a Map to the decorated {@link DynaBean}.
+     *
+     * @param map The Map of values to copy.
+     * @throws UnsupportedOperationException if
+     * <code>isReadOnly()</code> is true.
+     */
+    public void putAll(Map map) {
+        if (isReadOnly()) {
+            throw new UnsupportedOperationException("Map is read only");
+        }
+        Iterator keys = map.keySet().iterator();
+        while (keys.hasNext()) {
+            Object key = keys.next();
+            put(key, map.get(key));
+        }
+    }
+
+    /**
+     * remove() operation is not supported.
+     *
+     * @param key The {@link DynaBean}'s property name
+     * @return the value removed
+     * @throws UnsupportedOperationException
+     */
+    public Object remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the number properties in the decorated
+     * {@link DynaBean}.
+     * @return The number of properties.
+     */
+    public int size() {
+        return getDynaProperties().length;
+    }
+
+    /**
+     * Returns the set of property values in the
+     * decorated {@link DynaBean}.
+     *
+     * @return Unmodifiable collection of values.
+     */
+    public Collection values() {
+        DynaProperty[] properties = getDynaProperties();
+        List values = new ArrayList(properties.length);
+        for (int i = 0; i < properties.length; i++) {
+            String key = properties[i].getName();
+            Object value = getDynaBean().get(key);
+            values.add(value);
+        }
+        return Collections.unmodifiableList(values);
+    }
+
+    // ------------------- protected Methods -----------------------------
+
+    /**
+     * Provide access to the underlying {@link DynaBean}
+     * this Map decorates.
+     *
+     * @return the decorated {@link DynaBean}.
+     */
+    protected DynaBean getDynaBean() {
+        return dynaBean;
+    }
+
+    // ------------------- private Methods -------------------------------
+
+    /**
+     * Convenience method to retrieve the {@link DynaProperty}s
+     * for this {@link DynaClass}.
+     *
+     * @return The an array of the {@link DynaProperty}s.
+     */
+    private DynaProperty[] getDynaProperties() {
+        return getDynaBean().getDynaClass().getDynaProperties();
+    }
+
+    /**
+     * Convenience method to convert an Object
+     * to a String.
+     *
+     * @param obj The Object to convert
+     * @return String representation of the object
+     */
+    private String toString(Object obj) {
+        return (obj == null ? null : obj.toString());
+    }
+
+    /**
+     * Map.Entry implementation.
+     */
+    private static class MapEntry implements Map.Entry {
+        private Object key;
+        private Object value;
+        MapEntry(Object key, Object value) {
+            this.key = key;
+            this.value = value;
+        }
+        public boolean equals(Object o) {
+            if (!(o instanceof Map.Entry)) {
+                return false;
+            }
+            Map.Entry e = (Map.Entry)o;
+            return ((key.equals(e.getKey())) &&
+                    (value == null ? e.getValue() == null
+                                   : value.equals(e.getValue())));
+        }
+        public int hashCode() {
+            return key.hashCode() + (value == null ? 0 : value.hashCode());
+        }
+        public Object getKey() {
+            return key;
+        }
+        public Object getValue() {
+            return value;
+        }
+        public Object setValue(Object value) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+}

Propchange: jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/DynaBeanMapDecorator.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java?view=auto&rev=540419
==============================================================================
--- jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java (added)
+++ jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java Mon May 21 21:52:13 2007
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2006 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.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * <p>Test Case for the <code>DynaBeanMapDecorator</code> implementation class.</p>
+ *
+ * @author Niall Pemberton
+ */
+public class DynaBeanMapDecoratorTestCase extends TestCase {
+
+    private static final DynaProperty stringProp = new DynaProperty("stringProp", String.class);
+    private static final DynaProperty nullProp   = new DynaProperty("nullProp",   String.class);
+    private static final DynaProperty intProp    = new DynaProperty("intProp",    Integer.class);
+    private static final DynaProperty dateProp   = new DynaProperty("dateProp",   Date.class);
+    private static final DynaProperty mapProp    = new DynaProperty("mapProp",    Map.class);
+    private static final DynaProperty[] properties = new DynaProperty[] {
+                      stringProp, nullProp, intProp, dateProp, mapProp};
+    private static final DynaClass dynaClass = new BasicDynaClass("testDynaClass", BasicDynaBean.class, properties);
+
+    private static String  stringVal = "somevalue";
+    private static Integer intVal    = new Integer(5);
+    private static Date    dateVal   = new Date();
+    private Map     mapVal    = new HashMap();
+
+    private Object[] values = new Object[] {stringVal, null, intVal, dateVal, mapVal};
+
+    private BasicDynaBean dynaBean;
+    private Map decoratedMap;
+    private Map modifiableMap;
+    private static final Map emptyMap = new DynaBeanMapDecorator(new BasicDynaBean(new BasicDynaClass()));
+
+    // ---------------------------------------------------------- Constructors
+
+    /**
+     * Construct a new instance of this test case.
+     *
+     * @param name Name of the test case
+     */
+    public DynaBeanMapDecoratorTestCase(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(DynaBeanMapDecoratorTestCase.class));
+    }
+
+    /**
+     * Set up instance variables required by this test case.
+     */
+    public void setUp() throws Exception {
+
+        mapVal.clear(); 
+        mapVal.put("key1", "key1Value");
+        mapVal.put("key2", "key2Value");
+
+        // Initialize DynaBean and properties
+        dynaBean = new BasicDynaBean(dynaClass);
+        for (int i = 0; i < properties.length; i++) {
+            dynaBean.set(properties[i].getName(), values[i]);
+        }
+
+        // Create decorated Maps
+        decoratedMap  = new DynaBeanMapDecorator(dynaBean);
+        modifiableMap = new DynaBeanMapDecorator(dynaBean, false);
+
+    }
+
+    /**
+     * Tear down instance variables required by this test case.
+     */
+    public void tearDown() {
+        dynaBean = null;
+        decoratedMap = null;
+        modifiableMap = null;
+    }
+
+    // ------------------------------------------------ Individual Test Methods
+
+    /**
+     * Test isReadOnly() method
+     */
+    public void testIsReadOnly() {
+        assertTrue("decoratedMap true",   ((DynaBeanMapDecorator)decoratedMap).isReadOnly());
+        assertFalse("modifiableMap false", ((DynaBeanMapDecorator)modifiableMap).isReadOnly());
+    }
+
+    /**
+     * Test clear() method
+     */
+    public void testClear() {
+        try {
+            decoratedMap.clear();
+            fail("decoratedMap.clear()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+        try {
+            modifiableMap.clear();
+            fail("modifiableMap.clear()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+    }
+
+    /**
+     * Test containsKey() method
+     */
+    public void testContainsKey() {
+        assertTrue("decoratedMap true",   decoratedMap.containsKey(stringProp.getName()));
+        assertFalse("decoratedMap false", decoratedMap.containsKey("xyz"));
+    }
+
+    /**
+     * Test containsValue() method
+     */
+    public void testContainsValue() {
+        assertTrue("decoratedMap true",   decoratedMap.containsValue(stringVal));
+        assertFalse("decoratedMap false", decoratedMap.containsValue("xyz"));
+    }
+
+    /**
+     * Test entrySet() method
+     */
+    public void testEntrySet() {
+        Set set = modifiableMap.entrySet();
+
+        // Check the Set can't be modified
+        checkUnmodifiable("entrySet()", set);
+
+        assertEquals("entrySet size", properties.length, set.size());
+
+        // Set should be ordered in same sequence as properties
+        Iterator iterator = set.iterator();
+        int i = 0;
+        while (iterator.hasNext()) {
+            Map.Entry entry = (Map.Entry)iterator.next();
+            String expectName  = properties[i].getName();
+            Object expectValue = decoratedMap.get(expectName);
+            assertEquals("entrySet("+i+") key", expectName,  entry.getKey());
+            assertEquals("entrySet("+i+") val", expectValue, entry.getValue());
+            i++;
+        }
+    }
+
+    /**
+     * Test get() method
+     */
+    public void testGet() {
+
+        // valid property name
+        assertEquals("decoratedMap valid", stringVal, decoratedMap.get(stringProp.getName()));
+
+        // invalid property name
+        try {
+            decoratedMap.get("xyz");
+            fail("decoratedMap invalid");
+        } catch(IllegalArgumentException ignore) {
+            // expected result
+        }
+    }
+
+    /**
+     * Test isEmpty() method
+     */
+    public void testIsEmpty() {
+        assertTrue("Empty",      emptyMap.isEmpty());
+        assertFalse("Not Empty", decoratedMap.isEmpty());
+    }
+
+    /**
+     * Test keySet() method
+     */
+    public void testKeySet() {
+        Set set = modifiableMap.keySet();
+
+        // Check the Set can't be modified
+        checkUnmodifiable("keySet()", set);
+
+        assertEquals("keySet size", properties.length, set.size());
+
+        // Set should be ordered in same sequence as properties
+        Iterator iterator = set.iterator();
+        int i = 0;
+        while (iterator.hasNext()) {
+            String expectName  = properties[i].getName();
+            assertEquals("keySet("+i+") key", expectName,  iterator.next());
+            i++;
+        }
+    }
+
+    /**
+     * Test put() method
+     */
+    public void testPut() {
+
+        String newValue = "ABC";
+
+        // Test read only
+        try {
+            decoratedMap.put(stringProp.getName(), newValue);
+            fail("Not read only");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Test Writable
+        assertEquals("modifiableMap put", stringVal, modifiableMap.put(stringProp.getName(), newValue));
+        assertEquals("dynaBean get", newValue, dynaBean.get(stringProp.getName()));
+        assertEquals("modifiableMap get", newValue, modifiableMap.get(stringProp.getName()));
+    }
+
+    /**
+     * Test putAll() method
+     */
+    public void testPutAll() {
+
+        String newValue = "ABC";
+        Map newMap = new HashMap();
+        newMap.put(stringProp.getName(), newValue);
+
+        // Test read only
+        try {
+            decoratedMap.putAll(newMap);
+            fail("Not read only");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Test Writable
+        assertEquals("before putAll", stringVal, dynaBean.get(stringProp.getName()));
+        modifiableMap.putAll(newMap);
+        assertEquals("after putAll",  newValue,  dynaBean.get(stringProp.getName()));
+    }
+
+    /**
+     * Test remove() method
+     */
+    public void testRemove() {
+        try {
+            decoratedMap.remove(stringProp.getName());
+            fail("decoratedMap.remove()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+        try {
+            modifiableMap.remove(stringProp.getName());
+            fail("modifiableMap.remove()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+    }
+
+    /**
+     * Test size() method
+     */
+    public void testSize() {
+        assertEquals("Empty", 0, emptyMap.size());
+        assertEquals("Not Empty", properties.length, decoratedMap.size());
+    }
+
+    /**
+     * Test values() method
+     */
+    public void testValues() {
+        Collection collection = modifiableMap.values();
+
+        // Check the Collection can't be modified
+        checkUnmodifiable("values()", collection);
+
+        assertEquals("values size", values.length, collection.size());
+
+        // Collection should be ordered in same sequence as properties
+        Iterator iterator = collection.iterator();
+        int i = 0;
+        while (iterator.hasNext()) {
+            assertEquals("values("+i+")", values[i], iterator.next());
+            i++;
+        }
+    }
+
+    /**
+     * Check that a Collection is not modifiable
+     */
+    private void checkUnmodifiable(String desc, Collection collection) {
+        String testVal = "xyz";
+
+        // Check can't add()
+        try {
+            collection.add(testVal);
+            fail(desc + ".add()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Check can't addAll()
+        List list = new ArrayList(1);
+        list.add(testVal);
+        try {
+            collection.addAll(list);
+            fail(desc + ".addAll()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Check can't clear()
+        try {
+            collection.clear();
+            fail(desc + ".clear()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Check can't remove()
+        try {
+            collection.remove("abc");
+            fail(desc + ".remove()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Check can't removeAll()
+        try {
+            collection.removeAll(list);
+            fail(desc + ".removeAll()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+
+        // Check can't retainAll()
+        try {
+            collection.retainAll(list);
+            fail(desc + ".retainAll()");
+        } catch(UnsupportedOperationException ignore) {
+            // expected result
+        }
+    }
+}
\ No newline at end of file

Propchange: jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/DynaBeanMapDecoratorTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



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