Coverage Report - net.wotonomy.control.EOQualifier
 
Classes in this File Line Coverage Branch Coverage Complexity
EOQualifier
0% 
0% 
1.76
 
 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.lang.reflect.InvocationTargetException;
 22  
 import java.lang.reflect.Method;
 23  
 import java.util.Collection;
 24  
 import java.util.Iterator;
 25  
 import java.util.LinkedList;
 26  
 import java.util.List;
 27  
 import java.util.ListIterator;
 28  
 import java.util.Map;
 29  
 import java.util.Set;
 30  
 import java.util.StringTokenizer;
 31  
 
 32  
 import net.wotonomy.foundation.NSArray;
 33  
 import net.wotonomy.foundation.NSMutableArray;
 34  
 import net.wotonomy.foundation.NSMutableDictionary;
 35  
 import net.wotonomy.foundation.NSSelector;
 36  
 import net.wotonomy.foundation.NSSet;
 37  
 import net.wotonomy.foundation.internal.ValueConverter;
 38  
 import net.wotonomy.foundation.internal.WotonomyException;
 39  
 
 40  
 /**
 41  
 * EOQualifiers are used to perform property-based
 42  
 * qualifications on objects: for a set of criteria,
 43  
 * a qualifier either qualifies or disqualifies an
 44  
 * given object.  EOKeyValueQualifiers can be joined
 45  
 * by EOAndQualifier and EOOrQualifier, and so can
 46  
 * form a tree of qualifications.  <br><br>
 47  
 *
 48  
 * Certain qualifiers
 49  
 * can accept a variable in place of a value; variable
 50  
 * names are marked by a "$", as in "$name".  Variables
 51  
 * are resolved with the qualifierWithBindings() method.
 52  
 *
 53  
 * @author michael@mpowers.net
 54  
 * @author yjcheung@intersectsoft.com
 55  
 * @author $Author: cgruber $
 56  
 * @version $Revision: 894 $
 57  
 */
 58  0
 public abstract class EOQualifier
 59  
 {
 60  
     public static final NSSelector 
 61  0
         QualifierOperatorCaseInsensitiveLike = new OperatorCaseInsensitiveLike();
 62  
     public static final NSSelector 
 63  0
         QualifierOperatorContains = new OperatorContains();
 64  
     public static final NSSelector 
 65  0
         QualifierOperatorEqual = new OperatorEqual();
 66  
     public static final NSSelector 
 67  0
         QualifierOperatorGreaterThan = new OperatorGreaterThan();
 68  
     public static final NSSelector 
 69  0
         QualifierOperatorGreaterThanOrEqualTo = new OperatorGreaterThanOrEqualTo();
 70  
     public static final NSSelector 
 71  0
         QualifierOperatorLessThan = new OperatorLessThan();
 72  
     public static final NSSelector 
 73  0
         QualifierOperatorLessThanOrEqualTo = new OperatorLessThanOrEqualTo();
 74  
     public static final NSSelector 
 75  0
         QualifierOperatorLike = new OperatorLike();
 76  
     public static final NSSelector 
 77  0
         QualifierOperatorNotEqual = new OperatorNotEqual();
 78  
 
 79  
     /**
 80  
     * Default constructor.
 81  
     */
 82  0
     public EOQualifier ()
 83  0
     {
 84  0
     }
 85  
 
 86  
     /**
 87  
     * Adds all qualifier keys in this qualifier to
 88  
     * the specified Set, which is expected to be
 89  
     * mutable.  The tree of qualifiers is traversed
 90  
     * and the left-hand-side of each expression is
 91  
     * added to the set.
 92  
     */
 93  
     public void addQualifierKeysToSet ( Set aSet )
 94  
     {
 95  0
         throw new RuntimeException( "Not implemented yet." );
 96  
     }
 97  
 
 98  
     /**
 99  
     * Returns a Set of all property names used for
 100  
     * comparisons by this qualifier.  The tree of
 101  
     * qualifiers is traversed and the left-hand-side
 102  
     * of each expression is added to the set.
 103  
     */
 104  
     public NSSet allQualifierKeys ()
 105  
     {
 106  0
         throw new RuntimeException( "Not implemented yet." );
 107  
     }
 108  
 
 109  
     /**
 110  
     * Returns a List containing the variables used
 111  
     * at compare-time by this qualifier.  Each variable
 112  
     * will appear only once in the list.
 113  
     */
 114  
     public NSArray bindingKeys ()
 115  
     {
 116  0
         throw new RuntimeException( "Not implemented yet." );
 117  
     }
 118  
 
 119  
     /**
 120  
     * Returns whether the specified object meets the
 121  
     * criteria defined by this qualifier.
 122  
     */
 123  
     public boolean evaluateWithObject ( Object anObject )
 124  
     {
 125  0
         return true;
 126  
     }
 127  
     
 128  
     /**
 129  
     * Returns the key (which can be a key path) that
 130  
     * is tested against the specified binding variable.
 131  
     * The tree is traversed looking for the first instance
 132  
     * of the specified variable, and the corresponding
 133  
     * left-hand-side of the expression is returned.
 134  
     */
 135  
     public String keyPathForBindingKey ( String aVariable )
 136  
     {
 137  0
         throw new RuntimeException( "Not implemented yet." );
 138  
     }
 139  
 
 140  
     /**
 141  
     * Returns a qualifier that is like this qualifier,
 142  
     * except all variables will be replaced with values
 143  
     * from the specified Map whose keys match the variable
 144  
     * names.  If requireAll is true, an exception will be
 145  
     * thrown if there is no key that matches on of the
 146  
     * variables in the tree; otherwise, the qualifier
 147  
     * containing the unmatched variable is removed.
 148  
     */
 149  
     public EOQualifier qualifierWithBindings (
 150  
         Map aMap,
 151  
         boolean requireAll )
 152  
     {
 153  0
         throw new WotonomyException( "Not implemented yet." );
 154  
     }
 155  
 
 156  
 
 157  
     /**
 158  
     * Tests whether all the keys in this qualifier can
 159  
     * be applied to an object of the specified class.
 160  
     * @return A Throwable if the validation fails,
 161  
     * otherwise returns null if the class can be used
 162  
     * with this qualifier.
 163  
     */
 164  
     public Throwable validateKeysWithRootClassDescription (
 165  
         Class aClass )
 166  
     {
 167  0
         throw new WotonomyException( "Not implemented yet." );
 168  
     }
 169  
 
 170  
     // statics
 171  
 
 172  
     /**
 173  
     * Convenience to retain only those objects from the specified
 174  
     * List that meet the specified qualifier's requirements.
 175  
     */
 176  
     public static void filterArrayWithQualifier (
 177  
         List anObjectList, EOQualifier aQualifier )
 178  
     {
 179  0
         ListIterator iterator = anObjectList.listIterator();
 180  0
         while ( iterator.hasNext() )
 181  
         {
 182  0
             if ( ! aQualifier.evaluateWithObject( iterator.next() ) )
 183  
             {
 184  0
                 iterator.remove();
 185  0
             }
 186  
         }
 187  0
     }
 188  
 
 189  
     /**
 190  
     * Convenience to return a List consisting only
 191  
     * of those objects in the specified List that meet
 192  
     * the specified qualifier's requirements.
 193  
     */
 194  
     public static NSArray filteredArrayWithQualifier (
 195  
         List anObjectList, EOQualifier aQualifier )
 196  
     {
 197  
         Object o;
 198  0
         List result = new LinkedList();
 199  0
         Iterator iterator = anObjectList.iterator();
 200  0
         while ( iterator.hasNext() )
 201  
         {
 202  0
             o = iterator.next();
 203  0
             if ( aQualifier.evaluateWithObject( o ) )
 204  
             {
 205  0
                 result.add( o );
 206  0
             }
 207  
         }
 208  0
         return new NSArray( (Collection) result );
 209  
     }
 210  
 
 211  
     /**
 212  
     * Convenience to create a set of EOKeyValueQualifiers
 213  
     * joined by an EOAndQualifier. Each pair of keys and
 214  
     * values are used to create EOKeyValueQualifiers.
 215  
     */
 216  
     public static EOQualifier
 217  
     qualifierToMatchAllValues ( Map aMap )
 218  
     {
 219  
         Object key, value;
 220  0
         List qualifierList = new LinkedList();
 221  0
         Iterator iterator = aMap.keySet().iterator();
 222  0
         while ( iterator.hasNext() )
 223  
         {
 224  0
             key = iterator.next();
 225  0
             value = aMap.get( key );
 226  0
             qualifierList.add( new EOKeyValueQualifier( 
 227  0
                 key.toString(), QualifierOperatorEqual, value ) );
 228  0
         }
 229  0
         return new EOAndQualifier( qualifierList );
 230  
     }
 231  
 
 232  
     /**
 233  
     * Convenience to create a set of EOKeyValueQualifiers
 234  
     * joined by an EOOrQualifier.  Each pair of keys and
 235  
     * values are used to create EOKeyValueQualifiers.
 236  
     */
 237  
     public static EOQualifier
 238  
     qualifierToMatchAnyValue ( Map aMap )
 239  
     {
 240  
         Object key, value;
 241  0
         List qualifierList = new LinkedList();
 242  0
         Iterator iterator = aMap.keySet().iterator();
 243  0
         while ( iterator.hasNext() )
 244  
         {
 245  0
             key = iterator.next();
 246  0
             value = aMap.get( key );
 247  0
             qualifierList.add( new EOKeyValueQualifier( 
 248  0
                 key.toString(), QualifierOperatorEqual, value ) );
 249  0
         }
 250  0
         return new EOOrQualifier( qualifierList );
 251  
     }
 252  
 
 253  
     /**
 254  
     * Returns an EOQualifier that meets the criteria
 255  
     * represented by the specified string and variable
 256  
     * length argument list.  This method parses the string
 257  
     * and returns a tree of qualifiers.  Each token beginning
 258  
     * with "%" is replaced with the corresponding object
 259  
     * from the argument list.  The parser recognizes the
 260  
     * operation tokens returned from the allQualifierOperators()
 261  
     * method.
 262  
     */
 263  
     public static EOQualifier qualifierWithQualifierFormat (
 264  
         String aString, List anArgumentList )
 265  
     {
 266  0
         throw new RuntimeException( "Not implemented yet." );
 267  
     }
 268  
 
 269  
     /**
 270  
     * Returns a List of operators that are supported for
 271  
     * relational operations.  This excludes string comparison
 272  
     * operators.
 273  
     */
 274  
     public static NSArray relationalQualifierOperators ()
 275  
     {
 276  0
         NSMutableArray result = new NSMutableArray();
 277  
         BaseSelector selector;
 278  0
         Iterator iterator = allQualifierOperators().iterator();
 279  0
         while ( iterator.hasNext() )
 280  
         {
 281  0
             selector = (BaseSelector) iterator.next();
 282  0
             if ( selector.isRelationalOperator() )
 283  
             {
 284  0
                 result.addObject( selector );
 285  0
             }
 286  
         }
 287  0
         return result;
 288  
     }
 289  
 
 290  
     /**
 291  
     * Returns a List of valid operators.
 292  
     */
 293  
     public static NSArray allQualifierOperators ()
 294  
     {
 295  0
         return operators.allKeys();
 296  
     }
 297  
 
 298  
     /**
 299  
     * Returns a selector the corresponds to the operation
 300  
     * represented by the specified string.  For example,
 301  
     * ">" represents QualifierOperatorGreaterThan.
 302  
     */
 303  
     public static NSSelector operatorSelectorForString (
 304  
         String anOperatorString )
 305  
     {
 306  0
         return (NSSelector)
 307  0
             operators.objectForKey( anOperatorString );
 308  
     }
 309  
 
 310  
     /**
 311  
     * Returns a string the corresponds to the operation
 312  
     * represented by the specified selector.  For example,
 313  
     * QualifierOperatorGreaterThan is represented with ">".
 314  
     */
 315  
     public static String stringForOperatorSelector (
 316  
         NSSelector aSelector )
 317  
     {
 318  0
         return (String) 
 319  0
             operators.allKeysForObject( aSelector ).lastObject();
 320  
     }
 321  
 
 322  
     /**
 323  
     * Returns a string representation of this qualifier.
 324  
     */
 325  
     public String toString()
 326  
     {
 327  
          //TODO: implement this
 328  0
          return super.toString();
 329  
     }
 330  
 
 331  
     // built-in qualifiers
 332  
     
 333  
     private static NSMutableDictionary operators;
 334  
     static 
 335  
     {
 336  0
         operators = new NSMutableDictionary();
 337  0
         operators.setObjectForKey( 
 338  0
             QualifierOperatorCaseInsensitiveLike, 
 339  0
             QualifierOperatorCaseInsensitiveLike.toString() );
 340  0
         operators.setObjectForKey( 
 341  0
             QualifierOperatorContains, 
 342  0
             QualifierOperatorContains.toString() );
 343  0
         operators.setObjectForKey( 
 344  0
             QualifierOperatorEqual, 
 345  0
             QualifierOperatorEqual.toString() );
 346  0
         operators.setObjectForKey( 
 347  0
             QualifierOperatorGreaterThan, 
 348  0
             QualifierOperatorGreaterThan.toString() );
 349  0
         operators.setObjectForKey( 
 350  0
             QualifierOperatorGreaterThanOrEqualTo, 
 351  0
             QualifierOperatorGreaterThanOrEqualTo.toString() );
 352  0
         operators.setObjectForKey( 
 353  0
             QualifierOperatorLessThan, 
 354  0
             QualifierOperatorLessThan.toString() );
 355  0
         operators.setObjectForKey( 
 356  0
             QualifierOperatorLessThanOrEqualTo, 
 357  0
             QualifierOperatorLessThanOrEqualTo.toString() );
 358  0
         operators.setObjectForKey( 
 359  0
             QualifierOperatorLike, 
 360  0
             QualifierOperatorLike.toString() );
 361  0
         operators.setObjectForKey( 
 362  0
             QualifierOperatorNotEqual, 
 363  0
             QualifierOperatorNotEqual.toString() );
 364  0
     }
 365  
 
 366  0
     static private abstract class BaseSelector extends NSSelector
 367  
     {
 368  
         public String name ()
 369  
         {
 370  0
             return "BaseSelector";
 371  
         }
 372  
     
 373  
         public Class[] parameterTypes ()
 374  
         {
 375  0
             return new Class[] { Object.class, Object.class };
 376  
         }
 377  
     
 378  
         public Method methodOnClass (Class aClass) 
 379  
             throws NoSuchMethodException
 380  
         {
 381  0
             throw new NoSuchMethodException();
 382  
         }
 383  
         
 384  
         public Method methodOnObject (Object anObject)
 385  
             throws NoSuchMethodException
 386  
         {
 387  0
             throw new NoSuchMethodException();
 388  
         }
 389  
         
 390  
         public boolean implementedByClass (Class aClass)
 391  
         {
 392  0
             return true;
 393  
         }
 394  
         
 395  
         public boolean implementedByObject (Object anObject)
 396  
         {
 397  0
             return true;
 398  
         }
 399  
         
 400  
         public boolean isRelationalOperator()
 401  
         {
 402  0
             return true;
 403  
         }
 404  
         
 405  
         public Object invoke (Object anObject, Object[] parameters) 
 406  
             throws IllegalAccessException, IllegalArgumentException, 
 407  
                 InvocationTargetException, NoSuchMethodException
 408  
         {
 409  0
             return qualify( anObject, parameters[0] );
 410  
         }
 411  
         
 412  
         abstract protected Boolean qualify( Object target, Object parameter );
 413  
 
 414  
         protected int doCompare(Object o1, Object o2)
 415  
         {
 416  0
             Class firstClass = o1.getClass();
 417  0
             Class secondClass = o2.getClass();
 418  
     
 419  0
             if ( ! ( secondClass.equals( firstClass ) ) )
 420  
             {
 421  0
                 Object converted = null;
 422  0
                 if ( o2 instanceof Comparable )
 423  
                 {
 424  0
                     converted = ValueConverter.convertObjectToClass( o1, secondClass );
 425  0
                     if (converted != null)
 426  
                     {
 427  0
                         o1 = converted;
 428  
                     }
 429  
                 }
 430  
                 
 431  0
                 if (converted == null && (o1 instanceof Comparable))
 432  
                 {
 433  0
                     converted = ValueConverter.convertObjectToClass( o2, firstClass );
 434  0
                     if ( converted != null )
 435  
                     {
 436  0
                         o2 = converted;
 437  
                     }
 438  
                 }
 439  
                 
 440  0
                 if (converted == null)
 441  
                 {
 442  0
                     throw new WotonomyException("Qualifier: Not Comparable Objects");
 443  
                     // no way to compare
 444  
                 }
 445  
             }
 446  
             
 447  0
             return ((Comparable)o2).compareTo( o1 );
 448  
         }
 449  
     
 450  
     }
 451  
     
 452  
     
 453  0
     static class OperatorCaseInsensitiveLike extends BaseSelector {
 454  
         
 455  
         public boolean isRelationalOperator()
 456  
         {
 457  0
             return false;
 458  
         }
 459  
         
 460  
         protected Boolean qualify( Object o1, Object o2 )
 461  
         {
 462  0
             String myString1 = o1.toString();
 463  0
             String myString2 = o2.toString();
 464  0
             myString1 = myString1.toLowerCase();
 465  0
             myString2 = myString2.toLowerCase();
 466  0
             StringTokenizer st = new StringTokenizer(myString1, "%");
 467  
             
 468  0
             while (st.hasMoreTokens()) {
 469  0
                  String part = st.nextToken();
 470  0
                  int index = myString2.indexOf(part);
 471  0
                  if (index > -1)
 472  
                  {
 473  0
                      myString2 = myString2.substring(index + part.length());
 474  0
                  }
 475  
                  else
 476  
                  {
 477  0
                      return Boolean.FALSE;
 478  
                  }
 479  0
              }
 480  0
             return Boolean.TRUE;
 481  
             
 482  
         }
 483  
         
 484  
         public String toString()
 485  
         {
 486  0
             return "caseInsensitiveLike";
 487  
         }
 488  
     }
 489  
     
 490  0
     static class OperatorContains extends BaseSelector {
 491  
         
 492  
         public boolean isRelationalOperator()
 493  
         {
 494  0
             return false;
 495  
         }
 496  
         
 497  
         protected Boolean qualify( Object o1, Object o2 )
 498  
         {
 499  0
             String myString1 = o1.toString();
 500  0
             String myString2 = o2.toString();
 501  0
             return new Boolean(
 502  0
                 myString2.indexOf(myString1) > -1 );
 503  
         }
 504  
         
 505  
         public String toString()
 506  
         {
 507  0
             return "contains";
 508  
         }
 509  
     }
 510  
     
 511  0
     static class OperatorEqual extends BaseSelector {
 512  
     
 513  
         protected Boolean qualify( Object o1, Object o2 )
 514  
         {
 515  0
             return new Boolean( doCompare(o1, o2) == 0 );
 516  
         }
 517  
         
 518  
         public String toString()
 519  
         {
 520  0
             return "=";
 521  
         }
 522  
     }
 523  
     
 524  0
     static class OperatorGreaterThan extends BaseSelector {
 525  
     
 526  
         protected Boolean qualify( Object o1, Object o2 )
 527  
         {
 528  0
             return new Boolean( doCompare(o1, o2) > 0 );
 529  
         }
 530  
         
 531  
         public String toString()
 532  
         {
 533  0
             return ">";
 534  
         }
 535  
     }
 536  
     
 537  0
     static class OperatorGreaterThanOrEqualTo extends BaseSelector {
 538  
         
 539  
         protected Boolean qualify( Object o1, Object o2 )
 540  
         {
 541  0
             return new Boolean( doCompare(o1, o2) >= 0 );
 542  
         }
 543  
         
 544  
         public String toString()
 545  
         {
 546  0
             return new String(" >= ");
 547  
         }
 548  
     }
 549  
     
 550  0
     static class OperatorLessThan extends BaseSelector {
 551  
         
 552  
         protected Boolean qualify( Object o1, Object o2 )
 553  
         {
 554  0
             return new Boolean( doCompare(o1, o2) < 0 ); 
 555  
         }
 556  
         
 557  
         public String toString()
 558  
         {
 559  0
             return ">";
 560  
         }
 561  
     }
 562  
     
 563  0
     static class OperatorLessThanOrEqualTo extends BaseSelector {
 564  
         
 565  
         protected Boolean qualify( Object o1, Object o2 )
 566  
         {
 567  0
             return new Boolean (doCompare(o1, o2) <= 0);
 568  
         }
 569  
         
 570  
         public String toString()
 571  
         {
 572  0
             return "<=";
 573  
         }
 574  
     }
 575  
     
 576  0
     static class OperatorLike extends BaseSelector {
 577  
         
 578  
         public boolean isRelationalOperator()
 579  
         {
 580  0
             return false;
 581  
         }
 582  
         
 583  
         protected Boolean qualify( Object o1, Object o2 )
 584  
         {
 585  0
             String myString1 = o1.toString();
 586  0
             String myString2 = o2.toString();
 587  0
             StringTokenizer st = new StringTokenizer(myString1, "%");
 588  0
             while (st.hasMoreTokens()) {
 589  0
                  String part = st.nextToken();
 590  0
                  int index = myString2.indexOf(part);
 591  0
                  if (index > -1)
 592  
                  {
 593  0
                      myString2 = myString2.substring(index + part.length());
 594  0
                  }
 595  
                  else
 596  
                  {
 597  0
                      return Boolean.FALSE;
 598  
                  }
 599  0
             }
 600  0
             return Boolean.TRUE;
 601  
         }
 602  
         
 603  
         public String toString()
 604  
         {
 605  0
             return "like";
 606  
         }
 607  
     }
 608  
     
 609  0
     static class OperatorNotEqual extends BaseSelector {
 610  
 
 611  
         protected Boolean qualify( Object o1, Object o2 )
 612  
         {
 613  0
             return new Boolean(!(o1.equals(o2)));
 614  
         }
 615  
         
 616  
         public String toString()
 617  
         {
 618  0
             return "!=";
 619  
         }
 620  
     }
 621  
  
 622  
 
 623  
         public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver ua) {
 624  0
                 String cname = (String)ua.decodeObjectForKey("class");
 625  0
                 if (cname.equals("EOKeyValueQualifier"))
 626  0
                         return (EOQualifier)EOKeyValueQualifier.decodeWithKeyValueUnarchiver(ua);
 627  0
                 if (cname.equals("EOAndQualifier"))
 628  0
                         return (EOQualifier)EOAndQualifier.decodeWithKeyValueUnarchiver(ua);
 629  0
                 if (cname.equals("EOOrQualifier"))
 630  0
                         return (EOQualifier)EOOrQualifier.decodeWithKeyValueUnarchiver(ua);
 631  0
                 if (cname.equals("EONotQualifier"))
 632  0
                         return (EOQualifier)EONotQualifier.decodeWithKeyValueUnarchiver(ua);
 633  0
                 return null;
 634  
         }
 635  
 
 636  
 }
 637  
 /*
 638  
  * $Log$
 639  
  * Revision 1.2  2006/02/16 16:47:14  cgruber
 640  
  * Move some classes in to "internal" packages and re-work imports, etc.
 641  
  *
 642  
  * Also use UnsupportedOperationExceptions where appropriate, instead of WotonomyExceptions.
 643  
  *
 644  
  * Revision 1.1  2006/02/16 13:19:57  cgruber
 645  
  * Check in all sources in eclipse-friendly maven-enabled packages.
 646  
  *
 647  
  * Revision 1.10  2003/08/09 01:22:51  chochos
 648  
  * qualifiers implement EOKeyValueArchiving
 649  
  *
 650  
  * Revision 1.9  2001/11/04 18:29:11  mpowers
 651  
  * Better handling for non-string types used with non-relational operators.
 652  
  *
 653  
  * Revision 1.8  2001/10/31 15:25:14  mpowers
 654  
  * Cleanup of qualifiers.
 655  
  *
 656  
  * Revision 1.7  2001/10/30 22:57:28  mpowers
 657  
  * EOQualifier framework is now working.
 658  
  *
 659  
  * Revision 1.6  2001/10/30 22:16:37  mpowers
 660  
  * Implemented operators as selectors.
 661  
  *
 662  
  * Revision 1.5  2001/09/14 14:21:28  mpowers
 663  
  * Updated javadoc.
 664  
  *
 665  
  * Revision 1.3  2001/09/13 15:25:56  mpowers
 666  
  * Started implementation of the EOQualifier framework.
 667  
  *
 668  
  * Revision 1.2  2001/02/27 03:33:04  mpowers
 669  
  * Initial draft of the key-value qualifier.
 670  
  *
 671  
  * Revision 1.1.1.1  2000/12/21 15:46:47  mpowers
 672  
  * Contributing wotonomy.
 673  
  *
 674  
  * Revision 1.2  2000/12/20 16:25:35  michael
 675  
  * Added log to all files.
 676  
  *
 677  
  *
 678  
  */
 679  
 
 680