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 [EMAIL PROTECTED] DynaBean} to provide <code>Map</code> behaviour.</p> + * + * <p>The motivation for this implementation is to provide access to [EMAIL PROTECTED] DynaBean} + * properties in technologies that are unaware of BeanUtils and [EMAIL PROTECTED] DynaBean}s - + * such as the expression languages of JSTL and JSF.</p> + * + * <p>This can be achieved either by wrapping the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean} simply instantiate this class with the + * target [EMAIL PROTECTED] 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 + * [EMAIL PROTECTED] DynaBean}. + * + * @param dynaBean The dyna bean being decorated + * @throws IllegalArgumentException if the [EMAIL PROTECTED] DynaBean} is null. + */ + public DynaBeanMapDecorator(DynaBean dynaBean) { + this(dynaBean, true); + } + + /** + * Construct a Map for the specified [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean} contains a specified + * value for one (or more) of its properties. + * + * @param key The [EMAIL PROTECTED] DynaBean}'s property name + * @return <code>true</code> if one of the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean} contains + * a specified value. + * + * @param value The value to check for. + * @return <code>true</code> if one of the the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean}. + * + * @param key The [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean} has + * any properties. + * + * @return <code>true</code> if the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean}.</p> + * + * <p><b>N.B.</b>For [EMAIL PROTECTED] DynaBean}s whose associated [EMAIL PROTECTED] DynaClass} + * is a [EMAIL PROTECTED] MutableDynaClass} a new Set is created every + * time, otherwise the Set is created only once and cached.</p> + * + * @return An unmodifiable set of the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean}. + * + * @param key The [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 + * [EMAIL PROTECTED] DynaBean}. + * @return The number of properties. + */ + public int size() { + return getDynaProperties().length; + } + + /** + * Returns the set of property values in the + * decorated [EMAIL PROTECTED] 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 [EMAIL PROTECTED] DynaBean} + * this Map decorates. + * + * @return the decorated [EMAIL PROTECTED] DynaBean}. + */ + protected DynaBean getDynaBean() { + return dynaBean; + } + + // ------------------- private Methods ------------------------------- + + /** + * Convenience method to retrieve the [EMAIL PROTECTED] DynaProperty}s + * for this [EMAIL PROTECTED] DynaClass}. + * + * @return The an array of the [EMAIL PROTECTED] 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]