001    package org.apache.ojb.broker.query;
002    
003    /* Copyright 2002-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import java.util.Enumeration;
019    import java.util.Hashtable;
020    import java.util.Vector;
021    
022    /**
023     * OJB Search Filter Class for ObJectRelationalBridge O/R mapping tool
024     *
025     * This class builds a search filter tree, specifing how names and
026     * values are to be compared when searching a database.
027     * This extends SearchFilter and implements the Convert method
028     * that produces the search filter string for the SQL database
029     *
030     * @author David Forslund
031     * @author koenig
032     * @version $Revision: 1.1 $ $Date: 2007-08-24 22:17:36 $
033     */
034    public class OJBSearchFilter extends SearchFilter
035    {
036        Criteria criteria = new Criteria();
037    
038        /**
039         * Constructors are not needed, as the base class has a default constructor.
040         *
041         */
042    
043        /**
044         * Change the search filter to one that specifies an element to
045         * match or not match one of a list of values.
046         * The old search filter is deleted.
047         *
048         * @param elementName is the name of the element to be matched
049         * @param values is a vector of possible matches
050         * @param oper is the IN or NOT_IN operator to indicate how to matche
051         */
052        public void matchList(String elementName, Vector values, int oper)
053        {
054    
055            // Delete the old search criteria
056            criteria = new Criteria();
057    
058            if (oper != NOT_IN)
059            {
060                for (int i = 0; i < values.size(); i++)
061                {
062                    Criteria tempCrit = new Criteria();
063    
064                    tempCrit.addEqualTo(elementName, values.elementAt(i));
065                    criteria.addOrCriteria(tempCrit);
066                }
067            }
068            else
069            {
070                for (int i = 0; i < values.size(); i++)
071                {
072                    criteria.addNotEqualTo(elementName, values.elementAt(i));
073                }
074            }
075        }
076    
077        /**
078         * Change the search filter to one that specifies an element to not
079         * match one of a list of values.
080         * The old search filter is deleted.
081         *
082         * @param elementName is the name of the element to be matched
083         * @param values is an array of possible matches
084         * @param oper is the IN or NOT_IN operator to indicate how to matche
085         */
086        public void matchList(String elementName, String[] values, int oper)
087        {
088    
089            // see also matchList(String elementName, Vector values, int oper)
090            // Delete the old search criteria
091            criteria = new Criteria();
092    
093            if (oper != NOT_IN)
094            {
095                for (int i = 0; i < values.length; i++)
096                {
097                    Criteria tempCrit = new Criteria();
098    
099                    tempCrit.addEqualTo(elementName, values[i]);
100                    criteria.addOrCriteria(tempCrit);
101                }
102            }
103            else
104            {
105                for (int i = 0; i < values.length; i++)
106                {
107                    criteria.addNotEqualTo(elementName, values[i]);
108                }
109            }
110        }
111    
112        /**
113         * Change the search filter to one that specifies an element to not
114         * match one of a list of integer values.
115         * The old search filter is deleted.
116         *
117         * @param elementName is the name of the element to be matched
118         * @param values is an array of possible integer matches
119         * @param oper is the IN or NOT_IN operator to indicate how to matche
120         */
121        public void matchList(String elementName, int[] values, int oper)
122        {
123    
124            // see also matchList(String elementName, Vector values, int oper)
125            // Delete the old search criteria
126            criteria = new Criteria();
127    
128            if (oper != NOT_IN)
129            {
130                for (int i = 0; i < values.length; i++)
131                {
132                    Criteria tempCrit = new Criteria();
133    
134                    tempCrit.addEqualTo(elementName, new Integer(values[i]));
135                    criteria.addOrCriteria(tempCrit);
136                }
137            }
138            else
139            {
140                for (int i = 0; i < values.length; i++)
141                {
142                    criteria.addNotEqualTo(elementName, new Integer(values[i]));
143                }
144            }
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    
159            // Delete the old search criteria
160            criteria = new Criteria();
161    
162            if (oper != NOT_IN)
163            {
164                criteria.addEqualTo(elementName, value);
165            }
166            else
167            {
168                criteria.addNotEqualTo(elementName, value);
169            }
170        }
171    
172        /**
173         * -----------------------------------------------------------
174         * @param elementName
175         * @param value
176         * @param oper
177         */
178        public void matchValue(String elementName, int value, int oper)
179        {
180    
181            // Delete the old search criteria
182            criteria = new Criteria();
183    
184            if (oper != NOT_IN)
185            {
186                criteria.addEqualTo(elementName, new Integer(value));
187            }
188            else
189            {
190                criteria.addNotEqualTo(elementName, new Integer(value));
191            }
192        }
193    
194        /**
195         * Change the search filter to one that compares an element name to a value.
196         * The old search filter is deleted.
197         *
198         * @param elementName is the name of the element to be tested
199         * @param value is the value to be compared against
200         * @param oper is the binary comparison operator to be used
201         * @exception DBException
202         */
203        public void compareFilter(String elementName, String value,
204                                  int oper) throws DBException
205        {
206    
207            // Delete the old search criteria
208            criteria = new Criteria();
209    
210            // If this is not a binary operator, throw an exception
211            if ((oper & BINARY_OPER_MASK) == 0)
212            {
213                throw new DBException();
214            }
215    
216            switch (oper)
217            {
218    
219                case LIKE:
220                    {
221                        criteria.addLike(elementName, value);
222    
223                        break;
224                    }
225    
226                case EQUAL:
227                    {
228                        criteria.addEqualTo(elementName, value);
229    
230                        break;
231                    }
232    
233                case NOT_EQUAL:
234                    {
235                        criteria.addNotEqualTo(elementName, value);
236    
237                        break;
238                    }
239    
240                case LESS_THAN:
241                    {
242                        criteria.addLessThan(elementName, value);
243    
244                        break;
245                    }
246    
247                case GREATER_THAN:
248                    {
249                        criteria.addGreaterThan(elementName, value);
250    
251                        break;
252                    }
253    
254                case GREATER_EQUAL:
255                    {
256                        criteria.addGreaterOrEqualThan(elementName, value);
257    
258                        break;
259                    }
260    
261                case LESS_EQUAL:
262                    {
263                        criteria.addLessOrEqualThan(elementName, value);
264    
265                        break;
266                    }
267    
268                default:
269                    {
270                        throw new DBException("Unsupported binary operation in OJBSearchFilter!");
271                    }
272            }
273        }
274    
275        /**
276         * Change the search filter to one that specifies a set of elements and their values
277         * that must match, and the operator to use to combine the elements.
278         * Each key is compared for an equal match to the value, and all
279         * comparisons are combined by the specified logical operator (OR or AND).
280         * The old search filter is deleted.
281         *
282         * @param elements is a hashtable holding key-value pairs
283         * @param combine_op is the logical operator to be used to combine the comparisons
284         * @param compare_op is the binary operator to be used for the comparisons
285         * @exception DBException
286         */
287        public void matchSet(Hashtable elements, int combine_op,
288                             int compare_op) throws DBException
289        {
290    
291            // Delete the old search criteria
292            criteria = new Criteria();
293    
294            // If compare_op is not a binary operator, throw an exception
295            if ((compare_op & BINARY_OPER_MASK) == 0)
296            {
297                throw new DBException();
298            }
299    
300            if (combine_op == AND)
301            {
302                // combine all value pairs by an AND
303    
304                // For each of the elements in the hashtable, create a comparison node for the match
305                for (Enumeration e = elements.keys(); e.hasMoreElements();)
306                {
307    
308                    // Get the element name from the enumerator
309                    // and its value
310                    String elementName = (String) e.nextElement();
311                    String elementValue = (String) elements.get(elementName);
312    
313                    switch (compare_op)
314                    {
315    
316                        case LIKE:
317                            {
318                                criteria.addLike(elementName, elementValue);
319    
320                                break;
321                            }
322    
323                        case EQUAL:
324                            {
325                                criteria.addEqualTo(elementName, elementValue);
326    
327                                break;
328                            }
329    
330                        case NOT_EQUAL:
331                            {
332                                criteria.addNotEqualTo(elementName, elementValue);
333    
334                                break;
335                            }
336    
337                        case LESS_THAN:
338                            {
339                                criteria.addLessThan(elementName, elementValue);
340    
341                                break;
342                            }
343    
344                        case GREATER_THAN:
345                            {
346                                criteria.addGreaterThan(elementName, elementValue);
347    
348                                break;
349                            }
350    
351                        case GREATER_EQUAL:
352                            {
353                                criteria.addGreaterOrEqualThan(elementName, elementValue);
354    
355                                break;
356                            }
357    
358                        case LESS_EQUAL:
359                            {
360                                criteria.addLessOrEqualThan(elementName, elementValue);
361    
362                                break;
363                            }
364    
365                        default:
366                            {
367                                throw new DBException("Unsupported binary operation in OJBSearchFilter!");
368                            }
369                    }                                                  // end of switch
370                }                                                      // end of for
371            }
372            else if (combine_op == OR)
373            {
374                // combine all value pairs by an OR
375                // For each of the elements in the hashtable, create a comparison node for the match
376                for (Enumeration e = elements.keys(); e.hasMoreElements();)
377                {
378    
379                    // Get the element name from the enumerator
380                    // and its value
381                    String elementName = (String) e.nextElement();
382                    String elementValue = (String) elements.get(elementName);
383    
384                    switch (compare_op)
385                    {
386    
387                        case LIKE:
388                            {
389                                Criteria tempCrit = new Criteria();
390    
391                                tempCrit.addLike(elementName, elementValue);
392                                criteria.addOrCriteria(tempCrit);
393    
394                                break;
395                            }
396    
397                        case EQUAL:
398                            {
399                                Criteria tempCrit = new Criteria();
400    
401                                tempCrit.addEqualTo(elementName, elementValue);
402                                criteria.addOrCriteria(tempCrit);
403    
404                                break;
405                            }
406    
407                        case NOT_EQUAL:
408                            {
409                                Criteria tempCrit = new Criteria();
410    
411                                tempCrit.addNotEqualTo(elementName, elementValue);
412                                criteria.addOrCriteria(tempCrit);
413    
414                                break;
415                            }
416    
417                        case LESS_THAN:
418                            {
419                                Criteria tempCrit = new Criteria();
420    
421                                tempCrit.addLessThan(elementName, elementValue);
422                                criteria.addOrCriteria(tempCrit);
423    
424                                break;
425                            }
426    
427                        case GREATER_THAN:
428                            {
429                                Criteria tempCrit = new Criteria();
430    
431                                tempCrit.addGreaterThan(elementName, elementValue);
432                                criteria.addOrCriteria(tempCrit);
433    
434                                break;
435                            }
436    
437                        case GREATER_EQUAL:
438                            {
439                                Criteria tempCrit = new Criteria();
440    
441                                tempCrit.addGreaterOrEqualThan(elementName, elementValue);
442                                criteria.addOrCriteria(tempCrit);
443    
444                                break;
445                            }
446    
447                        case LESS_EQUAL:
448                            {
449                                Criteria tempCrit = new Criteria();
450    
451                                tempCrit.addLessOrEqualThan(elementName, elementValue);
452                                criteria.addOrCriteria(tempCrit);
453    
454                                break;
455                            }
456    
457                        default:
458                            {
459                                throw new DBException("Unsupported binary operation in OJBSearchFilter!");
460                            }
461                    }                                          // end of switch
462                }                                              // end of for
463    
464            }
465            else
466            {
467    
468                // combine_op is not a logical operator, throw an exception
469                throw new DBException();
470            }
471        }
472    
473        /**
474         * Change the search filter to one that specifies a set of elements and their values
475         * that must match, and the operator to use to combine the elements.
476         * Each element name is compared for an equal match to the value, and all
477         * comparisons are combined by the specified logical operator (OR or AND).
478         * The old search filter is deleted.
479         *
480         * @param elementNames is an array of names of elements to be tested
481         * @param elementValues is an array of values for the corresponding element
482         * @param op is the logical operator to be used to combine the comparisons
483         * @exception DBException
484         */
485        public void matchSet(String[] elementNames, String[] elementValues,
486                             int op) throws DBException
487        {
488    
489            // Delete the old search criteria
490            criteria = new Criteria();
491    
492            if (op == OR)
493            {
494                // For each of the elements in the array, create a leaf node for the match
495                for (int i = 0; i < elementNames.length; i++)
496                {
497                    Criteria tempCrit = new Criteria();
498    
499                    tempCrit.addEqualTo(elementNames[i], elementValues[i]);
500                    criteria.addOrCriteria(tempCrit);
501                }
502            }
503            else if (op == AND)
504            {
505                for (int i = 0; i < elementNames.length; i++)
506                {
507                    criteria.addEqualTo(elementNames[i], elementValues[i]);
508                }
509            }
510            else
511            {
512                throw new DBException();
513            }
514        }
515    
516        /**
517         * Combine other search filters with this one, using the specific operator.
518         *
519         * @param new_filters is a vector of SearchFilter classes to be combined
520         * @param op is the logical operator to be used to combine the filters
521         * @exception DBException
522         */
523        public void combine(Vector new_filters, int op) throws DBException
524        {
525            for (Enumeration elems = new_filters.elements(); elems.hasMoreElements();)
526            {
527                SearchFilter filter = (SearchFilter) elems.nextElement();
528    
529                combine(filter, op);
530            }
531        }
532    
533        /**
534         * Combine one other search filters with this one, using the specific operator.
535         *
536         * @param new_filter is the SearchFilter class to be combined
537         * @param op is the logical operator to be used to combine the filters
538         * @exception DBException
539         */
540        public void combine(SearchFilter new_filter, int op) throws DBException
541        {
542    
543            // cast down to OJBSearchFilter
544            OJBSearchFilter ojbFilter = (OJBSearchFilter) new_filter;
545    
546            switch (op)
547            {
548    
549                case OR:
550                    {
551                        criteria.addOrCriteria(ojbFilter.getCriteria());
552                        break;
553                    }
554    
555                case AND:
556                    {
557                        criteria.addAndCriteria(ojbFilter.getCriteria());
558                        break;
559                    }
560    
561                default:
562                    {
563                        throw new DBException();
564                    }
565            }
566        }
567    
568        /**
569         * Converts this search filter into a search string
570         * Note:
571         * ObJectRelationalBridge can't parse a SQL string yet, the functionality
572         * is therefor not implemented!
573         */
574    
575        /**
576         * -----------------------------------------------------------
577         * @return
578         */
579        public String toString()
580        {
581    
582            // return "";
583            return criteria.toString();
584        }
585    
586        /**
587         * Returns the search critera
588         *
589         */
590    
591        /**
592         * -----------------------------------------------------------
593         * @return
594         */
595        protected Criteria getCriteria()
596        {
597    
598            // return the search criteria
599            return criteria;
600        }
601    
602    }