001    /* Query.java -- Static methods for query construction.
002       Copyright (C) 2007 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package javax.management;
039    
040    /**
041     * Provides static methods for constructing queries.  Queries
042     * may be used to list and enumerate management beans, via
043     * the {@link MBeanServer}.  By using the methods in this class,
044     * complex queries can be created from their more basic
045     * components. 
046     *
047     * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
048     * @since 1.5
049     */
050    public class Query
051    {
052    
053      /**
054       * A code representing the {@link #plus(ValueExp, ValueExp)
055       * query to be used in serialization.
056       */
057      public static final int PLUS = 0;
058    
059      /**
060       * A code representing the {@link #minus(ValueExp, ValueExp)
061       * query to be used in serialization.
062       */
063      public static final int MINUS = 1;
064      
065      /**
066       * A code representing the {@link #times(ValueExp, ValueExp)
067       * query to be used in serialization.
068       */
069      public static final int TIMES = 2;
070    
071      /**
072       * A code representing the {@link #div(ValueExp, ValueExp)
073       * query to be used in serialization.
074       */
075      public static final int DIV = 3;
076    
077      /**
078       * A code representing the {@link #gt(ValueExp, ValueExp)
079       * query to be used in serialization.
080       */
081      public static final int GT = 0;
082    
083      /**
084       * A code representing the {@link #lt(ValueExp, ValueExp)
085       * query to be used in serialization.
086       */
087      public static final int LT = 1;
088    
089      /**
090       * A code representing the {@link #ge(ValueExp, ValueExp)
091       * query to be used in serialization.
092       */
093      public static final int GE = 2;
094    
095      /**
096       * A code representing the {@link #le(ValueExp, ValueExp)
097       * query to be used in serialization.
098       */
099      public static final int LE = 3;
100    
101      /**
102       * A code representing the {@link #eq(ValueExp, ValueExp)
103       * query to be used in serialization.
104       */
105      public static final int EQ = 4;
106    
107      /**
108       * Returns a query expression formed from the conjunction
109       * of the two supplied query expressions.
110       *
111       * @param q1 the first query expression.
112       * @param q2 the second query expression.
113       * @return a query expression representing q1 && q2.  This
114       *         will be serialized as the non-public class
115       *         {@link AndQueryExp}.
116       */
117      public static QueryExp and(QueryExp q1, QueryExp q2)
118      {
119        return new AndQueryExp(q1, q2);
120      }
121    
122      /**
123       * Returns a query expression which checks that an
124       * attribute value held by the specified
125       * {@link AttributeValueExp} contains the string
126       * specified by the given {@link StringValueExp}.
127       *
128       * @param attrib the attribute to match.
129       * @param string the substring to find.
130       * @return a query expression representing
131       *         <code>attrib.matches("*" + string + "*")</code>.
132       *         This will be serialized as the non-public class
133       *         {@link MatchQueryExp}.
134       */
135      public static QueryExp anySubString(AttributeValueExp attrib,
136                                          StringValueExp string)
137      {
138        return new MatchQueryExp(attrib, "*" + string.getValue() + "*");
139      }
140    
141      /**
142       * Returns a value expression for the value of the
143       * named attribute.  Evaluating this using an
144       * {@link ObjectName} involves an underlying call
145       * to {@link MBeanServer#getAttribute(ObjectName,String)}.
146       *
147       * @param name the name of the attribute.
148       * @return a value expression which returns the value
149       *         of the named attribute when applied.
150       */
151      public static AttributeValueExp attr(String name)
152      {
153        return new AttributeValueExp(name);
154      }
155    
156      /**
157       * Returns a value expression for the value of the
158       * named attribute from the specified class.  Evaluating
159       * this using an {@link ObjectName} involves an underlying call
160       * to both {@link MBeanServer#getObjectInstance(ObjectName)} and
161       * {@link MBeanServer#getAttribute(ObjectName,String)}.
162       *
163       * @param className the class containing the attribute.
164       * @param name the name of the attribute.
165       * @return a value expression which returns the value
166       *         of the named attribute when applied.
167       *         This will be serialized as the non-public class
168       *         {@link QualifiedAttributeValueExp}.
169       */
170      public static AttributeValueExp attr(String className,
171                                           String name)
172      {
173        return new QualifiedAttributeValueExp(className, name);
174      }
175    
176      /**
177       * Returns a query expression representing the constraint
178       * that the value, <code>v1</code>, lies between <code>v2</code>
179       * and <code>v3</code>.
180       *
181       * @param v1 the value to compare against the boundaries.
182       * @param v2 the lower boundary.
183       * @param v3 the upper boundary.
184       * @return a query expression representing a comparison
185       *         of <code>v1</code> against <code>v2</code>
186       *         and <code>v3</code>.  It returns true if
187       *         <code>v2 <= v1 <= v3</code>.  This
188       *         will be serialized as the non-public class
189       *         {@link BetweenQueryExp}.
190       */
191      public static QueryExp between(ValueExp v1, ValueExp v2,
192                                     ValueExp v3)
193      {
194        return new BetweenQueryExp(v1, v2, v3);
195      }
196    
197      /**
198       * Returns a value expression which evaluates to the name of
199       * the class of the bean when applied. Associating the expression
200       * with an {@link ObjectName} involves an underlying call
201       * to both {@link MBeanServer#getObjectInstance(ObjectName)}
202       * to obtain this information.
203       *
204       * @return a value expression which returns the class name
205       *         of the bean to which it is applied.
206       *         This will be serialized as the non-public class
207       *         {@link ClassAttributeValueExp}.
208       */
209      public static AttributeValueExp classattr()
210      {
211        return new ClassAttributeValueExp();
212      }
213    
214      /**
215       * Returns a value expression which evaluates to the result of
216       * dividing <code>v1</code> by <code>v2</code>. 
217       *
218       * @param v1 the left-hand operand.
219       * @param v2 the right-hand operand.
220       * @return a value expression which returns the result of
221       *         the division when applied.  This will be serialized
222       *         as the non-public class {@link BinaryOpValueExp}
223       *         with an operation of {@link #DIV}.
224       */
225      public static ValueExp div(ValueExp v1, ValueExp v2)
226      {
227        return new BinaryOpValueExp(DIV, v1, v2);
228      }
229    
230      /**
231       * Returns a query expression which evaluates to the result of
232       * comparing <code>v1</code> to <code>v2</code> for equality. 
233       *
234       * @param v1 the left-hand operand.
235       * @param v2 the right-hand operand.
236       * @return a value expression which returns the result of
237       *         the comparison when applied.  This will be serialized
238       *         as the non-public class {@link BinaryRelQueryExp}
239       *         with an operation of {@link #EQ}.
240       */
241      public static QueryExp eq(ValueExp v1, ValueExp v2)
242      {
243        return new BinaryRelQueryExp(EQ, v1, v2);
244      }
245    
246      /**
247       * Returns a query expression which checks that an
248       * attribute value held by the specified
249       * {@link AttributeValueExp} ends with the string
250       * specified by the given {@link StringValueExp}.
251       *
252       * @param attrib the attribute to match.
253       * @param string the substring to find.
254       * @return a query expression representing
255       *         <code>attrib.matches("*" + string)</code>.
256       *         This will be serialized as the non-public class
257       *         {@link MatchQueryExp}.
258       */
259      public static QueryExp finalSubString(AttributeValueExp attrib,
260                                            StringValueExp string)
261      {
262        return new MatchQueryExp(attrib, "*" + string.getValue());
263      }
264    
265      /**
266       * Returns a query expression which evaluates to the result of
267       * comparing <code>v1</code> to <code>v2</code> to see if
268       * <code>v1</code> is greater than or equal to <code>v2</code>. 
269       *
270       * @param v1 the left-hand operand.
271       * @param v2 the right-hand operand.
272       * @return a value expression which returns the result of
273       *         the comparison when applied.  This will be serialized
274       *         as the non-public class {@link BinaryRelQueryExp}
275       *         with an operation of {@link #GE}.
276       */
277      public static QueryExp geq(ValueExp v1, ValueExp v2)
278      {
279        return new BinaryRelQueryExp(GE, v1, v2);
280      }
281    
282      /**
283       * Returns a query expression which evaluates to the result of
284       * comparing <code>v1</code> to <code>v2</code> to see if
285       * <code>v1</code> is greater than <code>v2</code>. 
286       *
287       * @param v1 the left-hand operand.
288       * @param v2 the right-hand operand.
289       * @return a value expression which returns the result of
290       *         the comparison when applied.  This will be serialized
291       *         as the non-public class {@link BinaryRelQueryExp}
292       *         with an operation of {@link #GT}.
293       */
294      public static QueryExp gt(ValueExp v1, ValueExp v2)
295      {
296        return new BinaryRelQueryExp(GT, v1, v2);
297      }
298    
299      /**
300       * Returns a query expression representing the constraint
301       * that the value, <code>v</code>, is a member of the
302       * list, <code>vlist</code>.
303       *
304       * @param v the value to look for in the list.
305       * @param vlist the list of allowed values.
306       * @return a query expression representing a membership check
307       *         of <code>v</code> against the list, <code>vlist</code>.
308       *         This will be serialized as the non-public class
309       *         {@link InQueryExp}.
310       */
311      public static QueryExp in(ValueExp v, ValueExp[] vlist)
312      {
313        return new InQueryExp(v, vlist);
314      }
315    
316      /**
317       * Returns a query expression which checks that an
318       * attribute value held by the specified
319       * {@link AttributeValueExp} starts with the string
320       * specified by the given {@link StringValueExp}.
321       *
322       * @param attrib the attribute to match.
323       * @param string the substring to find.
324       * @return a query expression representing
325       *         <code>attrib.matches(string + "*")</code>.
326       *         This will be serialized as the non-public class
327       *         {@link MatchQueryExp}.
328       */
329      public static QueryExp initialSubString(AttributeValueExp attrib,
330                                              StringValueExp string)
331      {
332        return new MatchQueryExp(attrib, string.getValue() + "*");
333      }
334    
335      /**
336       * Returns a query expression which checks that a
337       * bean is an instance of the class specified
338       * by the given {@link StringValueExp}.  Associating the
339       * expression with an {@link ObjectName} involves an underlying
340       * call to {@link MBeanServer#isInstanceOf(ObjectName, String)}
341       * using the value of <code>((StringValueExp)
342       * className.apply(objectName)).getValue()</code> as the
343       * class name.
344       *
345       * @param className the name of the class which the bean
346       *                  should be an instance of.
347       * @return a query expression representing
348       *         the inheritance check.  This will be serialized
349       *         as the non-public class {@link InstanceOfQueryExp}.
350       * @since 1.6
351       */
352      public static QueryExp isInstanceOf(StringValueExp className)
353      {
354        return new InstanceOfQueryExp(className);
355      }
356    
357      /**
358       * Returns a query expression which evaluates to the result of
359       * comparing <code>v1</code> to <code>v2</code> to see if
360       * <code>v1</code> is less than or equal to <code>v2</code>. 
361       *
362       * @param v1 the left-hand operand.
363       * @param v2 the right-hand operand.
364       * @return a value expression which returns the result of
365       *         the comparison when applied.  This will be serialized
366       *         as the non-public class {@link BinaryRelQueryExp}
367       *         with an operation of {@link #LE}.
368       */
369      public static QueryExp leq(ValueExp v1, ValueExp v2)
370      {
371        return new BinaryRelQueryExp(LE, v1, v2);
372      }
373    
374      /**
375       * Returns a query expression which evaluates to the result of
376       * comparing <code>v1</code> to <code>v2</code> to see if
377       * <code>v1</code> is less than <code>v2</code>. 
378       *
379       * @param v1 the left-hand operand.
380       * @param v2 the right-hand operand.
381       * @return a value expression which returns the result of
382       *         the comparison when applied.  This will be serialized
383       *         as the non-public class {@link BinaryRelQueryExp}
384       *         with an operation of {@link #LT}.
385       */
386      public static QueryExp lt(ValueExp v1, ValueExp v2)
387      {
388        return new BinaryRelQueryExp(LT, v1, v2);
389      }
390    
391      /**
392       * <p>
393       * Returns a query expression which checks that an
394       * attribute value matches the pattern
395       * specified by the given {@link StringValueExp}.
396       * The pattern uses file-globbing syntax:
397       * </p>
398       * <ul>
399       * <li>'*' stands for any number of arbitrary characters.</li>
400       * <li>'?' stands for a single arbitrary characters.</li>
401       * <li>An expression within '[' and ']' specify a character
402       * class.</li>
403       * <ul>
404       * <li>A range of characters can be specified by separating
405       * the start and end character with '-'.</li>
406       * <li>The complement of the class can be obtained by using
407       * '!' as the first character of the class.</li>
408       * <li>'?', '*' and '[' can occur freely within the class. '-'
409       * may occur as the first or last character.  '!' may occur
410       * normally in any position other than the first.  ']' may occur
411       * as the first element of the class.</li>
412       * </ul>
413       * <li>'?', '*' and '[' may be escaped using a backslash
414       * character, '\'.</li>
415       * </ul>
416       *
417       * @param attrib the attribute to match.
418       * @param string the substring to find.
419       * @return a query expression representing the result of
420       *         matching the pattern against the evaluated
421       *         value of the attribute.  This will be serialized
422       *         as the non-public class {@link MatchQueryExp}.
423       */
424      public static QueryExp match(AttributeValueExp attrib,
425                                   StringValueExp string)
426      {
427        return new MatchQueryExp(attrib, string.getValue());
428      }
429    
430      /**
431       * Returns a value expression which evaluates to the result of
432       * subtracting <code>v2</code> from <code>v1</code>. 
433       *
434       * @param v1 the left-hand operand.
435       * @param v2 the right-hand operand.
436       * @return a value expression which returns the result of
437       *         the subtraction when applied.  This will be serialized
438       *         as the non-public class {@link BinaryOpValueExp}
439       *         with an operation of {@link #MINUS}.
440       */
441      public static ValueExp minus(ValueExp v1, ValueExp v2)
442      {
443        return new BinaryOpValueExp(MINUS, v1, v2);
444      }
445    
446      /**
447       * Returns a query expression representing the negation
448       * of the specified query expression.
449       *
450       * @param q the query to negate.
451       * @return a query expression representing the negation of
452       *         <code>q</code>.  This will be serialized as the
453       *         non-public class {@link NotQueryExp}.
454       */
455      public static QueryExp not(QueryExp q)
456      {
457        return new NotQueryExp(q);
458      }
459    
460      /**
461       * Returns a query expression formed from the disjunction
462       * of the two supplied query expressions.
463       *
464       * @param q1 the first query expression.
465       * @param q2 the second query expression.
466       * @return a query expression representing q1 || q2.  This
467       *         will be serialized as the non-public class
468       *         {@link OrQueryExp}.
469       */
470      public static QueryExp or(QueryExp q1, QueryExp q2)
471      {
472        return new OrQueryExp(q1, q2);
473      }
474    
475      /**
476       * Returns a value expression which evaluates to the result of
477       * adding <code>v1</code> to <code>v2</code>. 
478       *
479       * @param v1 the left-hand operand.
480       * @param v2 the right-hand operand.
481       * @return a value expression which returns the result of
482       *         the addition when applied.  This will be serialized
483       *         as the non-public class {@link BinaryOpValueExp}
484       *         with an operation of {@link #PLUS}.
485       */
486      public static ValueExp plus(ValueExp v1, ValueExp v2)
487      {
488        return new BinaryOpValueExp(PLUS, v1, v2);
489      }
490    
491      /**
492       * Returns a value expression which evaluates to the result of
493       * multiplying <code>v1</code> by <code>v2</code>. 
494       *
495       * @param v1 the left-hand operand.
496       * @param v2 the right-hand operand.
497       * @return a value expression which returns the result of
498       *         the multiplication when applied.  This will be serialized
499       *         as the non-public class {@link BinaryOpValueExp}
500       *         with an operation of {@link #TIMES}.
501       */
502      public static ValueExp times(ValueExp v1, ValueExp v2)
503      {
504        return new BinaryOpValueExp(TIMES, v1, v2);
505      }
506    
507      /**
508       * Returns a value expression wrapping the specified value. 
509       *
510       * @param val the boolean value to wrap.
511       * @return a value expression wrapping <code>val</code>.  This
512       *         will be serialized as the non-public class
513       *         {@link BooleanValueExp}.
514       */
515      public static ValueExp value(boolean val)
516      {
517        return new BooleanValueExp(val);
518      }
519    
520      /**
521       * Returns a value expression wrapping the specified value. 
522       *
523       * @param val the double value to wrap.
524       * @return a value expression wrapping <code>val</code>.  This
525       *         will be serialized as the non-public class
526       *         {@link NumericValueExp}.
527       */
528      public static ValueExp value(double val)
529      {
530        return new NumericValueExp(val);
531      }
532    
533      /**
534       * Returns a value expression wrapping the specified value. 
535       *
536       * @param val the float value to wrap.
537       * @return a value expression wrapping <code>val</code>.  This
538       *         will be serialized as the non-public class
539       *         {@link NumericValueExp}.
540       */
541      public static ValueExp value(float val)
542      {
543        return new NumericValueExp(val);
544      }
545    
546      /**
547       * Returns a value expression wrapping the specified value. 
548       *
549       * @param val the integer value to wrap.
550       * @return a value expression wrapping <code>val</code>.  This
551       *         will be serialized as the non-public class
552       *         {@link NumericValueExp}.
553       */
554      public static ValueExp value(int val)
555      {
556        return new NumericValueExp(val);
557      }
558    
559      /**
560       * Returns a value expression wrapping the specified value. 
561       *
562       * @param val the long value to wrap.
563       * @return a value expression wrapping <code>val</code>.  This
564       *         will be serialized as the non-public class
565       *         {@link NumericValueExp}.
566       */
567      public static ValueExp value(long val)
568      {
569        return new NumericValueExp(val);
570      }
571    
572      /**
573       * Returns a value expression wrapping the specified value. 
574       *
575       * @param val the {@link Number} value to wrap.
576       * @return a value expression wrapping <code>val</code>.  This
577       *         will be serialized as the non-public class
578       *         {@link NumericValueExp}.
579       */
580      public static ValueExp value(Number val)
581      {
582        return new NumericValueExp(val);
583      }
584    
585      /**
586       * Returns a value expression wrapping the specified string. 
587       *
588       * @param val the {@link String} to wrap.
589       * @return a {@link StringValueExp} wrapping <code>val</code>.
590       */
591      public static StringValueExp value(String val)
592      {
593        return new StringValueExp(val);
594      }
595    
596      /**
597       * Representation of the conjunction formed using
598       * {@link #and(QueryExp, QueryExp).
599       *
600       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
601       * @since 1.5
602       */
603      private static final class AndQueryExp
604        extends QueryEval
605        implements QueryExp
606      {
607    
608        /**
609         * Compatible with JDK 1.6
610         */
611        private static final long serialVersionUID = -1081892073854801359L;
612        
613        /**
614         * The first operand.
615         */
616        private QueryExp exp1;
617    
618        /**
619         * The second operand.
620         */
621        private QueryExp exp2;
622    
623        /**
624         * Constructs a new {@link AndQueryExp} using
625         * the two specified operands.
626         *
627         * @param exp1 the first query expression.
628         * @param exp2 the second query expression.
629         */
630        public AndQueryExp(QueryExp exp1, QueryExp exp2)
631        {
632          this.exp1 = exp1;
633          this.exp2 = exp2;
634        }
635    
636        /**
637         * Returns the conjunction of the two query
638         * expressions.
639         *
640         * @param name the {@link ObjectName} to apply
641         *             the query to.
642         * @return the conjunction of applying the name
643         *         to both operands.
644         * @throws BadStringOperationException if an invalid string
645         *                                     operation is used by
646         *                                     the query.
647         * @throws BadBinaryOpValueExpException if an invalid expression
648         *                                      is used by the query.
649         * @throws BadAttributeValueExpException if an invalid attribute
650         *                                       is used by the query.
651         * @throws InvalidApplicationException if the query is applied
652         *                                     to the wrong type of bean.
653         */
654        public boolean apply(ObjectName name)
655          throws BadStringOperationException, BadBinaryOpValueExpException,
656                 BadAttributeValueExpException, InvalidApplicationException
657        {
658          return exp1.apply(name) && exp2.apply(name);
659        }
660    
661      }
662    
663      /**
664       * Representation of a query that matches an
665       * attribute's value against a given pattern.
666       *
667       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
668       * @since 1.5
669       */
670      private static final class MatchQueryExp
671        extends QueryEval
672        implements QueryExp
673      {
674    
675        /**
676         * Compatible with JDK 1.6
677         */
678        private static final long serialVersionUID = -7156603696948215014L;
679        
680        /**
681         * The attribute to match against.
682         */
683        private AttributeValueExp exp;
684    
685        /**
686         * The pattern to be matched.
687         */
688        private String pattern;
689    
690        /**
691         * Constructs a new {@link MatchQueryExp} using
692         * the specified attribute value and pattern.
693         *
694         * @param exp the attribute value expression.
695         * @param pattern the pattern.
696         */
697        public MatchQueryExp(AttributeValueExp exp,
698                             String pattern)
699        {
700          this.exp = exp;
701          this.pattern = pattern;
702        }
703    
704        /**
705         * Returns the result of matching the attribute
706         * value against the pattern.
707         *
708         * @param name the {@link ObjectName} to apply
709         *             the query to.
710         * @return the result of the match.
711         * @throws BadStringOperationException if an invalid string
712         *                                     operation is used by
713         *                                     the query.
714         * @throws BadBinaryOpValueExpException if an invalid expression
715         *                                      is used by the query.
716         * @throws BadAttributeValueExpException if an invalid attribute
717         *                                       is used by the query.
718         * @throws InvalidApplicationException if the query is applied
719         *                                     to the wrong type of bean.
720         */
721        public boolean apply(ObjectName name)
722          throws BadStringOperationException, BadBinaryOpValueExpException,
723                 BadAttributeValueExpException, InvalidApplicationException
724        {
725          String val = ((StringValueExp) exp.apply(name)).getValue();
726          int valPos = 0;
727          int fallback = -1;
728          int fallbackP = -1;
729          boolean backslash = false;
730          for (int a = 0; a < pattern.length(); ++a)
731            {
732              boolean matched = false;
733              int next = pattern.codePointAt(a);
734              if (!backslash)
735                {
736                  if (next == '?' && valPos < val.length())
737                    {
738                      ++valPos;
739                      matched = true;
740                    }
741                  else if (next == '*')
742                    {
743                      fallback = valPos;
744                      fallbackP = a;
745                      matched = true;
746                    }
747                  else if (next == '[' && valPos < val.length()) 
748                    {
749                      boolean negated = false;
750                      int b = a + 1;
751                      int classChar = pattern.codePointAt(b);
752                      do
753                        {
754                          if (classChar == '!' && b == a + 1)
755                            negated = true;
756                          else if (pattern.codePointAt(b + 1) == '-' &&
757                                   pattern.codePointAt(b + 2) != ']')
758                            {
759                              if (classChar > pattern.codePointAt(b + 2))
760                                throw new BadStringOperationException("Invalid range: " +
761                                                                      classChar + " to " +
762                                                                      pattern.codePointAt(b+2));
763                              for (int c = classChar; c <= pattern.codePointAt(b+2); ++c)
764                                if (val.codePointAt(valPos) == c)
765                                  matched = true;
766                              b = b + 2;
767                            }
768                          else if (val.codePointAt(valPos) == classChar)
769                            matched = true;
770                          ++b;
771                          classChar = pattern.codePointAt(b);
772                        } while (classChar != ']');
773                      if (negated)
774                        matched = !matched;
775                      ++valPos;
776                      a = b;
777                    }
778                  else if (next == '\\')
779                    backslash = true;
780                  else if (valPos < val.length() && next == val.codePointAt(valPos))
781                    {
782                      matched = true;
783                      ++valPos;
784                    }
785                }
786              else
787                {
788                  backslash = false;
789                  if (valPos < val.length() && next == val.codePointAt(valPos))
790                    {
791                      matched = true;
792                      ++valPos;
793                    }       
794                }
795              if (!matched)
796                if (fallback != -1)
797                  {
798                    ++fallback;
799                    valPos = fallback;
800                    a = fallbackP;
801                    if (valPos == val.length())
802                      return false;
803                    continue;
804                  }
805                else
806                  return false;
807            }
808          return true;
809        }
810      }
811    
812      /**
813       * Representation of the retrieval of an attribute
814       * value from a certain class for {@link #attr(String,String)}.
815       *
816       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
817       * @since 1.5
818       */
819      private static final class QualifiedAttributeValueExp
820        extends AttributeValueExp
821      {
822    
823        /**
824         * Compatible with JDK 1.6
825         */
826        private static final long serialVersionUID = 8832517277410933254L;
827    
828        /**
829         * The name of the class from which the attribute is taken.
830         */
831        private String className;
832    
833        /**
834         * Constructs a new {@link QualifiedAttributeValueExp} using
835         * the specified class name and attribute name.
836         *
837         * @param className the class name.
838         * @param name the attribute name.
839         */
840        public QualifiedAttributeValueExp(String className, String name)
841        {
842          super(name);
843          this.className = className;
844        }
845    
846        /**
847         * Applies the {@link AttributeValueExp} to the specified
848         * management bean by checking that the attribute will be
849         * obtained from the correct class (by a class to
850         * {@link MBeanServer#getObjectInstance(ObjectName)} and
851         * then obtaining the attribute value from the
852         * {@link MBeanServer}, using it to create a
853         * {@link StringValueExp}.
854         *
855         * @param name the {@link ObjectName} of the bean to obtain
856         *             the value from.
857         * @return a {@link StringValueExp} containing the result.
858         * @throws BadStringOperationException if an invalid string
859         *                                     operation is used by
860         *                                     the value expression.
861         * @throws BadBinaryOpValueExpException if an invalid expression
862         *                                      is used by the value expression.
863         * @throws BadAttributeValueExpException if an invalid attribute
864         *                                       is used by the value expression.
865         * @throws InvalidApplicationException if the value expression is applied
866         *                                     to the wrong type of bean.
867         */
868        public ValueExp apply(ObjectName name)
869          throws BadStringOperationException, BadBinaryOpValueExpException,
870                 BadAttributeValueExpException, InvalidApplicationException
871        {
872          try
873            {
874              if (!(QueryEval.getMBeanServer().getObjectInstance(name).getClassName().equals(className)))
875                throw new BadAttributeValueExpException("The value is not from " +
876                                                        "the correct class.");
877            }
878          catch (InstanceNotFoundException e)
879            {
880              throw (BadAttributeValueExpException)
881                new BadAttributeValueExpException("The named bean is not registered.").initCause(e);
882            }
883          return super.apply(name);
884        }
885     
886      }
887    
888      /**
889       * Representation of the comparison of a value with
890       * a pair of bounds formed using
891       * {@link #between(ValueExp, ValueExp, ValueExp).
892       *
893       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
894       * @since 1.5
895       */
896      private static final class BetweenQueryExp
897        extends QueryEval
898        implements QueryExp
899      {
900    
901        /**
902         * Compatible with JDK 1.6
903         */
904        private static final long serialVersionUID = -2933597532866307444L;
905        
906        /**
907         * The value to compare.
908         */
909        private ValueExp exp1;
910    
911        /**
912         * The lower boundary.
913         */
914        private ValueExp exp2;
915    
916        /**
917         * The upper boundary.
918         */
919        private ValueExp exp3;
920    
921        /**
922         * Constructs a new {@link BetweenQueryExp} using
923         * the specified comparison value and the given
924         * bounds.
925         *
926         * @param exp1 the value to compare.
927         * @param exp2 the lower bound.
928         * @param exp3 the upper bound.
929         */
930        public BetweenQueryExp(ValueExp exp1, ValueExp exp2,
931                               ValueExp exp3)
932        {
933          this.exp1 = exp1;
934          this.exp2 = exp2;
935          this.exp3 = exp3;
936        }
937    
938        /**
939         * Returns the result of the comparison between
940         * the value and the two bounds.
941         *
942         * @param name the {@link ObjectName} to apply
943         *             the query to.
944         * @return the result of the comparison.
945         * @throws BadStringOperationException if an invalid string
946         *                                     operation is used by
947         *                                     the query.
948         * @throws BadBinaryOpValueExpException if an invalid expression
949         *                                      is used by the query.
950         * @throws BadAttributeValueExpException if an invalid attribute
951         *                                       is used by the query.
952         * @throws InvalidApplicationException if the query is applied
953         *                                     to the wrong type of bean.
954         */
955        public boolean apply(ObjectName name)
956          throws BadStringOperationException, BadBinaryOpValueExpException,
957                 BadAttributeValueExpException, InvalidApplicationException
958        {
959          String v1 = exp1.apply(name).toString();
960          String v2 = exp2.apply(name).toString();
961          String v3 = exp3.apply(name).toString();
962          return v1.compareTo(v2) >= 0 && v1.compareTo(v3) <= 0;
963        }
964    
965      }
966    
967      /**
968       * Representation of the retrieval of the name of
969       * a bean's class for {@link #classattr()}.
970       *
971       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
972       * @since 1.5
973       */
974      private static final class ClassAttributeValueExp
975        extends AttributeValueExp
976      {
977    
978        /**
979         * Compatible with JDK 1.6
980         */
981        private static final long serialVersionUID = -1081892073854801359L;
982    
983        /**
984         * Obtains the name of the specified bean's class using a call
985         * to {@link MBeanServer#getObjectInstance(ObjectName)}.
986         *
987         * @param name the {@link ObjectName} of the bean to obtain
988         *             the class name from.
989         * @return a {@link StringValueExp} containing the result.
990         * @throws BadStringOperationException if an invalid string
991         *                                     operation is used by
992         *                                     the value expression.
993         * @throws BadBinaryOpValueExpException if an invalid expression
994         *                                      is used by the value expression.
995         * @throws BadAttributeValueExpException if an invalid attribute
996         *                                       is used by the value expression.
997         * @throws InvalidApplicationException if the value expression is applied
998         *                                     to the wrong type of bean.
999         */
1000        public ValueExp apply(ObjectName name)
1001          throws BadStringOperationException, BadBinaryOpValueExpException,
1002                 BadAttributeValueExpException, InvalidApplicationException
1003        {
1004          try
1005            {
1006              return new StringValueExp(QueryEval.getMBeanServer().getObjectInstance(name).getClassName());
1007            }
1008          catch (InstanceNotFoundException e)
1009            {
1010              throw (BadAttributeValueExpException)
1011                new BadAttributeValueExpException("The named bean is not registered.").initCause(e);
1012            }
1013        }
1014     
1015      }
1016    
1017      /**
1018       * Representation of a binary operation formed using
1019       * {@link #div(ValueExp, ValueExp), {@link #plus(ValueExp,ValueExp)},
1020       * {@link #minus(ValueExp, ValueExp) or
1021       * {@link #times(ValueExp, ValueExp)}.
1022       *
1023       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1024       * @since 1.5
1025       */
1026      private static final class BinaryOpValueExp
1027        extends QueryEval
1028        implements ValueExp
1029      {
1030    
1031        /**
1032         * Compatible with JDK 1.6
1033         */
1034        private static final long serialVersionUID = 1216286847881456786L;
1035        
1036        /**
1037         * The operation to perform.
1038         */
1039        private int op;
1040    
1041        /**
1042         * The left-hand operand.
1043         */
1044        private ValueExp exp1;
1045    
1046        /**
1047         * The right-hand operand.
1048         */
1049        private ValueExp exp2;
1050    
1051        /**
1052         * Constructs a new {@link BinaryOpValueExp} using
1053         * the specified operation and the two values supplied.
1054         *
1055         * @param op the operation to perform.
1056         * @param exp1 the left-hand operand.
1057         * @param exp2 the right-hand operand.
1058         */
1059        public BinaryOpValueExp(int op, ValueExp exp1, ValueExp exp2)
1060        {
1061          this.op = op;
1062          this.exp1 = exp1;
1063          this.exp2 = exp2;
1064        }
1065    
1066        /**
1067         * Returns the result of performing the operation on
1068         * <code>exp1</code> and <code>exp2</code>.
1069         *
1070         * @param name the {@link ObjectName} to apply
1071         *             the query to.
1072         * @return the result of the operation.
1073         * @throws BadStringOperationException if an invalid string
1074         *                                     operation is used by
1075         *                                     the query.
1076         * @throws BadBinaryOpValueExpException if an invalid expression
1077         *                                      is used by the query.
1078         * @throws BadAttributeValueExpException if an invalid attribute
1079         *                                       is used by the query.
1080         * @throws InvalidApplicationException if the query is applied
1081         *                                     to the wrong type of bean.
1082         */
1083        public ValueExp apply(ObjectName name)
1084          throws BadStringOperationException, BadBinaryOpValueExpException,
1085                 BadAttributeValueExpException, InvalidApplicationException
1086        {
1087          NumericValueExp v1 = (NumericValueExp) exp1.apply(name);
1088          NumericValueExp v2 = (NumericValueExp) exp2.apply(name);
1089          switch (op)
1090            {
1091            case PLUS:
1092              return v1.plus(v2);
1093            case MINUS:
1094              return v1.minus(v2);
1095            case TIMES:
1096              return v1.times(v2);
1097            case DIV:
1098              return v1.div(v2);
1099            default:
1100              throw new BadBinaryOpValueExpException(this);
1101            }
1102        }
1103    
1104        /**
1105         * Returns a textual representation of the operation.
1106         *
1107         * @return a textual version of the operation.
1108         */
1109        public String toString()
1110        {
1111          String opS;
1112          switch (op)
1113            {
1114            case PLUS:
1115              opS = "+";
1116              break;
1117            case MINUS:
1118              opS = "-";
1119              break;
1120            case TIMES:
1121              opS = "x";
1122              break;
1123            case DIV:
1124              opS = "/";
1125              break;
1126            default:
1127              opS = "?";
1128            }
1129          return exp1 + " " + opS + " " + exp2;
1130        }
1131      }
1132    
1133      /**
1134       * Representation of a binary operation formed using
1135       * {@link #eq(ValueExp, ValueExp), {@link #geq(ValueExp, ValueExp)},
1136       * {@link #leq(ValueExp, ValueExp), {@link #gt(ValueExp, ValueExp)}
1137       * or {@link #lt(ValueExp, ValueExp)}.
1138       *
1139       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1140       * @since 1.5
1141       */
1142      private static final class BinaryRelQueryExp
1143        extends QueryEval
1144        implements QueryExp
1145      {
1146    
1147        /**
1148         * Compatible with JDK 1.6
1149         */
1150        private static final long serialVersionUID = -5690656271650491000L;
1151        
1152        /**
1153         * The operation to perform.
1154         */
1155        private int relOp;
1156    
1157        /**
1158         * The left-hand operand.
1159         */
1160        private ValueExp exp1;
1161    
1162        /**
1163         * The right-hand operand.
1164         */
1165        private ValueExp exp2;
1166    
1167        /**
1168         * Constructs a new {@link BinaryRelQueryExp} using
1169         * the specified operation and the two values supplied.
1170         *
1171         * @param relOp the operation to perform.
1172         * @param exp1 the left-hand operand.
1173         * @param exp2 the right-hand operand.
1174         */
1175        public BinaryRelQueryExp(int relOp, ValueExp exp1, ValueExp exp2)
1176        {
1177          this.relOp = relOp;
1178          this.exp1 = exp1;
1179          this.exp2 = exp2;
1180        }
1181    
1182        /**
1183         * Returns the result of performing the operation on
1184         * <code>exp1</code> and <code>exp2</code>.
1185         *
1186         * @param name the {@link ObjectName} to apply
1187         *             the query to.
1188         * @return the result of the comparison.
1189         * @throws BadStringOperationException if an invalid string
1190         *                                     operation is used by
1191         *                                     the query.
1192         * @throws BadBinaryOpValueExpException if an invalid expression
1193         *                                      is used by the query.
1194         * @throws BadAttributeValueExpException if an invalid attribute
1195         *                                       is used by the query.
1196         * @throws InvalidApplicationException if the query is applied
1197         *                                     to the wrong type of bean.
1198         */
1199        public boolean apply(ObjectName name)
1200          throws BadStringOperationException, BadBinaryOpValueExpException,
1201                 BadAttributeValueExpException, InvalidApplicationException
1202        {
1203          String v1 = exp1.apply(name).toString();
1204          String v2 = exp2.apply(name).toString();
1205          switch (relOp)
1206            {
1207            case EQ:
1208              return v1.equals(v2);
1209            case GT:
1210              return v1.compareTo(v2) > 0;
1211            case GE:
1212              return v1.compareTo(v2) >= 0;
1213            case LE:
1214              return v1.compareTo(v2) <= 0;
1215            case LT:
1216              return v1.compareTo(v2) < 0;
1217            default:
1218              throw new BadStringOperationException("Invalid operator: " + relOp);
1219            }
1220        }
1221    
1222        /**
1223         * Returns a textual representation of the operation.
1224         *
1225         * @return a textual version of the operation.
1226         */
1227        public String toString()
1228        {
1229          String op;
1230          switch (relOp)
1231            {
1232            case EQ:
1233              op = "=";
1234              break;
1235            case GT:
1236              op = ">";
1237              break;
1238            case GE:
1239              op = ">=";
1240              break;
1241            case LE:
1242              op = "<=";
1243              break;
1244            case LT:
1245              op = "<";
1246              break;
1247            default:
1248              op = "?";
1249            }
1250          return exp1 + " " + op + " " + exp2;
1251        }
1252      }
1253    
1254      /**
1255       * Representation of the comparison of a value with
1256       * the members of a list formed using
1257       * {@link #in(ValueExp, ValueExp[]).
1258       *
1259       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1260       * @since 1.5
1261       */
1262      private static final class InQueryExp
1263        extends QueryEval
1264        implements QueryExp
1265      {
1266    
1267        /**
1268         * Compatible with JDK 1.6
1269         */
1270        private static final long serialVersionUID = -5801329450358952434L;
1271        
1272        /**
1273         * The value to look for.
1274         */
1275        private ValueExp val;
1276    
1277        /**
1278         * The array to search.
1279         */
1280        private ValueExp[] valueList;
1281    
1282        /**
1283         * Constructs a new {@link InQueryExp} using
1284         * the specified comparison value and the given
1285         * list.
1286         *
1287         * @param val the value to compare.
1288         * @param valueList the list of values.
1289         */
1290        public InQueryExp(ValueExp val, ValueExp[] valueList)
1291        {
1292          this.val = val;
1293          this.valueList = valueList;
1294        }
1295    
1296        /**
1297         * Returns the result of the comparison between
1298         * the value and the list of allowed values.
1299         *
1300         * @param name the {@link ObjectName} to apply
1301         *             the query to.
1302         * @return the result of the comparison.
1303         * @throws BadStringOperationException if an invalid string
1304         *                                     operation is used by
1305         *                                     the query.
1306         * @throws BadBinaryOpValueExpException if an invalid expression
1307         *                                      is used by the query.
1308         * @throws BadAttributeValueExpException if an invalid attribute
1309         *                                       is used by the query.
1310         * @throws InvalidApplicationException if the query is applied
1311         *                                     to the wrong type of bean.
1312         */
1313        public boolean apply(ObjectName name)
1314          throws BadStringOperationException, BadBinaryOpValueExpException,
1315                 BadAttributeValueExpException, InvalidApplicationException
1316        {
1317          String v = val.apply(name).toString();
1318          for (ValueExp vl : valueList)
1319            if (v.equals(vl.apply(name).toString()))
1320              return true;
1321          return false;
1322        }
1323    
1324      }
1325    
1326      /**
1327       * Representation of the inheritance check on a
1328       * bean for {@link #isInstanceOf(StringValueExp)}.
1329       *
1330       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1331       * @since 1.6
1332       */
1333      private static final class InstanceOfQueryExp
1334        extends QueryEval
1335        implements QueryExp
1336      {
1337    
1338        /**
1339         * Compatible with JDK 1.6
1340         */
1341        private static final long serialVersionUID = -1081892073854801359L;
1342    
1343        /**
1344         * The name of the class from which the attribute is taken.
1345         */
1346        private StringValueExp classNameValue;
1347    
1348        /**
1349         * Constructs a new {@link InstanceOfQueryExp} using
1350         * the specified class name.
1351         *
1352         * @param classNameValue the class name.
1353         */
1354        public InstanceOfQueryExp(StringValueExp classNameValue)
1355        {
1356          this.classNameValue = classNameValue;
1357        }
1358    
1359        /**
1360         * Checks that the bean specified by the supplied
1361         * {@link ObjectName} is of the correct class 
1362         * using {@link MBeanServer#isInstanceOf(ObjectName,String)}.
1363         * where the string is obtained by evaluating
1364         * <code>classNameValue</code>.
1365         *
1366         * @param name the {@link ObjectName} of the bean to obtain
1367         *             the value from.
1368         * @return true if the bean is an instance of the class.
1369         * @throws BadStringOperationException if an invalid string
1370         *                                     operation is used by
1371         *                                     the value expression.
1372         * @throws BadBinaryOpValueExpException if an invalid expression
1373         *                                      is used by the value expression.
1374         * @throws BadAttributeValueExpException if an invalid attribute
1375         *                                       is used by the value expression.
1376         * @throws InvalidApplicationException if the value expression is applied
1377         *                                     to the wrong type of bean.
1378         */
1379        public boolean apply(ObjectName name)
1380          throws BadStringOperationException, BadBinaryOpValueExpException,
1381                 BadAttributeValueExpException, InvalidApplicationException
1382        {
1383          try
1384            {
1385              String className = ((StringValueExp)
1386                                  classNameValue.apply(name)).getValue();
1387              return QueryEval.getMBeanServer().isInstanceOf(name, className);
1388            }
1389          catch (InstanceNotFoundException e)
1390            {
1391              throw (BadAttributeValueExpException)
1392                new BadAttributeValueExpException("The named bean is not registered.").initCause(e);
1393            }
1394        }
1395     
1396      }
1397    
1398      /**
1399       * Representation of the negation of a query formed using
1400       * {@link #not(QueryExp).
1401       *
1402       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1403       * @since 1.5
1404       */
1405      private static final class NotQueryExp
1406        extends QueryEval
1407        implements QueryExp
1408      {
1409    
1410        /**
1411         * Compatible with JDK 1.6
1412         */
1413        private static final long serialVersionUID = 5269643775896723397L;
1414        
1415        /**
1416         * The expression to negate.
1417         */
1418        private QueryExp exp;
1419    
1420        /**
1421         * Constructs a new {@link NotQueryExp} using
1422         * the specified query expression.
1423         *
1424         * @param exp the expression to negate.
1425         */
1426        public NotQueryExp(QueryExp exp)
1427        {
1428          this.exp = exp;
1429        }
1430    
1431        /**
1432         * Returns the result of the negation.
1433         *
1434         * @param name the {@link ObjectName} to apply
1435         *             the query to.
1436         * @return the result of the negation.
1437         * @throws BadStringOperationException if an invalid string
1438         *                                     operation is used by
1439         *                                     the query.
1440         * @throws BadBinaryOpValueExpException if an invalid expression
1441         *                                      is used by the query.
1442         * @throws BadAttributeValueExpException if an invalid attribute
1443         *                                       is used by the query.
1444         * @throws InvalidApplicationException if the query is applied
1445         *                                     to the wrong type of bean.
1446         */
1447        public boolean apply(ObjectName name)
1448          throws BadStringOperationException, BadBinaryOpValueExpException,
1449                 BadAttributeValueExpException, InvalidApplicationException
1450        {
1451          return !(exp.apply(name));
1452        }
1453    
1454      }
1455    
1456      /**
1457       * Representation of the disjunction formed using
1458       * {@link #or(QueryExp, QueryExp).
1459       *
1460       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1461       * @since 1.5
1462       */
1463      private static final class OrQueryExp
1464        extends QueryEval
1465        implements QueryExp
1466      {
1467    
1468        /**
1469         * Compatible with JDK 1.6
1470         */
1471        private static final long serialVersionUID = 2962973084421716523L;
1472        
1473        /**
1474         * The first operand.
1475         */
1476        private QueryExp exp1;
1477    
1478        /**
1479         * The second operand.
1480         */
1481        private QueryExp exp2;
1482    
1483        /**
1484         * Constructs a new {@link OrQueryExp} using
1485         * the two specified operands.
1486         *
1487         * @param exp1 the first query expression.
1488         * @param exp2 the second query expression.
1489         */
1490        public OrQueryExp(QueryExp exp1, QueryExp exp2)
1491        {
1492          this.exp1 = exp1;
1493          this.exp2 = exp2;
1494        }
1495    
1496        /**
1497         * Returns the disjunction of the two query
1498         * expressions.
1499         *
1500         * @param name the {@link ObjectName} to apply
1501         *             the query to.
1502         * @return the disjunction of applying the name
1503         *         to both operands.
1504         * @throws BadStringOperationException if an invalid string
1505         *                                     operation is used by
1506         *                                     the query.
1507         * @throws BadBinaryOpValueExpException if an invalid expression
1508         *                                      is used by the query.
1509         * @throws BadAttributeValueExpException if an invalid attribute
1510         *                                       is used by the query.
1511         * @throws InvalidApplicationException if the query is applied
1512         *                                     to the wrong type of bean.
1513         */
1514        public boolean apply(ObjectName name)
1515          throws BadStringOperationException, BadBinaryOpValueExpException,
1516                 BadAttributeValueExpException, InvalidApplicationException
1517        {
1518          return exp1.apply(name) || exp2.apply(name);
1519        }
1520    
1521      }
1522    
1523      /**
1524       * Representation of a boolean being used as an argument
1525       * to a relational constraint, formed using
1526       * {@link #value(boolean)}.
1527       *
1528       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1529       * @since 1.5
1530       */
1531      private static final class BooleanValueExp
1532        extends QueryEval
1533        implements ValueExp
1534      {
1535    
1536        /**
1537         * Compatible with JDK 1.6
1538         */
1539        private static final long serialVersionUID = 7754922052666594581L;
1540    
1541        /**
1542         * The boolean value.
1543         */
1544        private boolean val;
1545        
1546        /**
1547         * Constructs a new {@link BooleanValueExp} using the
1548         * specified value.
1549         *
1550         * @param val the boolean value used for this expression.
1551         */
1552        public BooleanValueExp(boolean val)
1553        {
1554          this.val = val;
1555        }
1556    
1557        /**
1558         * Applies the {@link BooleanValueExp} to the specified
1559         * management bean by simply returning the value.
1560         *
1561         * @param name the {@link ObjectName} of the bean.
1562         * @return the {@link BooleanValueExp} itself.
1563         * @throws BadStringOperationException if an invalid string
1564         *                                     operation is used by
1565         *                                     the value expression.
1566         * @throws BadBinaryOpValueExpException if an invalid expression
1567         *                                      is used by the value expression.
1568         * @throws BadAttributeValueExpException if an invalid attribute
1569         *                                       is used by the value expression.
1570         * @throws InvalidApplicationException if the value expression is applied
1571         *                                     to the wrong type of bean.
1572         */
1573        public ValueExp apply(ObjectName name)
1574          throws BadStringOperationException, BadBinaryOpValueExpException,
1575                 BadAttributeValueExpException, InvalidApplicationException
1576        {
1577          return this;
1578        }
1579        
1580        /**
1581         * Returns the value as a string.
1582         *
1583         * @return the value in textual form.
1584         */
1585        public String toString()
1586        {
1587          return Boolean.toString(val);
1588        }
1589    
1590      }
1591    
1592      /**
1593       * Representation of a number being used as an argument
1594       * to a relational constraint, formed using
1595       * {@link #value(double)}, {@link #value(float)},
1596       * {@link #value(int)}, {@link #value(long)} or
1597       * {@link #value(Number)}.
1598       *
1599       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1600       * @since 1.5
1601       */
1602      private static final class NumericValueExp
1603        extends QueryEval
1604        implements ValueExp
1605      {
1606    
1607        /**
1608         * Compatible with JDK 1.6
1609         */
1610        private static final long serialVersionUID = -4679739485102359104L;
1611    
1612        /**
1613         * The numeric value.
1614         */
1615        private Number val;
1616        
1617        /**
1618         * Constructs a new {@link NumericValueExp} using the
1619         * specified value.
1620         *
1621         * @param val the numeric value used for this expression.
1622         */
1623        public NumericValueExp(Number val)
1624        {
1625          this.val = val;
1626        }
1627    
1628        /**
1629         * Applies the {@link NumericValueExp} to the specified
1630         * management bean by simply returning the value.
1631         *
1632         * @param name the {@link ObjectName} of the bean.
1633         * @return the {@link NumericValueExp} itself.
1634         * @throws BadStringOperationException if an invalid string
1635         *                                     operation is used by
1636         *                                     the value expression.
1637         * @throws BadBinaryOpValueExpException if an invalid expression
1638         *                                      is used by the value expression.
1639         * @throws BadAttributeValueExpException if an invalid attribute
1640         *                                       is used by the value expression.
1641         * @throws InvalidApplicationException if the value expression is applied
1642         *                                     to the wrong type of bean.
1643         */
1644        public ValueExp apply(ObjectName name)
1645          throws BadStringOperationException, BadBinaryOpValueExpException,
1646                 BadAttributeValueExpException, InvalidApplicationException
1647        {
1648          return this;
1649        }
1650        
1651        /**
1652         * Returns the value.
1653         */
1654        public Number getValue()
1655        {
1656          return val;
1657        }
1658    
1659        /**
1660         * Returns the value as a string.
1661         *
1662         * @return the value in textual form.
1663         */
1664        public String toString()
1665        {
1666          return val.toString();
1667        }
1668    
1669        /**
1670         * Return the result of adding the specified
1671         * {@link NumericValueExp} to this one.
1672         *
1673         * @param o the value to add.
1674         * @return the result of the addition.
1675         */
1676        public NumericValueExp plus(NumericValueExp o)
1677        {
1678          Number v = o.getValue();
1679          if (val instanceof Double)
1680            {
1681              double d = val.doubleValue();
1682              if (v instanceof Double)
1683                return new NumericValueExp(d + v.doubleValue());
1684              else if (v instanceof Float)
1685                return new NumericValueExp(d + v.floatValue());
1686              else if (v instanceof Long)
1687                return new NumericValueExp(d + v.longValue());
1688              else
1689                return new NumericValueExp(d + v.intValue());
1690            }
1691          else if (val instanceof Float)
1692            {
1693              float f = val.floatValue();
1694              if (v instanceof Double)
1695                return new NumericValueExp(f + v.doubleValue());
1696              else if (v instanceof Float)
1697                return new NumericValueExp(f + v.floatValue());
1698              else if (v instanceof Long)
1699                return new NumericValueExp(f + v.longValue());
1700              else
1701                return new NumericValueExp(f + v.intValue());
1702            }
1703          else if (val instanceof Long)
1704            {
1705              long l = val.longValue();
1706              if (v instanceof Double)
1707                return new NumericValueExp(l + v.doubleValue());
1708              else if (v instanceof Float)
1709                return new NumericValueExp(l + v.floatValue());
1710              else if (v instanceof Long)
1711                return new NumericValueExp(l + v.longValue());
1712              else
1713                return new NumericValueExp(l + v.intValue());
1714            }
1715          int i = val.intValue();
1716          if (v instanceof Double)
1717            return new NumericValueExp(i + v.doubleValue());
1718          else if (v instanceof Float)
1719            return new NumericValueExp(i + v.floatValue());
1720          else if (v instanceof Long)
1721            return new NumericValueExp(i + v.longValue());
1722          else
1723            return new NumericValueExp(i + v.intValue());   
1724        }   
1725    
1726        /**
1727         * Return New NumericValueExp(the result of subtracting the specified
1728         * {@link NumericValueExp} from this one.
1729         *
1730         * @param o the value to subtract.
1731         * @return new NumericValueExp(the result of the subtraction.
1732         */
1733        public NumericValueExp minus(NumericValueExp o)
1734        {
1735          Number v = o.getValue();
1736          if (val instanceof Double)
1737            {
1738              double d = val.doubleValue();
1739              if (v instanceof Double)
1740                return new NumericValueExp(d - v.doubleValue());
1741              else if (v instanceof Float)
1742                return new NumericValueExp(d - v.floatValue());
1743              else if (v instanceof Long)
1744                return new NumericValueExp(d - v.longValue());
1745              else
1746                return new NumericValueExp(d - v.intValue());
1747            }
1748          else if (val instanceof Float)
1749            {
1750              float f = val.floatValue();
1751              if (v instanceof Double)
1752                return new NumericValueExp(f - v.doubleValue());
1753              else if (v instanceof Float)
1754                return new NumericValueExp(f - v.floatValue());
1755              else if (v instanceof Long)
1756                return new NumericValueExp(f - v.longValue());
1757              else
1758                return new NumericValueExp(f - v.intValue());
1759            }
1760          else if (val instanceof Long)
1761            {
1762              long l = val.longValue();
1763              if (v instanceof Double)
1764                return new NumericValueExp(l - v.doubleValue());
1765              else if (v instanceof Float)
1766                return new NumericValueExp(l - v.floatValue());
1767              else if (v instanceof Long)
1768                return new NumericValueExp(l - v.longValue());
1769              else
1770                return new NumericValueExp(l - v.intValue());
1771            }
1772          int i = val.intValue();
1773          if (v instanceof Double)
1774            return new NumericValueExp(i - v.doubleValue());
1775          else if (v instanceof Float)
1776            return new NumericValueExp(i - v.floatValue());
1777          else if (v instanceof Long)
1778            return new NumericValueExp(i - v.longValue());
1779          else
1780            return new NumericValueExp(i - v.intValue());   
1781        }   
1782    
1783        /**
1784         * Return New NumericValueExp(the result of multiplying the specified
1785         * {@link NumericValueExp} to this one.
1786         *
1787         * @param o the value to multiply by.
1788         * @return new NumericValueExp(the result of the multiplication.
1789         */
1790        public NumericValueExp times(NumericValueExp o)
1791        {
1792          Number v = o.getValue();
1793          if (val instanceof Double)
1794            {
1795              double d = val.doubleValue();
1796              if (v instanceof Double)
1797                return new NumericValueExp(d * v.doubleValue());
1798              else if (v instanceof Float)
1799                return new NumericValueExp(d * v.floatValue());
1800              else if (v instanceof Long)
1801                return new NumericValueExp(d * v.longValue());
1802              else
1803                return new NumericValueExp(d * v.intValue());
1804            }
1805          else if (val instanceof Float)
1806            {
1807              float f = val.floatValue();
1808              if (v instanceof Double)
1809                return new NumericValueExp(f * v.doubleValue());
1810              else if (v instanceof Float)
1811                return new NumericValueExp(f * v.floatValue());
1812              else if (v instanceof Long)
1813                return new NumericValueExp(f * v.longValue());
1814              else
1815                return new NumericValueExp(f * v.intValue());
1816            }
1817          else if (val instanceof Long)
1818            {
1819              long l = val.longValue();
1820              if (v instanceof Double)
1821                return new NumericValueExp(l * v.doubleValue());
1822              else if (v instanceof Float)
1823                return new NumericValueExp(l * v.floatValue());
1824              else if (v instanceof Long)
1825                return new NumericValueExp(l * v.longValue());
1826              else
1827                return new NumericValueExp(l * v.intValue());
1828            }
1829          int i = val.intValue();
1830          if (v instanceof Double)
1831            return new NumericValueExp(i * v.doubleValue());
1832          else if (v instanceof Float)
1833            return new NumericValueExp(i * v.floatValue());
1834          else if (v instanceof Long)
1835            return new NumericValueExp(i * v.longValue());
1836          else
1837            return new NumericValueExp(i * v.intValue());   
1838        }   
1839    
1840        /**
1841         * Return New NumericValueExp(the result of dividing this
1842         * number by value of the specified
1843         * {@link NumericValueExp}.
1844         *
1845         * @param o the value to divide by.
1846         * @return new NumericValueExp(the result of the division.
1847         */
1848        public NumericValueExp div(NumericValueExp o)
1849        {
1850          Number v = o.getValue();
1851          if (val instanceof Double)
1852            {
1853              double d = val.doubleValue();
1854              if (v instanceof Double)
1855                return new NumericValueExp(d / v.doubleValue());
1856              else if (v instanceof Float)
1857                return new NumericValueExp(d / v.floatValue());
1858              else if (v instanceof Long)
1859                return new NumericValueExp(d / v.longValue());
1860              else
1861                return new NumericValueExp(d / v.intValue());
1862            }
1863          else if (val instanceof Float)
1864            {
1865              float f = val.floatValue();
1866              if (v instanceof Double)
1867                return new NumericValueExp(f / v.doubleValue());
1868              else if (v instanceof Float)
1869                return new NumericValueExp(f / v.floatValue());
1870              else if (v instanceof Long)
1871                return new NumericValueExp(f / v.longValue());
1872              else
1873                return new NumericValueExp(f / v.intValue());
1874            }
1875          else if (val instanceof Long)
1876            {
1877              long l = val.longValue();
1878              if (v instanceof Double)
1879                return new NumericValueExp(l / v.doubleValue());
1880              else if (v instanceof Float)
1881                return new NumericValueExp(l / v.floatValue());
1882              else if (v instanceof Long)
1883                return new NumericValueExp(l / v.longValue());
1884              else
1885                return new NumericValueExp(l / v.intValue());
1886            }
1887          int i = val.intValue();
1888          if (v instanceof Double)
1889            return new NumericValueExp(i / v.doubleValue());
1890          else if (v instanceof Float)
1891            return new NumericValueExp(i / v.floatValue());
1892          else if (v instanceof Long)
1893            return new NumericValueExp(i / v.longValue());
1894          else
1895            return new NumericValueExp(i / v.intValue());   
1896        }   
1897    
1898      }
1899    
1900    }
1901