Re: Null values at end of sorted list
Re: Null values at end of sorted list
- Subject: Re: Null values at end of sorted list
- From: email@hidden
- Date: Fri, 1 Feb 2008 10:56:35 -0500
Thanks for pondering the question James.
Yes, when I say "commit" I
mean "ec.saveChanges()".
We have a listController that manages
an array of enterprise objects that have been fetched from the database.
"displayedObjects" is just a mutable clone of that array that
is sorted and filtered before being presented to the user.
If I simply uncomment the line for "setSupportForClass()"
then the problem dissappears. There is no issue with commits, etc. So the
problem must be:
1) "CXNullsAtEndComparisonSupport"
has a bug that we just haven't been able to see yet. Perhaps in the way
that it extends Apple's class and the subtleties of polymorphic / non-polymorphic
behavior when static methods are involved.
2) "setSupportForClass()"
is being called incorrectly. Maybe I can't give it "Object.class"
as a parameter for some strange reason. In other words, perhaps sometimes
it uses my support class and other times it uses the default support class
which confuses the K2Sort algorithm and leaves it in an unworkable state.
-- Aaron
James Cicenia <email@hidden> wrote on 31-01-2008
02:48:26 PM:
> Aaron -
>
> I really don't know. I have created my own specific comparators that
> worked... and I don't see anything in your
> ComparisonSupport class that should stop working
upon a commit.
>
> When you say commit do you mean save changes? Are you getting a
> fresh array for displayedObjects?
>
> - James
>
> On Jan 31, 2008, at 1:26 PM, email@hidden wrote:
>
>
> Hi James,
>
> The ComparisonSupport becomes transparent and used universally
> throughout the app. Here's an excerpt of one place where a sort occurs:
>
> NSMutableArray displayedObjects = <the objects to display in a
> paginated list on the screen>
> NSMutableArray sortOrderings = <a list of EOSortOrdering objects
> taking a key and an NSSelector>
> EOSortOrdering.sortArrayUsingKeyOrderArray(displayedObjects, sortOrderings);
>
> This is often called by clicking a little toggle icon to modify the
> "sortOrderings" array with a particular "key"
and either
> "compareAscending" or "compareDescending".
>
> It works like a charm. The null values are placed at the very end
of
> an ascending sort and placed at the beginning of a descending sort.
> It works so long as we haven't done any commits to the database.
> Sounds odd, I know, because I don't fully understand what is
> happening. It probably isn't the commit to the database itself but
> some other nuance. All I know with certainty is that I can move
> around the whole app and happily re-sort columns anywhere but as
> soon as I do a commit I'm no longer able to reliably sort columns
on
> any page. Also, once it gets in this bad state, any new wosessions
I
> start exhibit the same problem immediately.
>
> -- Aaron
>
> James Cicenia <email@hidden> wrote on 31-01-2008 02:01:03
PM:
>
> > What do you mean it no longer works after commits?
> >
> > How are you using your comparator?
> >
> > -James Cicenia
> >
> > On Jan 31, 2008, at 12:34 PM, email@hidden wrote:
> >
> >
> > 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'sbaffling.
> >
> > 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
> _______________________________________________
> 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 _______________________________________________
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