You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ma...@apache.org on 2002/03/13 05:36:18 UTC
cvs commit: jakarta-commons/collections/src/test/org/apache/commons/collections TestBeanMap.java
mas 02/03/12 20:36:18
Modified: collections/src/java/org/apache/commons/collections
BeanMap.java
collections/src/test/org/apache/commons/collections
TestBeanMap.java
Log:
Fixed bugs where methods failed when there is no bean set for the bean map.
Fixed entrySet() to return a set containing Map.Entry objects with readable
properties as keys. This fixes the test case error, and a couple of the test
case failures (and uncovers a couple more test case failures)
Fixed clone method to allow subclasses to clone properly. This requires a
non-backwards compatible change where the clone method now declares it throws
CloneNotSupportedException. See:
http://www.javaworld.com/javaworld/jw-01-1999/jw-01-object.html Seeing how
BeanMap never directly implemented Cloneable anyway, and this is for a major
revision, I don't see this changing being much of a problem.
Since clone() declares it throws CloneNotSupportedException, that exception is
now used to indicate a problem when attempting to clone (rather than
UnsupportedOperationException, or other RuntimeException).
Added a small test for testing BeanMap clone.
Revision Changes Path
1.6 +108 -17 jakarta-commons/collections/src/java/org/apache/commons/collections/BeanMap.java
Index: BeanMap.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/BeanMap.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- BeanMap.java 13 Mar 2002 04:15:49 -0000 1.5
+++ BeanMap.java 13 Mar 2002 04:36:18 -0000 1.6
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/BeanMap.java,v 1.5 2002/03/13 04:15:49 mas Exp $
- * $Revision: 1.5 $
- * $Date: 2002/03/13 04:15:49 $
+ * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/BeanMap.java,v 1.6 2002/03/13 04:36:18 mas Exp $
+ * $Revision: 1.6 $
+ * $Date: 2002/03/13 04:36:18 $
*
* ====================================================================
*
@@ -68,8 +68,10 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractMap;
+import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -85,13 +87,13 @@
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
*/
-public class BeanMap extends AbstractMap {
+public class BeanMap extends AbstractMap implements Cloneable {
- private Object bean;
+ private transient Object bean;
- private HashMap readMethods = new HashMap();
- private HashMap writeMethods = new HashMap();
- private HashMap types = new HashMap();
+ private transient HashMap readMethods = new HashMap();
+ private transient HashMap writeMethods = new HashMap();
+ private transient HashMap types = new HashMap();
public static final Object[] NULL_ARGUMENTS = {};
public static HashMap defaultTransformers = new HashMap();
@@ -177,18 +179,77 @@
// Map interface
//-------------------------------------------------------------------------
- public Object clone() {
+ /**
+ * Clone this bean map using the following process:
+ *
+ * <ul>
+
+ * <li>If there is no underlying bean, return a cloned BeanMap without a
+ * bean.
+ *
+ * <li>Since there is an underlying bean, try to instantiate a new bean of
+ * the same type using Class.newInstance().
+ *
+ * <li>If the instantiation fails, throw a CloneNotSupportedException
+ *
+ * <li>Clone the bean map and set the newly instantiated bean as the
+ * underyling bean for the bean map.
+ *
+ * <li>Copy each property that is both readable and writable from the
+ * existing object to a cloned bean map.
+ *
+ * <li>If anything fails along the way, throw a
+ * CloneNotSupportedException.
+ *
+ * <ul>
+ **/
+ public Object clone() throws CloneNotSupportedException {
+ BeanMap newMap = (BeanMap)super.clone();
+
+ if(bean == null) {
+ // no bean, just an empty bean map at the moment. return a newly
+ // cloned and empty bean map.
+ return newMap;
+ }
+
+ Object newBean = null;
Class beanClass = null;
try {
beanClass = bean.getClass();
- Object newBean = beanClass.newInstance();
- Map newMap = new BeanMap( newBean );
- newMap.putAll( this );
- return newMap;
- }
- catch (Exception e) {
- throw new UnsupportedOperationException( "Could not create new instance of class: " + beanClass );
+ newBean = beanClass.newInstance();
+ } catch (Exception e) {
+ // unable to instantiate
+ throw new CloneNotSupportedException
+ ("Unable to instantiate the underlying bean \"" +
+ beanClass.getName() + "\": " + e);
+ }
+
+ try {
+ newMap.setBean(newBean);
+ } catch (Exception exception) {
+ throw new CloneNotSupportedException
+ ("Unable to set bean in the cloned bean map: " +
+ exception);
+ }
+
+ try {
+ // copy only properties that are readable and writable. If its
+ // not readable, we can't get the value from the old map. If
+ // its not writable, we can't write a value into the new map.
+ Iterator readableKeys = readMethods.keySet().iterator();
+ while(readableKeys.hasNext()) {
+ Object key = readableKeys.next();
+ if(getWriteMethod(key) != null) {
+ newMap.put(key, get(key));
+ }
+ }
+ } catch (Exception exception) {
+ throw new CloneNotSupportedException
+ ("Unable to copy bean values to cloned bean map: " +
+ exception);
}
+
+ return newMap;
}
/**
@@ -200,6 +261,8 @@
* BeanMap are fixed).
**/
public void clear() {
+ if(bean == null) return;
+
Class beanClass = null;
try {
beanClass = bean.getClass();
@@ -281,7 +344,33 @@
}
public Set entrySet() {
- return readMethods.keySet();
+ return Collections.unmodifiableSet(new AbstractSet() {
+ public Iterator iterator() {
+ return new Iterator() {
+
+ Iterator methodIter =
+ BeanMap.this.readMethods.keySet().iterator();
+
+ public boolean hasNext() {
+ return methodIter.hasNext();
+ }
+
+ public Object next() {
+ Object key = (Object)methodIter.next();
+ return new DefaultMapEntry(key, get(key));
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException
+ ("remove() not supported from BeanMap.entrySet()");
+ }
+ };
+ }
+
+ public int size() {
+ return BeanMap.this.readMethods.size();
+ }
+ });
}
public Collection values() {
@@ -369,6 +458,8 @@
}
private void initialise() {
+ if(getBean() == null) return;
+
Class beanClass = getBean().getClass();
try {
//BeanInfo beanInfo = Introspector.getBeanInfo( bean, null );
1.4 +21 -3 jakarta-commons/collections/src/test/org/apache/commons/collections/TestBeanMap.java
Index: TestBeanMap.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/TestBeanMap.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TestBeanMap.java 22 Feb 2002 07:00:30 -0000 1.3
+++ TestBeanMap.java 13 Mar 2002 04:36:18 -0000 1.4
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/TestBeanMap.java,v 1.3 2002/02/22 07:00:30 mas Exp $
- * $Revision: 1.3 $
- * $Date: 2002/02/22 07:00:30 $
+ * $Header: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/TestBeanMap.java,v 1.4 2002/03/13 04:36:18 mas Exp $
+ * $Revision: 1.4 $
+ * $Date: 2002/03/13 04:36:18 $
*
* ====================================================================
*
@@ -278,5 +278,23 @@
public void testClear() {
//TODO: make sure a call to BeanMap.clear returns the bean to its
//default initialization values.
+ }
+
+ public void testBeanMapClone() {
+ BeanMap map = (BeanMap)makeFullMap();
+ try {
+ BeanMap map2 = (BeanMap)((BeanMap)map).clone();
+
+ // make sure containsKey is working to verify the bean was cloned
+ // ok, and the read methods were properly initialized
+ Object[] keys = getSampleKeys();
+ for(int i = 0; i < keys.length; i++) {
+ assertTrue("Cloned BeanMap should contain the same keys",
+ map2.containsKey(keys[i]));
+ }
+ } catch (CloneNotSupportedException exception) {
+ fail("BeanMap.clone() should not throw a " +
+ "CloneNotSupportedException when clone should succeed.");
+ }
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>