Author: tn
Date: Mon Jan 12 15:21:18 2015
New Revision: 1651115
URL: http://svn.apache.org/r1651115
Log:
[COLLECTIONS-543] AbstractCollectionDecorator does not forward equals and
hashCode anymore to the backing collection.
Modified:
commons/proper/collections/trunk/src/changes/changes.xml
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/AbstractBagDecorator.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/PredicatedBag.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/SynchronizedBag.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/TransformedBag.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/AbstractListDecorator.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/PredicatedList.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/TransformedList.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/queue/AbstractQueueDecorator.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/AbstractSetDecorator.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/PredicatedSet.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/TransformedSet.java
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
Modified: commons/proper/collections/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/changes/changes.xml?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/changes/changes.xml (original)
+++ commons/proper/collections/trunk/src/changes/changes.xml Mon Jan 12
15:21:18 2015
@@ -22,6 +22,9 @@
<body>
<release version="4.1" date="TBD" description="">
+ <action issue="COLLECTIONS-543" dev="tn" type="fix">
+ "AbstractCollectionDecorator" doesn't forward equals and hashCode
anymore.
+ </action>
<action issue="COLLECTIONS-544" dev="tn" type="fix" due-to="Oswaldo Olivo">
Documented runtime complexity of "CollectionUtils#retainAll(Collection,
Collection).
</action>
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/AbstractBagDecorator.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/AbstractBagDecorator.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/AbstractBagDecorator.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/AbstractBagDecorator.java
Mon Jan 12 15:21:18 2015
@@ -63,6 +63,16 @@ public abstract class AbstractBagDecorat
return (Bag<E>) super.decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
//-----------------------------------------------------------------------
public int getCount(final Object object) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/PredicatedBag.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/PredicatedBag.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/PredicatedBag.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/PredicatedBag.java
Mon Jan 12 15:21:18 2015
@@ -87,6 +87,16 @@ public class PredicatedBag<E> extends Pr
return (Bag<E>) super.decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
//-----------------------------------------------------------------------
public boolean add(final E object, final int count) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/SynchronizedBag.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/SynchronizedBag.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/SynchronizedBag.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/SynchronizedBag.java
Mon Jan 12 15:21:18 2015
@@ -82,6 +82,23 @@ public class SynchronizedBag<E> extends
return (Bag<E>) decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ if (object == this) {
+ return true;
+ }
+ synchronized (lock) {
+ return getBag().equals(object);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ synchronized (lock) {
+ return getBag().hashCode();
+ }
+ }
+
//-----------------------------------------------------------------------
public boolean add(final E object, final int count) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/TransformedBag.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/TransformedBag.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/TransformedBag.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bag/TransformedBag.java
Mon Jan 12 15:21:18 2015
@@ -18,10 +18,10 @@ package org.apache.commons.collections4.
import java.util.Set;
-import org.apache.commons.collections4.set.TransformedSet;
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.collection.TransformedCollection;
+import org.apache.commons.collections4.set.TransformedSet;
/**
* Decorates another {@link Bag} to transform objects that are added.
@@ -110,6 +110,16 @@ public class TransformedBag<E> extends T
return (Bag<E>) decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
//-----------------------------------------------------------------------
public int getCount(final Object object) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
Mon Jan 12 15:21:18 2015
@@ -343,6 +343,16 @@ public abstract class AbstractDualBidiMa
}
@Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
+ @Override
public boolean removeAll(final Collection<?> coll) {
if (parent.isEmpty() || coll.isEmpty()) {
return false;
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
Mon Jan 12 15:21:18 2015
@@ -34,6 +34,19 @@ import java.util.Iterator;
* {@link #iterator()}. Instead it simply returns the value from the
* wrapped collection. This may be undesirable, for example if you are trying
* to write an unmodifiable implementation it might provide a loophole.
+ * <p>
+ * This implementation does not forward the hashCode and equals methods through
+ * to the backing object, but relies on Object's implementation. This is
necessary
+ * to preserve the symmetry of equals. Custom definitions of equality are
usually
+ * based on an interface, such as Set or List, so that the implementation of
equals
+ * can cast the object being tested for equality to the custom interface.
+ * AbstractCollectionDecorator does not implement such custom interfaces
directly;
+ * they are implemented only in subclasses. Therefore, forwarding equals would
break
+ * symmetry, as the forwarding object might consider itself equal to the
object being
+ * tested, but the reverse could not be true. This behavior is consistent with
the
+ * JDK's collection wrappers, such as {@link
java.util.Collections#unmodifiableCollection(Collection)}.
+ * Use an interface-specific subclass of AbstractCollectionDecorator, such as
+ * AbstractListDecorator, to preserve equality behavior, or override equals
directly.
*
* @param <E> the type of the elements in the collection
* @since 3.0
@@ -145,16 +158,6 @@ public abstract class AbstractCollection
}
@Override
- public boolean equals(final Object object) {
- return object == this || decorated().equals(object);
- }
-
- @Override
- public int hashCode() {
- return decorated().hashCode();
- }
-
- @Override
public String toString() {
return decorated().toString();
}
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/AbstractListDecorator.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/AbstractListDecorator.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/AbstractListDecorator.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/AbstractListDecorator.java
Mon Jan 12 15:21:18 2015
@@ -65,6 +65,16 @@ public abstract class AbstractListDecora
return (List<E>) super.decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
//-----------------------------------------------------------------------
public void add(final int index, final E object) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/PredicatedList.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/PredicatedList.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/PredicatedList.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/PredicatedList.java
Mon Jan 12 15:21:18 2015
@@ -94,6 +94,16 @@ public class PredicatedList<E> extends P
return (List<E>) super.decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
//-----------------------------------------------------------------------
public E get(final int index) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/TransformedList.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/TransformedList.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/TransformedList.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/list/TransformedList.java
Mon Jan 12 15:21:18 2015
@@ -114,6 +114,16 @@ public class TransformedList<E> extends
return (List<E>) decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
//-----------------------------------------------------------------------
public E get(final int index) {
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/queue/AbstractQueueDecorator.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/queue/AbstractQueueDecorator.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/queue/AbstractQueueDecorator.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/queue/AbstractQueueDecorator.java
Mon Jan 12 15:21:18 2015
@@ -24,6 +24,12 @@ import org.apache.commons.collections4.c
* Decorates another {@link Queue} to provide additional behaviour.
* <p>
* Methods are forwarded directly to the decorated queue.
+ * <p>
+ * This implementation does not forward the hashCode and equals methods through
+ * to the backing object, but relies on Object's implementation. This is
+ * necessary as some Queue implementations, e.g. LinkedList, have custom a
+ * equals implementation for which symmetry can not be preserved.
+ * See class javadoc of AbstractCollectionDecorator for more information.
*
* @param <E> the type of the elements in the queue
* @since 4.0
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/AbstractSetDecorator.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/AbstractSetDecorator.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/AbstractSetDecorator.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/AbstractSetDecorator.java
Mon Jan 12 15:21:18 2015
@@ -63,4 +63,14 @@ public abstract class AbstractSetDecorat
return (Set<E>) super.decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
}
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/PredicatedSet.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/PredicatedSet.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/PredicatedSet.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/PredicatedSet.java
Mon Jan 12 15:21:18 2015
@@ -86,4 +86,14 @@ public class PredicatedSet<E> extends Pr
return (Set<E>) super.decorated();
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
}
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/TransformedSet.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/TransformedSet.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/TransformedSet.java
(original)
+++
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/set/TransformedSet.java
Mon Jan 12 15:21:18 2015
@@ -101,4 +101,14 @@ public class TransformedSet<E> extends T
super(set, transformer);
}
+ @Override
+ public boolean equals(final Object object) {
+ return object == this || decorated().equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decorated().hashCode();
+ }
+
}
Modified:
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java?rev=1651115&r1=1651114&r2=1651115&view=diff
==============================================================================
---
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
(original)
+++
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
Mon Jan 12 15:21:18 2015
@@ -29,6 +29,7 @@ import java.util.Set;
import org.apache.commons.collections4.AbstractObjectTest;
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.BulkTest;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapIterator;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.collections4.bag.AbstractBagTest;
@@ -754,7 +755,7 @@ public abstract class AbstractMultiValue
(MultiValuedMap<?, ?>)
readExternalFormFromDisk(getCanonicalFullCollectionName(map));
assertEquals("Map is the right size", map.size(), map2.size());
for (final Object key : map.keySet()) {
- assertEquals("Map had inequal elements", map.get(key),
map2.get(key));
+ assertTrue("Map had inequal elements",
CollectionUtils.isEqualCollection(map.get(key), map2.get(key)));
if (isRemoveSupported()) {
map2.remove(key);
}
@@ -1071,10 +1072,12 @@ public abstract class AbstractMultiValue
return AbstractMultiValuedMapTest.this.makeObject().asMap();
}
+ @Override
public Map<K, Collection<V>> makeFullMap() {
return AbstractMultiValuedMapTest.this.makeFullMap().asMap();
}
+ @Override
@SuppressWarnings("unchecked")
public K[] getSampleKeys() {
K[] samplekeys = AbstractMultiValuedMapTest.this.getSampleKeys();
@@ -1085,6 +1088,7 @@ public abstract class AbstractMultiValue
return (K[]) finalKeys;
}
+ @Override
@SuppressWarnings("unchecked")
public Collection<V>[] getSampleValues() {
V[] sampleValues =
AbstractMultiValuedMapTest.this.getSampleValues();
@@ -1095,6 +1099,7 @@ public abstract class AbstractMultiValue
return colArr;
}
+ @Override
@SuppressWarnings("unchecked")
public Collection<V>[] getNewSampleValues() {
Object[] sampleValues = { "ein", "ek", "zwei", "duey", "drei",
"teen" };