Coverage Report - net.wotonomy.control.EOSortOrdering
 
Classes in this File Line Coverage Branch Coverage Complexity
EOSortOrdering
0% 
0% 
2.55
 
 1  
 /*
 2  
 Wotonomy: OpenStep design patterns for pure Java applications.
 3  
 Copyright (C) 2000 Michael Powers
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, see http://www.gnu.org
 17  
 */
 18  
 
 19  
 package net.wotonomy.control;
 20  
 
 21  
 import java.io.Serializable;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collections;
 24  
 import java.util.Comparator;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 
 28  
 import net.wotonomy.foundation.NSArray;
 29  
 import net.wotonomy.foundation.NSMutableArray;
 30  
 import net.wotonomy.foundation.NSSelector;
 31  
 
 32  
 /**
 33  
 * EOSortOrdering defines a sort key and operation.
 34  
 * DisplayGroups use lists of EOSortOrdering to determine
 35  
 * how to order their items.  
 36  
 *
 37  
 * @author michael@mpowers.net
 38  
 * @author $Author: cgruber $
 39  
 * @version $Revision: 894 $
 40  
 */
 41  0
 public class EOSortOrdering implements Serializable, EOKeyValueArchiving
 42  
 {
 43  
     /**
 44  
     * Sorts items in ascending order.
 45  
     */
 46  
     public static final 
 47  0
         NSSelector CompareAscending = new CompareAscendingComparator();
 48  
         
 49  
     /**
 50  
     * Sorts items in descending order.
 51  
     */
 52  
     public static final 
 53  0
         NSSelector CompareDescending = new CompareDescendingComparator();
 54  
         
 55  
     /**
 56  
     * Sorts items' string representations in ascending order
 57  
     * in a case insensitive manner.
 58  
     */
 59  
     public static final 
 60  0
         NSSelector CompareCaseInsensitiveAscending = 
 61  0
             new CompareCaseInsensitiveAscendingComparator();
 62  
         
 63  
     /**
 64  
     * Sorts items' string representations in descending order
 65  
     * in a case insensitive manner.
 66  
     */
 67  
     public static final 
 68  0
         NSSelector CompareCaseInsensitiveDescending = 
 69  0
             new CompareCaseInsensitiveDescendingComparator();
 70  
     
 71  
     protected String key;
 72  
     protected NSSelector selector;
 73  
     
 74  
     /**
 75  
     * Factory-style constructor returns a new EOSortOrdering instance
 76  
     * with the specified key and selector.  Neither may be null.
 77  
     */
 78  
     public static EOSortOrdering sortOrderingWithKey(String key, NSSelector selector)
 79  
     {
 80  0
         return new EOSortOrdering( key, selector );
 81  
     }
 82  
     
 83  
     /**
 84  
     * Constructor creates an EOSortOrdering that uses the 
 85  
     * specified key and selector.  Neither may be null.
 86  
     */
 87  0
     public EOSortOrdering( String aKey, NSSelector aSelector )
 88  0
     {
 89  0
         key = aKey;
 90  0
         selector = aSelector;
 91  0
     }
 92  
     
 93  
     /**
 94  
     * Constructor creates an EOSortOrdering that uses the 
 95  
     * specified key and comparator.  Neither may be null.
 96  
     * Not in the spec.
 97  
     */
 98  0
     public EOSortOrdering( String aKey, Comparator aComparator )
 99  0
     {
 100  0
         key = aKey;
 101  0
         selector = new NSSelector( aKey, aComparator );
 102  0
     }
 103  
     
 104  
     /**
 105  
     * Returns the property key.
 106  
     */
 107  
     public String key()
 108  
     {
 109  0
         return key;   
 110  
     }
 111  
 
 112  
     /**
 113  
     * Returns the selector.
 114  
     */
 115  
     public NSSelector selector()
 116  
     {
 117  0
         return selector;        
 118  
     }
 119  
     
 120  
     public String toString()
 121  
     {
 122  0
         return "[EOSortOrdering: key='"+key+"' selector='"+selector+"']";
 123  
     }
 124  
     
 125  
     public boolean equals( Object anObject )
 126  
     {
 127  0
         if ( anObject instanceof EOSortOrdering )
 128  
         {
 129  0
             EOSortOrdering x = (EOSortOrdering) anObject;
 130  0
             if ( selector().equals( x.selector() ) )
 131  
             {
 132  0
                 if ( key().equals( x.key() ) )
 133  
                 {
 134  0
                     return true;
 135  
                 }
 136  
             }
 137  
         }
 138  0
         return false;
 139  
     }
 140  
     
 141  
     /**
 142  
     * Sorts the specified list in place according to the specified
 143  
     * list of EOSortOrderings.  The items will be sorted first by the
 144  
     * first ordering, and items with equal values for that property 
 145  
     * will be sorted by the next ordering, and so on.
 146  
     */ 
 147  
     public static void sortArrayUsingKeyOrderArray( 
 148  
         List anObjectList, List aSortOrderingList )
 149  
     {
 150  0
         List keys = new ArrayList( aSortOrderingList );
 151  0
         Collections.reverse( keys );
 152  0
         Iterator it = keys.iterator();
 153  
         EOSortOrdering sortOrdering;
 154  0
         while ( it.hasNext() )
 155  
         {
 156  0
             sortOrdering = (EOSortOrdering) it.next();
 157  0
             Collections.sort( anObjectList, 
 158  0
                 new DelegatingComparator( 
 159  0
                     sortOrdering.key(), sortOrdering.selector() ) );
 160  0
         }
 161  0
     }
 162  
     
 163  
     /**
 164  
     * Sorts the specified list in place according to the specified
 165  
     * list of EOSortOrderings.  The items will be sorted first by the
 166  
     * first ordering, and items with equal values for that property 
 167  
     * will be sorted by the next ordering, and so on.
 168  
     */ 
 169  
     public static NSArray sortedArrayUsingKeyOrderArray( 
 170  
         List anObjectList, List aSortOrderingList )
 171  
     {
 172  0
         NSArray result = new NSMutableArray();
 173  0
         result.addAll( anObjectList );
 174  0
         sortArrayUsingKeyOrderArray( result, aSortOrderingList );
 175  0
         return result;
 176  
     }
 177  
 
 178  
         public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver arch) {
 179  0
                 String k = (String)arch.decodeObjectForKey("key");
 180  0
                 String sname = (String)arch.decodeObjectForKey("selectorName");
 181  0
                 NSSelector sel = null;
 182  0
                 if (sname.equals("compareAscending:"))
 183  0
                         sel = CompareAscending;
 184  0
                 else if (sname.equals("compareDescending:"))
 185  0
                         sel = CompareDescending;
 186  0
                 else if (sname.equals("compareCaseInsensitiveAscending:"))
 187  0
                         sel = CompareCaseInsensitiveAscending;
 188  0
                 else if (sname.equals("compareCaseInsensitiveDescending:"))
 189  0
                         sel = CompareCaseInsensitiveAscending;
 190  
                 else {
 191  0
                         if (sname.endsWith(":"))
 192  0
                                 sname = sname.substring(0, sname.length()-1);
 193  0
                         sel = new NSSelector(sname, new Class[]{ Object.class });
 194  
                 }
 195  0
                 return new EOSortOrdering(k, sel);
 196  
         }
 197  
 
 198  
         public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) {
 199  0
                 arch.encodeObject("EOSortOrdering", "class");
 200  0
                 arch.encodeObject(key(), "key");
 201  0
                 if (selector.equals(CompareAscending))
 202  0
                         arch.encodeObject("compareAscending:", "selectorName");
 203  0
                 else if (selector.equals(CompareDescending))
 204  0
                         arch.encodeObject("compareDescending:", "selectorName");
 205  0
                 else if (selector.equals(CompareCaseInsensitiveAscending))
 206  0
                         arch.encodeObject("compareCaseInsensitiveAscending:", "selectorName");
 207  0
                 else if (selector.equals(CompareCaseInsensitiveAscending))
 208  0
                         arch.encodeObject("compareCaseInsensitiveDescending:", "selectorName");
 209  
                 else
 210  0
                         arch.encodeObject(selector.name() + ":", "selectorName");
 211  0
         }
 212  
 
 213  0
     private static class CompareAscendingComparator
 214  
         extends NSSelector
 215  
     {
 216  
         public int compare(Object o1, Object o2)
 217  
         {
 218  0
             if ( o1 instanceof Comparable ) 
 219  
             {
 220  0
                 if ( o2 instanceof Comparable ) 
 221  
                 {
 222  0
                     return ((Comparable)o1).compareTo( o2 );
 223  
                 }
 224  
             }
 225  
             
 226  
             // null handling: null is less than any object
 227  
             
 228  0
             if ( o1 == null ) 
 229  
             {
 230  0
                 if ( o2 == null )
 231  
                 {
 232  0
                     return 0;
 233  
                 }
 234  
                 else
 235  
                 {
 236  0
                    return -1;
 237  
                 }
 238  
             }
 239  
             else // o1 != null
 240  0
             if ( o2 == null )
 241  
             {
 242  0
                 return 1;
 243  
             }
 244  
             
 245  
             // fall back on string representation comparison
 246  
             
 247  0
             return o1.toString().compareTo( o2.toString() );
 248  
         }
 249  
                            
 250  
         public boolean equals(Object obj)
 251  
         {
 252  0
             return ( this == obj );   
 253  
         }
 254  
     }
 255  
     
 256  0
     private static class CompareDescendingComparator 
 257  
         extends CompareAscendingComparator
 258  
     {
 259  
         public int compare(Object o1, Object o2)
 260  
         {
 261  0
             return -1 * super.compare( o1, o2 );             
 262  
         }
 263  
     }
 264  
 
 265  0
     private static class CompareCaseInsensitiveAscendingComparator 
 266  
         extends NSSelector
 267  
     {
 268  
         public int compare(Object o1, Object o2)
 269  
         {
 270  
             // null handling: null is less than any object
 271  
             
 272  0
             if ( o1 == null ) 
 273  
             {
 274  0
                 if ( o2 == null )
 275  
                 {
 276  0
                     return 0;
 277  
                 }
 278  
                 else
 279  
                 {
 280  0
                    return -1;
 281  
                 }
 282  
             }
 283  
             else // o1 != null
 284  0
             if ( o2 == null )
 285  
             {
 286  0
                 return 1;
 287  
             }
 288  
             
 289  0
             return o1.toString().toLowerCase().compareTo( 
 290  0
                 o2.toString().toLowerCase() );
 291  
         }
 292  
                            
 293  
         public boolean equals(Object obj)
 294  
         {
 295  0
             return ( this == obj );   
 296  
         }
 297  
     }
 298  
     
 299  0
     private static class CompareCaseInsensitiveDescendingComparator 
 300  
         extends CompareCaseInsensitiveAscendingComparator
 301  
     {
 302  
         public int compare(Object o1, Object o2)
 303  
         {
 304  0
             return -1 * super.compare( o1, o2 );             
 305  
         }
 306  
     }
 307  
     
 308  
     private static class DelegatingComparator implements Comparator
 309  
     {
 310  
         private String key;
 311  
         private Comparator comparator;
 312  
         
 313  0
         public DelegatingComparator( String aKey, Comparator aComparator )
 314  0
         {
 315  0
             key = aKey;
 316  0
             comparator = aComparator;
 317  0
         }
 318  
         
 319  
         public int compare(Object o1, Object o2)
 320  
         {
 321  
             Object v1, v2;
 322  0
             if ( o1 instanceof EOKeyValueCoding )
 323  
             {
 324  0
                 v1 = ((EOKeyValueCoding)o1).valueForKey( key );   
 325  0
             }
 326  
             else
 327  
             {
 328  0
                 v1 = EOKeyValueCodingSupport.valueForKey( o1, key );
 329  
             }
 330  0
             if ( o2 instanceof EOKeyValueCoding )
 331  
             {
 332  0
                 v2 = ((EOKeyValueCoding)o2).valueForKey( key );   
 333  0
             }
 334  
             else
 335  
             {
 336  0
                 v2 = EOKeyValueCodingSupport.valueForKey( o2, key );
 337  
             }
 338  0
             return comparator.compare( v1, v2 );
 339  
         }
 340  
                            
 341  
         public boolean equals(Object obj)
 342  
         {
 343  0
             return ( this == obj );   
 344  
         }
 345  
     }
 346  
 
 347  
 }
 348  
 
 349  
 /*
 350  
  * $Log$
 351  
  * Revision 1.2  2006/02/16 16:47:14  cgruber
 352  
  * Move some classes in to "internal" packages and re-work imports, etc.
 353  
  *
 354  
  * Also use UnsupportedOperationExceptions where appropriate, instead of WotonomyExceptions.
 355  
  *
 356  
  * Revision 1.1  2006/02/16 13:19:57  cgruber
 357  
  * Check in all sources in eclipse-friendly maven-enabled packages.
 358  
  *
 359  
  * Revision 1.14  2003/08/11 19:39:52  chochos
 360  
  * now encodes/decodes correctly.
 361  
  *
 362  
  * Revision 1.13  2003/08/09 01:29:56  chochos
 363  
  * implements EOKeyValueArchiving
 364  
  *
 365  
  * Revision 1.12  2003/08/06 23:07:52  chochos
 366  
  * general code cleanup (mostly, removing unused imports)
 367  
  *
 368  
  * Revision 1.11  2003/02/07 20:23:23  mpowers
 369  
  * Provided backwards compatibility for comparators.
 370  
  *
 371  
  * Revision 1.10  2003/01/18 23:46:58  mpowers
 372  
  * EOSortOrdering is now correctly using NSSelectors.
 373  
  *
 374  
  * Revision 1.9  2003/01/16 22:47:30  mpowers
 375  
  * Compatibility changes to support compiling woextensions source.
 376  
  * (34 out of 56 classes compile!)
 377  
  *
 378  
  * Revision 1.8  2002/03/01 20:23:27  mpowers
 379  
  * Implemented equals.
 380  
  *
 381  
  * Revision 1.7  2002/02/06 21:15:04  mpowers
 382  
  * Added null handling to CompareCaseInsensitiveAscendingComparator.
 383  
  *
 384  
  * Revision 1.6  2001/12/01 23:51:24  mpowers
 385  
  * Made serializable.
 386  
  *
 387  
  * Revision 1.5  2001/03/29 03:29:49  mpowers
 388  
  * Now using KeyValueCoding and Support instead of Introspector.
 389  
  *
 390  
  * Revision 1.4  2001/01/24 22:15:52  mpowers
 391  
  * Fixed npe when comparing nulls.
 392  
  *
 393  
  * Revision 1.3  2001/01/12 19:11:56  mpowers
 394  
  * Fixed table column click sorting.
 395  
  *
 396  
  * Revision 1.2  2001/01/12 17:23:46  mpowers
 397  
  * Inner classes are now private.
 398  
  *
 399  
  * Revision 1.1  2001/01/11 20:34:26  mpowers
 400  
  * Implemented EOSortOrdering and added support in framework.
 401  
  * Added header-click to sort table columns.
 402  
  *
 403  
  *
 404  
  */
 405  
     
 406