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