001/* Query.java -- Static methods for query construction.
002   Copyright (C) 2007 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package 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 */
050public 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