Coverage Report - org.apache.ojb.broker.query.SearchFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
SearchFilter
N/A
N/A
2.318
SearchFilter$SearchBase
N/A
N/A
2.318
SearchFilter$SearchBaseLeaf
N/A
N/A
2.318
SearchFilter$SearchBaseLeafComparison
N/A
N/A
2.318
SearchFilter$SearchBaseLeafInt
N/A
N/A
2.318
SearchFilter$SearchBaseNode
N/A
N/A
2.318
 
 1  
 package org.apache.ojb.broker.query;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.util.Enumeration;
 19  
 import java.util.Hashtable;
 20  
 import java.util.Vector;
 21  
 
 22  
 /**
 23  
  * Class to build selection criteria for searches
 24  
  * Search Filter Class (Abstract)
 25  
  * This class builds a search filter tree, specifing how names and
 26  
  * values are to be compared when searching a database.
 27  
  * It just builds internal structures, and needs to be extended
 28  
  * to return a search filter string or other object that can be
 29  
  * used by the database to perform the actual search.
 30  
  */
 31  
 public abstract class SearchFilter
 32  
 {
 33  
     // Define the operators
 34  
     // Binary operators have bit 8 set
 35  
     // Logical operators have bit 9 set
 36  
     public static final int AND = 0x200;              // Logical operator
 37  
     public static final int OR = 0x201;               // Logical operator
 38  
     public static final int NOT = 0x2;                // Unary operator
 39  
     public static final int IN = 0x3;
 40  
     public static final int NOT_IN = 0x4;
 41  
     public static final int LIKE = 0x109;             // Binary operator
 42  
     public static final int EQUAL = 0x10A;            // Binary operator
 43  
     public static final int NOT_EQUAL = 0x10B;        // Binary operator
 44  
     public static final int LESS_THAN = 0x10C;        // Binary operator
 45  
     public static final int GREATER_THAN = 0x10D;     // Binary operator
 46  
     public static final int GREATER_EQUAL = 0x10E;    // Binary operator
 47  
     public static final int LESS_EQUAL = 0x10F;       // Binary operator
 48  
     // Define a mask for the binary and logical operators
 49  
     // private static final int                                        BINARY_OPER_MASK = 0x100;
 50  
     // private static final int                                        LOGICAL_OPER_MASK = 0x200;
 51  
     protected static final int BINARY_OPER_MASK = 0x100;
 52  
     protected static final int LOGICAL_OPER_MASK = 0x200;
 53  
     // Define the current search filter
 54  
     protected SearchBase m_filter = null;
 55  
 
 56  
     /**
 57  
      * Create an empty search filter.
 58  
      *
 59  
      */
 60  
     // -----------------------------------------------------------
 61  
     public SearchFilter()
 62  
     {
 63  
     }
 64  
 
 65  
     /**
 66  
      * Change the search filter to one that specifies an element to
 67  
      * match or not match one of a list of values.
 68  
      * The old search filter is deleted.
 69  
      *
 70  
      * @param ElementName is the name of the element to be matched
 71  
      * @param values is a vector of possible matches
 72  
      * @param oper is the IN or NOT_IN operator to indicate how to matche
 73  
      */
 74  
     public void matchList(String ElementName, Vector values, int oper)
 75  
     {
 76  
         // Delete the old search filter
 77  
         m_filter = null;
 78  
         // If not NOT_IN, assume IN
 79  
         // (Since ints are passed by value, it is OK to change it)
 80  
         if (oper != NOT_IN)
 81  
         {
 82  
             oper = IN;
 83  
             // Convert the vector of match strings to an array of strings
 84  
         }
 85  
         String[] value_string_array = new String[values.size()];
 86  
         values.copyInto(value_string_array);
 87  
         // Create a leaf node for this list and store it as the filter
 88  
         m_filter = new SearchBaseLeaf(ElementName, oper, value_string_array);
 89  
     }
 90  
 
 91  
     /**
 92  
      * Change the search filter to one that specifies an element to not
 93  
      * match one of a list of values.
 94  
      * The old search filter is deleted.
 95  
      *
 96  
      * @param ElementName is the name of the element to be matched
 97  
      * @param values is an array of possible matches
 98  
      * @param oper is the IN or NOT_IN operator to indicate how to matche
 99  
      */
 100  
     public void matchList(String ElementName, String[] values, int oper)
 101  
     {
 102  
         // Delete the old search filter
 103  
         m_filter = null;
 104  
         // If not NOT_IN, assume IN
 105  
         // (Since ints are passed by value, it is OK to change it)
 106  
         if (oper != NOT_IN)
 107  
         {
 108  
             oper = IN;
 109  
             // Create a leaf node for this list and store it as the filter
 110  
         }
 111  
         m_filter = new SearchBaseLeaf(ElementName, oper, values);
 112  
     }
 113  
 
 114  
     /**
 115  
      * Change the search filter to one that specifies an element to not
 116  
      * match one of a list of integer values.
 117  
      * The old search filter is deleted.
 118  
      *
 119  
      * @param ElementName is the name of the element to be matched
 120  
      * @param values is an array of possible integer matches
 121  
      * @param oper is the IN or NOT_IN operator to indicate how to matche
 122  
      */
 123  
     public void matchList(String ElementName, int[] values, int oper)
 124  
     {
 125  
         // Delete the old search filter
 126  
         m_filter = null;
 127  
         // If not NOT_IN, assume IN
 128  
         // (Since ints are passed by value, it is OK to change it)
 129  
         if (oper != NOT_IN)
 130  
         {
 131  
             oper = IN;
 132  
             // Create a leaf node for this list and store it as the filter
 133  
         }
 134  
         m_filter = new SearchBaseLeafInt(ElementName, oper, values);
 135  
     }
 136  
 
 137  
     /**
 138  
      * Change the search filter to one that specifies an element to not
 139  
      * match one single value.
 140  
      * The old search filter is deleted.
 141  
      *
 142  
      * @param ElementName is the name of the element to be matched
 143  
      * @param value is the value to not be matched
 144  
      * @param oper is the IN or NOT_IN operator to indicate how to matche
 145  
      */
 146  
     public void matchValue(String ElementName, String value, int oper)
 147  
     {
 148  
         // Delete the old search filter
 149  
         m_filter = null;
 150  
         // If not NOT_IN, assume IN
 151  
         // (Since ints are passed by value, it is OK to change it)
 152  
         if (oper != NOT_IN)
 153  
         {
 154  
             oper = IN;
 155  
             // Create a String array in which to hold the one name,
 156  
             // and put that name in the array
 157  
         }
 158  
         String[] ValueArray = new String[1];
 159  
         ValueArray[0] = value;
 160  
         // Create a leaf node for this list and store it as the filter
 161  
         m_filter = new SearchBaseLeaf(ElementName, oper, ValueArray);
 162  
     }
 163  
 
 164  
     /**
 165  
      * -----------------------------------------------------------
 166  
      * @param ElementName
 167  
      * @param value
 168  
      * @param oper
 169  
      */
 170  
     public void matchValue(String ElementName, int value, int oper)
 171  
     {
 172  
         // Delete the old search filter
 173  
         m_filter = null;
 174  
         // If not NOT_IN, assume IN
 175  
         // (Since ints are passed by value, it is OK to change it)
 176  
         if (oper != NOT_IN)
 177  
         {
 178  
             oper = IN;
 179  
             // Create a leaf node for this list and store it as the filter
 180  
         }
 181  
         m_filter = new SearchBaseLeafInt(ElementName, oper, new int[]
 182  
         {
 183  
             value
 184  
         });
 185  
     }
 186  
 
 187  
     /**
 188  
      * Change the search filter to one that compares an element name to a value.
 189  
      * The old search filter is deleted.
 190  
      *
 191  
      * @param ElementName is the name of the element to be tested
 192  
      * @param value is the value to be compared against
 193  
      * @param oper is the binary comparison operator to be used
 194  
      * @exception DBException
 195  
      */
 196  
     public void compareFilter(String ElementName, String value, int oper) throws DBException
 197  
     {
 198  
         // Delete the old search filter
 199  
         m_filter = null;
 200  
         // If this is not a binary operator, throw an exception
 201  
         if ((oper & BINARY_OPER_MASK) == 0)
 202  
         {
 203  
             throw new DBException();
 204  
             // Create a SearchBaseLeafComparison node and store it as the filter
 205  
         }
 206  
         m_filter = new SearchBaseLeafComparison(ElementName, oper, value);
 207  
     }
 208  
 
 209  
     /**
 210  
      * Change the search filter to one that specifies a set of elements and their values
 211  
      * that must match, and the operator to use to combine the elements.
 212  
      * Each key is compared for an equal match to the value, and all
 213  
      * comparisons are combined by the specified logical operator (OR or AND).
 214  
      * The old search filter is deleted.
 215  
      *
 216  
      * @param elements is a hashtable holding key-value pairs
 217  
      * @param combine_op is the logical operator to be used to combine the comparisons
 218  
      * @param compare_op is the binary operator to be used for the comparisons
 219  
      * @exception DBException
 220  
      */
 221  
     public void matchSet(Hashtable elements, int combine_op, int compare_op) throws DBException
 222  
     {
 223  
         // Delete the old search filter
 224  
         m_filter = null;
 225  
         // If combine_op is not a logical operator, throw an exception
 226  
         if ((combine_op & LOGICAL_OPER_MASK) == 0)
 227  
         {
 228  
             throw new DBException();
 229  
             // If compare_op is not a binary operator, throw an exception
 230  
         }
 231  
         if ((compare_op & BINARY_OPER_MASK) == 0)
 232  
         {
 233  
             throw new DBException();
 234  
             // Create a vector that will hold the comparison nodes for all elements in the hashtable
 235  
         }
 236  
         Vector compareVector = new Vector();
 237  
         // For each of the elements in the hashtable, create a comparison node for the match
 238  
         for (Enumeration e = elements.keys(); e.hasMoreElements();)
 239  
         {
 240  
             // Get the element name from the enumerator
 241  
             // and its value
 242  
             String elementName = (String) e.nextElement();
 243  
             String elementValue = (String) elements.get(elementName);
 244  
             // Create a comparison node for this list and store it as the filter
 245  
             SearchBaseLeafComparison comparenode = new SearchBaseLeafComparison(elementName,
 246  
                     compare_op, elementValue);
 247  
             // Add this leaf node to the vector
 248  
             compareVector.addElement(comparenode);
 249  
         }
 250  
         // Now return a node that holds this set of leaf nodes
 251  
         m_filter = new SearchBaseNode(combine_op, compareVector);
 252  
     }
 253  
 
 254  
     /**
 255  
      * Change the search filter to one that specifies a set of elements and their values
 256  
      * that must match, and the operator to use to combine the elements.
 257  
      * Each element name is compared for an equal match to the value, and all
 258  
      * comparisons are combined by the specified logical operator (OR or AND).
 259  
      * The old search filter is deleted.
 260  
      *
 261  
      * @param ElementNames is an array of names of elements to be tested
 262  
      * @param ElementValues is an array of values for the corresponding element
 263  
      * @param op is the logical operator to be used to combine the comparisons
 264  
      * @exception DBException
 265  
      */
 266  
     public void matchSet(String[] ElementNames, String[] ElementValues, int op) throws DBException
 267  
     {
 268  
         // Delete the old search filter
 269  
         m_filter = null;
 270  
         // If this is not a logical operator, throw an exception
 271  
         if ((op & LOGICAL_OPER_MASK) == 0)
 272  
         {
 273  
             throw new DBException();
 274  
             // Create a vector that will hold the leaf nodes for all elements in the hashtable
 275  
         }
 276  
         Vector leafVector = new Vector();
 277  
         // For each of the elements in the array, create a leaf node for the match
 278  
         int numnames = ElementNames.length;
 279  
         for (int i = 0; i < numnames; i++)
 280  
         {
 281  
             // Create a leaf node for this list and store it as the filter
 282  
             SearchBaseLeaf leafnode = new SearchBaseLeaf(ElementNames[i], IN, ElementValues[i]);
 283  
             // Add this leaf node to the vector
 284  
             leafVector.addElement(leafnode);
 285  
         }
 286  
         // Now return a node that holds this set of leaf nodes
 287  
         m_filter = new SearchBaseNode(op, leafVector);
 288  
     }
 289  
 
 290  
     /**
 291  
      * Combine other search filters with this one, using the specific operator.
 292  
      *
 293  
      * @param new_filters is a vector of SearchFilter classes to be combined
 294  
      * @param op is the logical operator to be used to combine the filters
 295  
      * @exception DBException
 296  
      */
 297  
     public void combine(Vector new_filters, int op) throws DBException
 298  
     {
 299  
         // If this is not a logical operator, throw an exception
 300  
         if ((op & LOGICAL_OPER_MASK) == 0)
 301  
         {
 302  
             throw new DBException();
 303  
             // Create a new vector consisting of just the filters
 304  
             // from the SearchFilter classes in new_filters
 305  
         }
 306  
         Vector filters = new Vector();
 307  
         // Now add in all the nodes of the new filters
 308  
         for (Enumeration e = new_filters.elements(); e.hasMoreElements();)
 309  
         {
 310  
             // Get the search filter from the vector
 311  
             SearchFilter f = (SearchFilter) e.nextElement();
 312  
             filters.addElement(f.getFilter());
 313  
         }
 314  
         // Create a node for this list and return it
 315  
         m_filter = new SearchBaseNode(op, m_filter, filters);
 316  
     }
 317  
 
 318  
     /**
 319  
      * Combine one other search filters with this one, using the specific operator.
 320  
      *
 321  
      * @param new_filter is the SearchFilter class to be combined
 322  
      * @param op is the logical operator to be used to combine the filters
 323  
      * @exception DBException
 324  
      */
 325  
     public void combine(SearchFilter new_filter, int op) throws DBException
 326  
     {
 327  
         // If this is not a logical operator, throw an exception
 328  
         if ((op & LOGICAL_OPER_MASK) == 0)
 329  
         {
 330  
             throw new DBException();
 331  
             // Create a new vector consisting of just the filters
 332  
             // from the SearchFilter classes in new_filters
 333  
         }
 334  
         Vector filters = new Vector();
 335  
         filters.addElement(new_filter.getFilter());
 336  
         // Create a node for this list and return it
 337  
         m_filter = new SearchBaseNode(op, m_filter, filters);
 338  
     }
 339  
 
 340  
     /**
 341  
      * Static method to convert a binary operator into a string.
 342  
      *
 343  
      * @param oper is the binary comparison operator to be converted
 344  
      */
 345  
     protected static String ConvertBinaryOperator(int oper)
 346  
     {
 347  
         // Convert the operator into the proper string
 348  
         String oper_string;
 349  
         switch (oper)
 350  
         {
 351  
             default:
 352  
             case EQUAL:
 353  
                 oper_string = "=";
 354  
                 break;
 355  
             case LIKE:
 356  
                 oper_string = "LIKE";
 357  
                 break;
 358  
             case NOT_EQUAL:
 359  
                 oper_string = "!=";
 360  
                 break;
 361  
             case LESS_THAN:
 362  
                 oper_string = "<";
 363  
                 break;
 364  
             case GREATER_THAN:
 365  
                 oper_string = ">";
 366  
                 break;
 367  
             case GREATER_EQUAL:
 368  
                 oper_string = ">=";
 369  
                 break;
 370  
             case LESS_EQUAL:
 371  
                 oper_string = "<=";
 372  
                 break;
 373  
         }
 374  
         return oper_string;
 375  
     }
 376  
 
 377  
     /**
 378  
      * Get the actual filter out of the class.
 379  
      * This is only needed when combining filters together
 380  
      * and one instantiation has to get the filter from another.
 381  
      * However, I do not know how to protect it from outside use.
 382  
      * @return
 383  
      *
 384  
      */
 385  
     protected SearchBase getFilter()
 386  
     {
 387  
         return m_filter;
 388  
     }
 389  
 
 390  
     /**
 391  
      * Converts this search filter into a search string for use by a database.
 392  
      *
 393  
      */
 394  
 
 395  
     /**
 396  
      * -----------------------------------------------------------
 397  
      * @return
 398  
      */
 399  
     public abstract String toString();
 400  
 
 401  
     /**
 402  
      * SearchBase is the base node class for the parse tree
 403  
      * This class holds the binary operator
 404  
      *
 405  
      */
 406  
     // ===============================================================
 407  
     protected class SearchBase
 408  
     {
 409  
         // Define the operator to be used for this group
 410  
         public int oper;
 411  
 
 412  
         /**
 413  
          * Constructor.
 414  
          * This is protected so only the subclasses can instantiate it
 415  
          *
 416  
          */
 417  
         // ------------------------------------------------------------
 418  
         protected SearchBase()
 419  
         {
 420  
         }
 421  
 
 422  
     }
 423  
 
 424  
     /**
 425  
      * SearchBaseLeafComparison holds a leaf of the search tree
 426  
      * This class holds an element name, a binary operator, and a value to be compared
 427  
      */
 428  
     // ===============================================================
 429  
     protected class SearchBaseLeafComparison extends SearchBase
 430  
     {
 431  
         // Define the element name
 432  
         public String elementName;
 433  
         // Only operators allowed are binary operators
 434  
         // Define the comparison value
 435  
         public String value;
 436  
 
 437  
         /**
 438  
          * Constructor.
 439  
          *
 440  
          * @param ElementName is the name of the element to be tested
 441  
          * @param oper is the binary operator to be used for the comparison
 442  
          * @param value is the value to be used for the comparison
 443  
          */
 444  
         SearchBaseLeafComparison(String ElementName, int oper, String value)
 445  
         {
 446  
             this.elementName = ElementName;
 447  
             this.oper = oper;
 448  
             this.value = value;
 449  
         }
 450  
 
 451  
     }
 452  
 
 453  
     /**
 454  
      * SearchBaseLeaf holds a leaf of the search tree
 455  
      * This class holds an element name, and a vector of possible matches.
 456  
      * It searches for an element of the given name that matches at least
 457  
      * one of the strings in the array (IN), or does not match any (NOT_IN)
 458  
      *
 459  
      */
 460  
     // ===============================================================
 461  
     protected class SearchBaseLeaf extends SearchBase
 462  
     {
 463  
         // Define the element name
 464  
         public String elementName;
 465  
         // Only operators allowed are IN and NOT_IN
 466  
         // Define the vector of possible matches
 467  
         public String[] matches;
 468  
 
 469  
         /**
 470  
          * Constructor.
 471  
          *
 472  
          * @param ElementName is the name of the element to be tested
 473  
          * @param oper is the operator (IN or NOT_IN) to be used for the comparison
 474  
          * @param matches is an array of String values to be matched
 475  
          */
 476  
         SearchBaseLeaf(String ElementName, int oper, String[] matches)
 477  
         {
 478  
             this.elementName = ElementName;
 479  
             this.oper = oper;
 480  
             this.matches = matches;
 481  
         }
 482  
 
 483  
         /**
 484  
          * Constructor for only one value.
 485  
          *
 486  
          * @param ElementName is the name of the element to be tested
 487  
          * @param oper is the operator (IN or NOT_IN) to be used for the comparison
 488  
          * @param match is a string value to be matched
 489  
          */
 490  
         SearchBaseLeaf(String ElementName, int oper, String match)
 491  
         {
 492  
             this.elementName = ElementName;
 493  
             this.oper = oper;
 494  
             this.matches = new String[1];
 495  
             this.matches[0] = match;
 496  
         }
 497  
 
 498  
     }
 499  
 
 500  
     /**
 501  
      * SearchBaseLeafInt holds a leaf of the search tree with integers
 502  
      * This class holds an element name, and a vector of possible matches.
 503  
      * It searches for an element of the given name that matches at least
 504  
      * one of the integers in the array (IN), or does not match any (NOT_IN)
 505  
      */
 506  
     // ===============================================================
 507  
     protected class SearchBaseLeafInt extends SearchBase
 508  
     {
 509  
         // Define the element name
 510  
         public String elementName;
 511  
         // Only operators allowed are IN and NOT_IN
 512  
         // Define the vector of possible matches
 513  
         public int[] matches;
 514  
 
 515  
         /**
 516  
          * Constructor.
 517  
          *
 518  
          * @param ElementName is the name of the element to be tested
 519  
          * @param oper is the operator (IN or NOT_IN) to be used for the comparison
 520  
          * @param matches is an array of integer values to be matched
 521  
          */
 522  
         SearchBaseLeafInt(String ElementName, int oper, int[] matches)
 523  
         {
 524  
             this.elementName = ElementName;
 525  
             this.oper = oper;
 526  
             this.matches = matches;
 527  
         }
 528  
 
 529  
         /**
 530  
          * Constructor for only one value.
 531  
          *
 532  
          * @param ElementName is the name of the element to be tested
 533  
          * @param oper is the operator (IN or NOT_IN) to be used for the comparison
 534  
          * @param match is an int value to be matched
 535  
          */
 536  
         SearchBaseLeafInt(String ElementName, int oper, int match)
 537  
         {
 538  
             this.elementName = ElementName;
 539  
             this.oper = oper;
 540  
             this.matches = new int[1];
 541  
             this.matches[0] = match;
 542  
         }
 543  
 
 544  
     }
 545  
 
 546  
     /**
 547  
      * Define the class to represent a node of the search tree
 548  
      * This class holds an operator and a vector other nodes.
 549  
      */
 550  
     // ===============================================================
 551  
     protected class SearchBaseNode extends SearchBase
 552  
     {
 553  
         // Define the vector of other nodes
 554  
         public Vector nodes;
 555  
 
 556  
         /**
 557  
          * Constructor.
 558  
          * Store a list of filters and an operator for combining them.
 559  
          *
 560  
          * @param oper is the operator (IN or NOT_IN) to be used for the comparison
 561  
          * @param new_filters is a vector of filters to be combined
 562  
          */
 563  
         SearchBaseNode(int oper, Vector new_filters)
 564  
         {
 565  
             this.oper = oper;
 566  
             this.nodes = new_filters;
 567  
         }
 568  
 
 569  
         /**
 570  
          * Constructor for a specific filter and a vector of new ones.
 571  
          * Store a list of filters and an operator for combining them.
 572  
          *
 573  
          * @param oper is the operator (IN or NOT_IN) to be used for the comparison
 574  
          * @param filter is the first filter to be combined
 575  
          * @param new_filters is a vector of filters to be combined
 576  
          */
 577  
         SearchBaseNode(int oper, Object filter, Vector new_filters)
 578  
         {
 579  
             // Store the operator
 580  
             this.oper = oper;
 581  
             // Create a vector and add in the first filter as the initial node (if present)
 582  
             nodes = new Vector();
 583  
             if (filter != null)
 584  
             {
 585  
                 nodes.addElement(filter);
 586  
                 // Now add in all the nodes of the new filters
 587  
             }
 588  
             for (Enumeration e = new_filters.elements(); e.hasMoreElements();)
 589  
             {
 590  
                 nodes.addElement(e.nextElement());
 591  
             }
 592  
         }
 593  
 
 594  
     }
 595  
 }