From dce4319552e773fb98e794d09c23e8e6bfc0cfb9 Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Wed, 31 Mar 2004 23:18:56 +0000 Subject: [PATCH] Make Flat3Map serializable bug 27946 Add clone() to Flat3Map git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131617 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE-NOTES.html | 6 +- .../Flat3Map.emptyCollection.version3.1.obj | Bin 0 -> 71 bytes .../Flat3Map.fullCollection.version3.1.obj | Bin 0 -> 322 bytes .../commons/collections/map/Flat3Map.java | 91 ++++++++-- .../commons/collections/map/TestFlat3Map.java | 156 +++++++++++++++++- 5 files changed, 235 insertions(+), 18 deletions(-) create mode 100644 data/test/Flat3Map.emptyCollection.version3.1.obj create mode 100644 data/test/Flat3Map.fullCollection.version3.1.obj diff --git a/RELEASE-NOTES.html b/RELEASE-NOTES.html index f10ca05e1..557dc6290 100644 --- a/RELEASE-NOTES.html +++ b/RELEASE-NOTES.html @@ -30,12 +30,14 @@ No interface changes, or deprecations have occurred.

ENHANCEMENTS

BUG FIXES

diff --git a/data/test/Flat3Map.emptyCollection.version3.1.obj b/data/test/Flat3Map.emptyCollection.version3.1.obj new file mode 100644 index 0000000000000000000000000000000000000000..2f30ffa204ebbe7d10eb2d73d85f4df9c0eb907c GIT binary patch literal 71 zcmZ4UmVvdnh(SBQC|xhHATc>3RWCU|H#a}87)a;jq$ZbSg4nr<1$u5di6zFqi3N)p VzSKP|Y?;B#z)(?8&cXl$6#%`E8BqWL literal 0 HcmV?d00001 diff --git a/data/test/Flat3Map.fullCollection.version3.1.obj b/data/test/Flat3Map.fullCollection.version3.1.obj new file mode 100644 index 0000000000000000000000000000000000000000..3e3665812d43a49a2ba6419c6aef19d3cb3a511d GIT binary patch literal 322 zcmXX>F>=B{4AhLzByI8u3T9l8KcveeWal_D$mp;SgHurD5%jctiU-i;0a+b1yOMTS zce>uG9C})4A1aRAw7zPz>vTJSMSPRiR(Bk$PvP|O#qmOar`zuLTo4`O!4c7WqGF|* z$N|Sh<-yNI63sGWPz>Hf1zJ<{4;r9ZTQ7p-Eb~L{v)Y@=f!AB8nK5u1KP@pIS@ziY z5>&tI3DxVfvJLP=(4>0=fR?L;TjY$)67qk5)}#)02Sif_Ts`5%%$5u~SklPMY==4E K7g& literal 0 HcmV?d00001 diff --git a/src/java/org/apache/commons/collections/map/Flat3Map.java b/src/java/org/apache/commons/collections/map/Flat3Map.java index 3e3b55696..6936d37dc 100644 --- a/src/java/org/apache/commons/collections/map/Flat3Map.java +++ b/src/java/org/apache/commons/collections/map/Flat3Map.java @@ -15,6 +15,10 @@ */ package org.apache.commons.collections.map; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.AbstractCollection; import java.util.AbstractSet; import java.util.Collection; @@ -56,34 +60,37 @@ import org.apache.commons.collections.ResettableIterator; * Do not use Flat3Map if the size is likely to grow beyond 3. * * @since Commons Collections 3.0 - * @version $Revision: 1.13 $ $Date: 2004/02/18 01:13:19 $ + * @version $Revision: 1.14 $ $Date: 2004/03/31 23:18:56 $ * * @author Stephen Colebourne */ -public class Flat3Map implements IterableMap { +public class Flat3Map implements IterableMap, Serializable, Cloneable { + + /** Serialization version */ + private static final long serialVersionUID = -6701087419741928296L; /** The size of the map, used while in flat mode */ - private int size; + private transient int size; /** Hash, used while in flat mode */ - private int hash1; + private transient int hash1; /** Hash, used while in flat mode */ - private int hash2; + private transient int hash2; /** Hash, used while in flat mode */ - private int hash3; + private transient int hash3; /** Key, used while in flat mode */ - private Object key1; + private transient Object key1; /** Key, used while in flat mode */ - private Object key2; + private transient Object key2; /** Key, used while in flat mode */ - private Object key3; + private transient Object key3; /** Value, used while in flat mode */ - private Object value1; + private transient Object value1; /** Value, used while in flat mode */ - private Object value2; + private transient Object value2; /** Value, used while in flat mode */ - private Object value3; + private transient Object value3; /** Map, used while in delegate mode */ - private HashedMap delegateMap; + private transient HashedMap delegateMap; /** * Constructor. @@ -344,7 +351,7 @@ public class Flat3Map implements IterableMap { * Converts the flat map data to a HashMap. */ private void convertToMap() { - delegateMap = new HashedMap(); + delegateMap = createDelegateMap(); switch (size) { // drop through case 3: delegateMap.put(key3, value3); @@ -360,6 +367,16 @@ public class Flat3Map implements IterableMap { value1 = value2 = value3 = null; } + /** + * Create an instance of the map used for storage when in delegation mode. + * This can be overridden by subclasses. + * + * @return a new HashedMap or subclass + */ + protected HashedMap createDelegateMap() { + return new HashedMap(); + } + /** * Removes the specified mapping from this map. * @@ -945,8 +962,52 @@ public class Flat3Map implements IterableMap { return getValue(); } } - + //----------------------------------------------------------------------- + /** + * Write the map out using a custom routine. + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(size()); + for (MapIterator it = mapIterator(); it.hasNext();) { + out.writeObject(it.next()); // key + out.writeObject(it.getValue()); // value + } + } + + /** + * Read the map in using a custom routine. + */ + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + int count = in.readInt(); + if (count > 3) { + delegateMap = createDelegateMap(); + } + for (int i = count; i > 0; i--) { + put(in.readObject(), in.readObject()); + } + } + + //----------------------------------------------------------------------- + /** + * Clones the map without cloning the keys or values. + * + * @return a shallow clone + */ + public Object clone() { + try { + Flat3Map cloned = (Flat3Map) super.clone(); + if (cloned.delegateMap != null) { + cloned.delegateMap = (HashedMap) cloned.delegateMap.clone(); + } + return cloned; + } catch (CloneNotSupportedException ex) { + throw new InternalError(); + } + } + /** * Compares this map with another. * diff --git a/src/test/org/apache/commons/collections/map/TestFlat3Map.java b/src/test/org/apache/commons/collections/map/TestFlat3Map.java index dd8405090..33ae859ad 100644 --- a/src/test/org/apache/commons/collections/map/TestFlat3Map.java +++ b/src/test/org/apache/commons/collections/map/TestFlat3Map.java @@ -15,6 +15,10 @@ */ package org.apache.commons.collections.map; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Map; import junit.framework.Test; @@ -27,12 +31,17 @@ import org.apache.commons.collections.iterators.AbstractTestMapIterator; /** * JUnit tests. * - * @version $Revision: 1.6 $ $Date: 2004/02/18 01:20:37 $ + * @version $Revision: 1.7 $ $Date: 2004/03/31 23:18:56 $ * * @author Stephen Colebourne */ public class TestFlat3Map extends AbstractTestIterableMap { + private static final Integer ONE = new Integer(1); + private static final Integer TWO = new Integer(2); + private static final String TEN = "10"; + private static final String TWENTY = "20"; + public TestFlat3Map(String testName) { super(testName); } @@ -49,6 +58,136 @@ public class TestFlat3Map extends AbstractTestIterableMap { return new Flat3Map(); } + //----------------------------------------------------------------------- + public void testClone2() { + Flat3Map map = new Flat3Map(); + assertEquals(0, map.size()); + map.put(ONE, TEN); + map.put(TWO, TWENTY); + assertEquals(2, map.size()); + assertEquals(true, map.containsKey(ONE)); + assertEquals(true, map.containsKey(TWO)); + assertSame(TEN, map.get(ONE)); + assertSame(TWENTY, map.get(TWO)); + + // clone works (size = 2) + Flat3Map cloned = (Flat3Map) map.clone(); + assertEquals(2, cloned.size()); + assertEquals(true, cloned.containsKey(ONE)); + assertEquals(true, cloned.containsKey(TWO)); + assertSame(TEN, cloned.get(ONE)); + assertSame(TWENTY, cloned.get(TWO)); + + // change original doesn't change clone + map.put(TEN, ONE); + map.put(TWENTY, TWO); + assertEquals(4, map.size()); + assertEquals(2, cloned.size()); + assertEquals(true, cloned.containsKey(ONE)); + assertEquals(true, cloned.containsKey(TWO)); + assertSame(TEN, cloned.get(ONE)); + assertSame(TWENTY, cloned.get(TWO)); + } + public void testClone4() { + Flat3Map map = new Flat3Map(); + assertEquals(0, map.size()); + map.put(ONE, TEN); + map.put(TWO, TWENTY); + map.put(TEN, ONE); + map.put(TWENTY, TWO); + + // clone works (size = 4) + Flat3Map cloned = (Flat3Map) map.clone(); + assertEquals(4, map.size()); + assertEquals(4, cloned.size()); + assertEquals(true, cloned.containsKey(ONE)); + assertEquals(true, cloned.containsKey(TWO)); + assertEquals(true, cloned.containsKey(TEN)); + assertEquals(true, cloned.containsKey(TWENTY)); + assertSame(TEN, cloned.get(ONE)); + assertSame(TWENTY, cloned.get(TWO)); + assertSame(ONE, cloned.get(TEN)); + assertSame(TWO, cloned.get(TWENTY)); + + // change original doesn't change clone + map.clear(); + assertEquals(0, map.size()); + assertEquals(4, cloned.size()); + assertEquals(true, cloned.containsKey(ONE)); + assertEquals(true, cloned.containsKey(TWO)); + assertEquals(true, cloned.containsKey(TEN)); + assertEquals(true, cloned.containsKey(TWENTY)); + assertSame(TEN, cloned.get(ONE)); + assertSame(TWENTY, cloned.get(TWO)); + assertSame(ONE, cloned.get(TEN)); + assertSame(TWO, cloned.get(TWENTY)); + } + + public void testSerialisation0() throws Exception { + Flat3Map map = new Flat3Map(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bout); + out.writeObject(map); + byte[] bytes = bout.toByteArray(); + out.close(); + ByteArrayInputStream bin = new ByteArrayInputStream(bytes); + ObjectInputStream in = new ObjectInputStream(bin); + Flat3Map ser = (Flat3Map) in.readObject(); + in.close(); + assertEquals(0, map.size()); + assertEquals(0, ser.size()); + } + + public void testSerialisation2() throws Exception { + Flat3Map map = new Flat3Map(); + map.put(ONE, TEN); + map.put(TWO, TWENTY); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bout); + out.writeObject(map); + byte[] bytes = bout.toByteArray(); + out.close(); + ByteArrayInputStream bin = new ByteArrayInputStream(bytes); + ObjectInputStream in = new ObjectInputStream(bin); + Flat3Map ser = (Flat3Map) in.readObject(); + in.close(); + assertEquals(2, map.size()); + assertEquals(2, ser.size()); + assertEquals(true, ser.containsKey(ONE)); + assertEquals(true, ser.containsKey(TWO)); + assertEquals(TEN, ser.get(ONE)); + assertEquals(TWENTY, ser.get(TWO)); + } + + public void testSerialisation4() throws Exception { + Flat3Map map = new Flat3Map(); + map.put(ONE, TEN); + map.put(TWO, TWENTY); + map.put(TEN, ONE); + map.put(TWENTY, TWO); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bout); + out.writeObject(map); + byte[] bytes = bout.toByteArray(); + out.close(); + ByteArrayInputStream bin = new ByteArrayInputStream(bytes); + ObjectInputStream in = new ObjectInputStream(bin); + Flat3Map ser = (Flat3Map) in.readObject(); + in.close(); + assertEquals(4, map.size()); + assertEquals(4, ser.size()); + assertEquals(true, ser.containsKey(ONE)); + assertEquals(true, ser.containsKey(TWO)); + assertEquals(true, ser.containsKey(TEN)); + assertEquals(true, ser.containsKey(TWENTY)); + assertEquals(TEN, ser.get(ONE)); + assertEquals(TWENTY, ser.get(TWO)); + assertEquals(ONE, ser.get(TEN)); + assertEquals(TWO, ser.get(TWENTY)); + } + //----------------------------------------------------------------------- public BulkTest bulkTestMapIterator() { return new TestFlatMapIterator(); @@ -96,4 +235,19 @@ public class TestFlat3Map extends AbstractTestIterableMap { TestFlat3Map.this.verify(); } } + + public String getCompatibilityVersion() { + return "3.1"; + } + +// public void testCreate() throws Exception { +// resetEmpty(); +// writeExternalFormToDisk( +// (java.io.Serializable) map, +// "D:/dev/collections/data/test/Flat3Map.emptyCollection.version3.1.obj"); +// resetFull(); +// writeExternalFormToDisk( +// (java.io.Serializable) map, +// "D:/dev/collections/data/test/Flat3Map.fullCollection.version3.1.obj"); +// } }