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 protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to