Null values at end of sorted list
Null values at end of sorted list
- Subject: Null values at end of sorted list
- From: email@hidden
- Date: Thu, 31 Jan 2008 13:34:11 -0500
What happens when you want to sort ten
values in ascending order but one of them is null? Does that void value
get put at the beginning, the middle, or the end?
Apple decided that null values (or keyPaths
that return a null value) should be placed at the beginning of an array
sorted in ascending order. Perhaps they felt that "null is less than
zero".
For us, it seems that null values should
be placed at the end of an ascending sort. More often than not, null values
make more sense to be placed at the end of the list when working in our
Domain.
Has anyone crossed this bridge before?
We've tried our hand at a solution which
is listed at the bottom of this message. It works so long as no commits
have been made to the database! After a commit, from any page in the app,
sorting no longer works as expected and often results in a K2Sort error.
It's baffling.
Our class extends the default sorting
logic of EOSortOrdering.ComparisonSupport (the class that does sorting
globally for WO). We really only want to override "handleNulls()"
but because it is both private and static, we need to redo a few other
methods as well. Functionally, our class is identical but choose to place
null values at the end of the list for an ascending sort.
Here is the line we add to the Appliction's
constructor to get the ball rolling globally:
==========================
EOSortOrdering.ComparisonSupport.setSupportForClass(new
CXNullsAtEndComparisonSupport(), Object.class);
Here is the source code to the custom
ComparisonSupport:
==========================
public class CXNullsAtEndComparisonSupport
extends EOSortOrdering.ComparisonSupport {
public static final Logger
_logger = Logger.getLogger(CXNullsAtEndComparisonSupport.class);
public
CXNullsAtEndComparisonSupport() {}
protected
static final int kNeitherNull = -42;
protected
static int handleNulls(Object left, Object right)
{
if(left == null || left == NSKeyValueCoding.NullValue)
return
right != null && right != NSKeyValueCoding.NullValue ? NSComparator.OrderedDescending
: NSComparator.OrderedSame;
return right != null && right != NSKeyValueCoding.NullValue
? kNeitherNull : NSComparator.OrderedAscending;
}
private
static final NSTimestampFormatter defaultStringTimestampFormatter = new
NSTimestampFormatter("%Y-%m-%d %H:%M:%S %Z");
protected
static NSTimestamp coerceToTimestampClass(Object value)
{
if(value instanceof NSTimestamp)
return
(NSTimestamp)value;
if(value instanceof Date)
return
new NSTimestamp(((Date)value).getTime());
if(value instanceof Number)
return
new NSTimestamp(((Number)value).longValue());
try {
return
(NSTimestamp)defaultStringTimestampFormatter.parseObject((String)value);
} catch (Exception e) {
//fixme:
do something more.
_logger.info("coerceToTimestampClass
failed. Message = " + e.getMessage());
return
null;
}
}
protected
int _genericCompareTo(Object left, Object right)
{
int nullCheck = handleNulls(left, right);
if(nullCheck != kNeitherNull) {
return
nullCheck;
}
Class LHSClass = left.getClass();
if(LHSClass == _NSUtilities._StringClass)
return
left.toString().compareTo(right.toString());
if((left instanceof Number) || LHSClass ==
_NSUtilities._BooleanClass)
return
_NSUtilities.compareNumbersOrBooleans(left, right);
if(left instanceof Date)
{
if(LHSClass
!= NSTimestamp._CLASS)
left = coerceToTimestampClass(left);
right
= coerceToTimestampClass(right);
}
if(left instanceof Comparable)
return
((Comparable)left).compareTo(right);
else
return
left.toString().compareTo(right.toString());
}
protected
int _genericCaseInsensitiveCompareTo(Object left, Object right)
{
int nullCheck = handleNulls(left, right);
if(nullCheck != kNeitherNull)
return
nullCheck;
Class LHSClass = left.getClass();
if(LHSClass == _NSUtilities._StringClass)
return
left.toString().compareToIgnoreCase(right.toString());
if((left instanceof Number) || LHSClass ==
_NSUtilities._BooleanClass)
return
_NSUtilities.compareNumbersOrBooleans(left, right);
if(left instanceof Date)
{
if(LHSClass
!= NSTimestamp._CLASS)
left = coerceToTimestampClass(left);
right
= coerceToTimestampClass(right);
return
((Comparable)left).compareTo(right);
} else
{
return
left.toString().compareToIgnoreCase(right.toString());
}
}
} _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden