Fix for broken contract for GroupNode node comparator.

This comparator's general contract is broken for the case where both
node1 and node2 have negative source indexes. In that case the returned
results are:
- (node1, node2) => -1
- (node2, node1) => -1
which is not symmetric, as is expected by the Comparator interface.

This is noticed by the TimSort implementation when sorting:
12:59:34.108 SEVERE: [38] util.UtilActivator.uncaughtException().108 An uncaught exception occurred in thread=Thread[AWT-EventQueue-0,6,main] and message was: Comparison method violates its general contract!  java.lang.IllegalArgumentException: Comparison method violates its general contract!
	at java.util.TimSort.mergeHi(TimSort.java:868)
	at java.util.TimSort.mergeAt(TimSort.java:485)
	at java.util.TimSort.mergeCollapse(TimSort.java:410)
	at java.util.TimSort.sort(TimSort.java:214)
	at java.util.TimSort.sort(TimSort.java:173)
	at java.util.Arrays.sort(Arrays.java:659)
	at java.util.Collections.sort(Collections.java:217)
	at net.java.sip.communicator.impl.gui.main.contactlist.GroupNode$1.run(GroupNode.java:323)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:694)
	at java.awt.EventQueue$3.run(EventQueue.java:692)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

This proposition tries to distinguish between two nodes by comparing
their hashCode value. This is kind of a work around, however, since this
is already a special case it should not matter that much. Since the
hashCode is a comparable value we can ensure that we make a consistent,
symmetric choice every time. Thus enforcing the contract.
fix-message-formatting
Danny van Heumen 11 years ago
parent 9bc82801d0
commit 413f55e419

@ -439,6 +439,21 @@ public int compare(ContactListNode node1, ContactListNode node2)
int index1 = node1.getSourceIndex();
int index2 = node2.getSourceIndex();
// If both indexes are unknown.
if (index1 < 0 && index2 < 0)
{
// To ensure correct behaviour under the Comparator's general
// contract, we still need to return consistent (symmetric)
// choices even in the case where both nodes have negative
// source index.
final int hash1 = node1.hashCode();
final int hash2 = node2.hashCode();
if (hash1 < hash2)
return -1;
if (hash2 < hash1)
return 1;
return 0;
}
// If the first index is unknown then we position it at the end.
if (index1 < 0)
return 1;

Loading…
Cancel
Save