Coverage Report - net.wotonomy.foundation.NSSelector
 
Classes in this File Line Coverage Branch Coverage Complexity
NSSelector
0% 
0% 
1.957
 
 1  
 /*
 2  
 Wotonomy: OpenStep design patterns for pure Java applications.
 3  
 Copyright (C) 2000 Blacksmith, Inc.
 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.foundation;
 20  
 
 21  
 import java.io.Serializable;
 22  
 import java.lang.reflect.InvocationTargetException;
 23  
 import java.lang.reflect.Method;
 24  
 import java.util.Comparator;
 25  
 
 26  
 import net.wotonomy.foundation.internal.PropertyComparator;
 27  
 
 28  
 /**
 29  
 * A pure java implementation of NSSelector.
 30  
 *
 31  
 * @author michael@mpowers.net
 32  
 * @author $Author: cgruber $
 33  
 * @version $Revision: 892 $
 34  
 */
 35  0
 public class NSSelector implements Comparator, Serializable
 36  
 {
 37  
         protected NSMutableDictionary methodMap; // map of classes to methods
 38  
         protected String methodName;
 39  
         protected Class[] parameterTypes;
 40  
 
 41  
         /**
 42  
         * A marker to indicate object not found.
 43  
         */
 44  
         protected static final String NOT_FOUND = "NOT_FOUND";
 45  
         
 46  
         /**
 47  
         * Saves creating a new class array for parameterless method invocation.
 48  
         */
 49  0
         protected static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
 50  
         
 51  
         /**
 52  
         * Saves creating a new object array for parameterless method invocation.
 53  
         */
 54  0
         protected static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
 55  
         
 56  
     /**
 57  
     * Constructor specifying a method name and an array of parameter types.
 58  
     */
 59  0
     public NSSelector (String aMethodName, Class[] aParameterTypeArray)
 60  0
     {
 61  0
             methodName = aMethodName;
 62  0
             parameterTypes = aParameterTypeArray;
 63  0
             methodMap = new NSMutableDictionary();
 64  0
     }
 65  
     
 66  
     /**
 67  
     * Constructor specifying a method name with no parameters.
 68  
     */
 69  
     public NSSelector (String aMethodName)
 70  
     {
 71  0
             this( aMethodName, EMPTY_CLASS_ARRAY );
 72  0
     }
 73  
     
 74  
     /**
 75  
     * Constructor for custom subclasses that implement specific operators
 76  
     * and that do not use dynamic method invocation.
 77  
     */
 78  0
     protected NSSelector()
 79  0
     {
 80  0
     }
 81  
 
 82  
     /**
 83  
     * Returns the name of the method.
 84  
     */
 85  
     public String name ()
 86  
     {
 87  0
             return methodName;
 88  
     }
 89  
 
 90  
     /**
 91  
     * Returns the array of parameter types.
 92  
     */
 93  
     public Class[] parameterTypes ()
 94  
     {
 95  0
             return parameterTypes;
 96  
     }
 97  
 
 98  
     /**
 99  
     * A String description of this selector.
 100  
     */
 101  
     public String toString ()
 102  
     {
 103  0
             StringBuffer result = new StringBuffer();
 104  0
             result.append( "[" + getClass().getName() + ": name = " + name() + ", parameter types = [" );
 105  0
         if ( parameterTypes != null )
 106  
         {
 107  0
             if ( parameterTypes.length > 0 )
 108  
             {
 109  0
                 result.append( parameterTypes[0].toString() );
 110  
             }
 111  0
             for ( int i = 1; i < parameterTypes.length; i++ )
 112  
             {
 113  0
                 result.append( ", " );
 114  0
                 result.append( parameterTypes[i].toString() );
 115  
             }
 116  
         }
 117  0
             result.append( "] ]" );
 118  0
             return result.toString();
 119  
     }
 120  
 
 121  
     /**
 122  
     * Returns the appropriate method for the specified class.
 123  
     */
 124  
     public Method methodOnClass (Class aClass) 
 125  
             throws NoSuchMethodException
 126  
         {
 127  0
                 Object result = methodMap.objectForKey( aClass );
 128  
                 
 129  0
                 if ( result == null )
 130  
                 {
 131  0
                         result = getMethodForClass( aClass );
 132  0
             if ( result == null )
 133  
             {
 134  0
                 result = NOT_FOUND;
 135  
             }
 136  0
                         methodMap.setObjectForKey( result, aClass );
 137  
                 }
 138  
                 
 139  0
                 if ( result == NOT_FOUND )
 140  
                 {
 141  0
                         throw new NoSuchMethodException();
 142  
                 }
 143  0
                 return (Method) result;
 144  
         }
 145  
         
 146  
     /**
 147  
     * Returns the appropriate method, or null if not found.
 148  
     */
 149  
         private Method getMethodForClass( Class aClass )
 150  
         {
 151  0
                 Method[] methods = aClass.getMethods();
 152  0
                 for ( int i = 0; i < methods.length; i++ )
 153  
                 {
 154  0
                         if ( methods[i].getName().equals( name() ) )
 155  
                         {
 156  0
                                 Class[] params = methods[i].getParameterTypes();
 157  0
                                 if ( params.length == parameterTypes.length )
 158  
                                 {
 159  0
                                         boolean pass = true;
 160  0
                                         for ( int j = 0; j < params.length; j++ )
 161  
                                         {
 162  0
                                                 if ( ! params[j].isAssignableFrom( parameterTypes[j] ) )
 163  
                                                 {
 164  0
                                                         pass = false;
 165  
                                                 }
 166  
                                         }        
 167  0
                                         if ( pass ) return methods[i];
 168  
                                 }
 169  
                         }
 170  
                 }
 171  0
                 return null;
 172  
         }
 173  
 
 174  
     /**
 175  
     * Convenience to get a method for an object.
 176  
     */
 177  
     public Method methodOnObject (Object anObject)
 178  
             throws NoSuchMethodException
 179  
         {
 180  0
                 Method m = methodOnClass( anObject.getClass() );
 181  0
         if ( m == null ) throw new NoSuchMethodException( name() );
 182  0
         return m;
 183  
         }
 184  
 
 185  
     /**
 186  
     * Returns whether the class implements the method for this selector.
 187  
     */
 188  
     public boolean implementedByClass (Class aClass)
 189  
     {
 190  
             try
 191  
             {
 192  0
                         methodOnClass( aClass );
 193  0
                         return true;
 194  
             }
 195  0
             catch ( NoSuchMethodException exc )
 196  
             {
 197  
             }
 198  0
             return false;
 199  
     }
 200  
 
 201  
     /**
 202  
     * Returns whether the object's class implements the method 
 203  
     * for this selector.
 204  
     */
 205  
     public boolean implementedByObject (Object anObject)
 206  
     {
 207  
             try
 208  
             {
 209  0
                         methodOnObject( anObject );
 210  0
                         return true;
 211  
             }
 212  0
             catch ( NoSuchMethodException exc )
 213  
             {
 214  
             }
 215  0
             return false;
 216  
     }
 217  
 
 218  
     /**
 219  
     * Invokes this selector's method on the specified object 
 220  
     * using the specified parameters.
 221  
     */
 222  
     public Object invoke (Object anObject, Object[] parameters) 
 223  
             throws IllegalAccessException, IllegalArgumentException, 
 224  
                     InvocationTargetException, NoSuchMethodException
 225  
         {
 226  0
                 return methodOnObject( anObject ).invoke( anObject, parameters );
 227  
         }
 228  
 
 229  
     /**
 230  
     * Invokes this selector's method on the specified object 
 231  
     * with no parameters.
 232  
     */
 233  
     public Object invoke (Object anObject) 
 234  
             throws IllegalAccessException, IllegalArgumentException, 
 235  
                     InvocationTargetException, NoSuchMethodException
 236  
         {
 237  0
                 return invoke( anObject, EMPTY_OBJECT_ARRAY );
 238  
         }
 239  
 
 240  
     /**
 241  
     * Invokes this selector's method on the specified object 
 242  
     * with the specified parameter.
 243  
     */
 244  
     public Object invoke (Object anObject, Object aParameter) 
 245  
             throws IllegalAccessException, IllegalArgumentException, 
 246  
                     InvocationTargetException, NoSuchMethodException
 247  
         {
 248  0
                 return invoke( anObject, new Object[] { aParameter } );
 249  
         }
 250  
 
 251  
     /**
 252  
     * Invokes this selector's method on the specified object 
 253  
     * using the specified two parameters.
 254  
     */
 255  
     public Object invoke (Object anObject, Object p1, Object p2) 
 256  
             throws IllegalAccessException, IllegalArgumentException, 
 257  
                     InvocationTargetException, NoSuchMethodException
 258  
         {
 259  0
                 return invoke( anObject, new Object[] { p1, p2 } );
 260  
         }
 261  
                     
 262  
     /**
 263  
     * Invokes the method with the specified signature on the specified 
 264  
     * object using the specified parameters.
 265  
     */
 266  
     public static Object invoke 
 267  
                 (String methodName, Class[] parameterTypes, Object anObject, Object[] parameters) 
 268  
             throws IllegalAccessException, IllegalArgumentException, 
 269  
                     InvocationTargetException, NoSuchMethodException
 270  
         {
 271  0
                 return new NSSelector( methodName, parameterTypes ).invoke( anObject, parameters );
 272  
         }
 273  
 
 274  
     /**
 275  
     * Invokes the method with the specified signature on the specified object 
 276  
     * with no parameters.
 277  
     */
 278  
     public static Object invoke  
 279  
                 (String methodName, Object anObject) 
 280  
             throws IllegalAccessException, IllegalArgumentException, 
 281  
                     InvocationTargetException, NoSuchMethodException
 282  
         {
 283  0
                 return NSSelector.invoke( 
 284  0
                         methodName, EMPTY_CLASS_ARRAY, anObject, EMPTY_OBJECT_ARRAY );
 285  
         }
 286  
 
 287  
     /**
 288  
     * Invokes the method with the specified signature on the specified 
 289  
     * object using the specified parameter.
 290  
     */
 291  
     public static Object invoke  
 292  
                 (String methodName, Class[] parameterTypes, 
 293  
                  Object anObject, Object aParameter) 
 294  
             throws IllegalAccessException, IllegalArgumentException, 
 295  
                     InvocationTargetException, NoSuchMethodException
 296  
         {
 297  0
                 return NSSelector.invoke( 
 298  0
                         methodName, parameterTypes, anObject, new Object[] { aParameter } );
 299  
         }
 300  
 
 301  
     /**
 302  
     * Invokes the method with the specified signature on the specified 
 303  
     * object using the specified two parameters.
 304  
     */
 305  
     public static Object invoke  
 306  
                 (String methodName, Class[] parameterTypes, 
 307  
                  Object anObject, Object p1, Object p2) 
 308  
             throws IllegalAccessException, IllegalArgumentException, 
 309  
                     InvocationTargetException, NoSuchMethodException
 310  
         {
 311  0
                 return NSSelector.invoke( 
 312  0
                         methodName, parameterTypes, anObject, new Object[] { p1, p2 } );
 313  
         }
 314  
 
 315  
     // interface Comparator
 316  
 
 317  
     private Comparator comparator;        
 318  
     
 319  
     /**
 320  
     * Constructor specifying a method name and a comparator.
 321  
     * This is not in the spec.
 322  
     */
 323  
     public NSSelector (String aMethodName, Comparator aComparator)
 324  
     {
 325  0
             this( aMethodName, EMPTY_CLASS_ARRAY );
 326  0
         comparator = aComparator;
 327  0
     }
 328  
     
 329  
     /**
 330  
     * Returns the Comparator used for this selector.
 331  
     * This is not in the spec.
 332  
     */
 333  
     public Comparator comparator()
 334  
     {
 335  0
         if ( comparator == null )
 336  
         {
 337  0
             comparator = new PropertyComparator( methodName );
 338  
         }
 339  0
         return comparator;
 340  
     }
 341  
     
 342  
     public int compare(Object o1, Object o2)
 343  
     {
 344  0
         if ( comparator == null )
 345  
         {
 346  0
             comparator = new PropertyComparator( methodName );
 347  
         }
 348  0
         return comparator.compare( o1, o2 );
 349  
     }
 350  
     
 351  
     public boolean equals(Object obj)
 352  
     {
 353  0
         return ( obj == this );
 354  
     }
 355  
 }
 356  
 
 357  
 /*
 358  
  * $Log$
 359  
  * Revision 1.1  2006/02/16 12:47:16  cgruber
 360  
  * Check in all sources in eclipse-friendly maven-enabled packages.
 361  
  *
 362  
  * Revision 1.9  2003/02/12 19:34:35  mpowers
 363  
  * Added accessor for comparator.
 364  
  *
 365  
  * Revision 1.8  2003/02/07 20:23:41  mpowers
 366  
  * Provided backwards compatibility for comparators.
 367  
  *
 368  
  * Revision 1.7  2003/01/22 23:02:25  mpowers
 369  
  * Fixed a null pointer error in NSSelector.toString.
 370  
  *
 371  
  * Revision 1.6  2003/01/18 23:46:58  mpowers
 372  
  * EOSortOrdering is now correctly using NSSelectors.
 373  
  *
 374  
  * Revision 1.4  2001/10/31 15:24:45  mpowers
 375  
  * Implicit constructor is now protected.
 376  
  *
 377  
  * Revision 1.3  2001/02/07 19:25:51  mpowers
 378  
  * Fixed: method matching uses isAssignableFrom rather than ==.
 379  
  *
 380  
  * Revision 1.2  2001/01/08 23:30:16  mpowers
 381  
  * Fixed major bug - selectors were not supposed to share a method map.
 382  
  *
 383  
  * Revision 1.1.1.1  2000/12/21 15:47:45  mpowers
 384  
  * Contributing wotonomy.
 385  
  *
 386  
  * Revision 1.3  2000/12/20 16:25:39  michael
 387  
  * Added log to all files.
 388  
  *
 389  
  *
 390  
  */
 391