1 /*
   2  * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.image.renderable;
  27 import java.awt.image.RenderedImage;
  28 import java.io.Serializable;
  29 import java.util.Vector;
  30 
  31 /**
  32  * A <code>ParameterBlock</code> encapsulates all the information about sources and
  33  * parameters (Objects) required by a RenderableImageOp, or other
  34  * classes that process images.
  35  *
  36  * <p> Although it is possible to place arbitrary objects in the
  37  * source Vector, users of this class may impose semantic constraints
  38  * such as requiring all sources to be RenderedImages or
  39  * RenderableImage.  <code>ParameterBlock</code> itself is merely a container and
  40  * performs no checking on source or parameter types.
  41  *
  42  * <p> All parameters in a <code>ParameterBlock</code> are objects; convenience
  43  * add and set methods are available that take arguments of base type and
  44  * construct the appropriate subclass of Number (such as
  45  * Integer or Float).  Corresponding get methods perform a
  46  * downward cast and have return values of base type; an exception
  47  * will be thrown if the stored values do not have the correct type.
  48  * There is no way to distinguish between the results of
  49  * "short s; add(s)" and "add(new Short(s))".
  50  *
  51  * <p> Note that the get and set methods operate on references.
  52  * Therefore, one must be careful not to share references between
  53  * <code>ParameterBlock</code>s when this is inappropriate.  For example, to create
  54  * a new <code>ParameterBlock</code> that is equal to an old one except for an
  55  * added source, one might be tempted to write:
  56  *
  57  * <pre>
  58  * ParameterBlock addSource(ParameterBlock pb, RenderableImage im) {
  59  *     ParameterBlock pb1 = new ParameterBlock(pb.getSources());
  60  *     pb1.addSource(im);
  61  *     return pb1;
  62  * }
  63  * </pre>
  64  *
  65  * <p> This code will have the side effect of altering the original
  66  * <code>ParameterBlock</code>, since the getSources operation returned a reference
  67  * to its source Vector.  Both pb and pb1 share their source Vector,
  68  * and a change in either is visible to both.
  69  *
  70  * <p> A correct way to write the addSource function is to clone
  71  * the source Vector:
  72  *
  73  * <pre>
  74  * ParameterBlock addSource (ParameterBlock pb, RenderableImage im) {
  75  *     ParameterBlock pb1 = new ParameterBlock(pb.getSources().clone());
  76  *     pb1.addSource(im);
  77  *     return pb1;
  78  * }
  79  * </pre>
  80  *
  81  * <p> The clone method of <code>ParameterBlock</code> has been defined to
  82  * perform a clone of both the source and parameter Vectors for
  83  * this reason.  A standard, shallow clone is available as
  84  * shallowClone.
  85  *
  86  * <p> The addSource, setSource, add, and set methods are
  87  * defined to return 'this' after adding their argument.  This allows
  88  * use of syntax like:
  89  *
  90  * <pre>
  91  * ParameterBlock pb = new ParameterBlock();
  92  * op = new RenderableImageOp("operation", pb.add(arg1).add(arg2));
  93  * </pre>
  94  * */
  95 public class ParameterBlock implements Cloneable, Serializable {
  96     private static final long serialVersionUID = -7577115551785240750L;
  97 
  98     /** A Vector of sources, stored as arbitrary Objects. */
  99     protected Vector<Object> sources = new Vector<Object>();
 100 
 101     /** A Vector of non-source parameters, stored as arbitrary Objects. */
 102     protected Vector<Object> parameters = new Vector<Object>();
 103 
 104     /** A dummy constructor. */
 105     public ParameterBlock() {}
 106 
 107     /**
 108      * Constructs a <code>ParameterBlock</code> with a given Vector
 109      * of sources.
 110      * @param sources a <code>Vector</code> of source images
 111      */
 112     public ParameterBlock(Vector<Object> sources) {
 113         setSources(sources);
 114     }
 115 
 116     /**
 117      * Constructs a <code>ParameterBlock</code> with a given Vector of sources and
 118      * Vector of parameters.
 119      * @param sources a <code>Vector</code> of source images
 120      * @param parameters a <code>Vector</code> of parameters to be used in the
 121      *        rendering operation
 122      */
 123     public ParameterBlock(Vector<Object> sources,
 124                           Vector<Object> parameters)
 125     {
 126         setSources(sources);
 127         setParameters(parameters);
 128     }
 129 
 130     /**
 131      * Creates a shallow copy of a <code>ParameterBlock</code>.  The source and
 132      * parameter Vectors are copied by reference -- additions or
 133      * changes will be visible to both versions.
 134      *
 135      * @return an Object clone of the <code>ParameterBlock</code>.
 136      */
 137     public Object shallowClone() {
 138         try {
 139             return super.clone();
 140         } catch (Exception e) {
 141             // We can't be here since we implement Cloneable.
 142             return null;
 143         }
 144     }
 145 
 146     /**
 147      * Creates a copy of a <code>ParameterBlock</code>.  The source and parameter
 148      * Vectors are cloned, but the actual sources and parameters are
 149      * copied by reference.  This allows modifications to the order
 150      * and number of sources and parameters in the clone to be invisible
 151      * to the original <code>ParameterBlock</code>.  Changes to the shared sources or
 152      * parameters themselves will still be visible.
 153      *
 154      * @return an Object clone of the <code>ParameterBlock</code>.
 155      */
 156     @SuppressWarnings("unchecked") // casts from clone
 157     public Object clone() {
 158         ParameterBlock theClone;
 159 
 160         try {
 161             theClone = (ParameterBlock) super.clone();
 162         } catch (Exception e) {
 163             // We can't be here since we implement Cloneable.
 164             return null;
 165         }
 166 
 167         if (sources != null) {
 168             theClone.setSources((Vector<Object>)sources.clone());
 169         }
 170         if (parameters != null) {
 171             theClone.setParameters((Vector<Object>)parameters.clone());
 172         }
 173         return (Object) theClone;
 174     }
 175 
 176     /**
 177      * Adds an image to end of the list of sources.  The image is
 178      * stored as an object in order to allow new node types in the
 179      * future.
 180      *
 181      * @param source an image object to be stored in the source list.
 182      * @return a new <code>ParameterBlock</code> containing the specified
 183      *         <code>source</code>.
 184      */
 185     public ParameterBlock addSource(Object source) {
 186         sources.addElement(source);
 187         return this;
 188     }
 189 
 190     /**
 191      * Returns a source as a general Object.  The caller must cast it into
 192      * an appropriate type.
 193      *
 194      * @param index the index of the source to be returned.
 195      * @return an <code>Object</code> that represents the source located
 196      *         at the specified index in the <code>sources</code>
 197      *         <code>Vector</code>.
 198      * @see #setSource(Object, int)
 199      */
 200     public Object getSource(int index) {
 201         return sources.elementAt(index);
 202     }
 203 
 204     /**
 205      * Replaces an entry in the list of source with a new source.
 206      * If the index lies beyond the current source list,
 207      * the list is extended with nulls as needed.
 208      * @param source the specified source image
 209      * @param index the index into the <code>sources</code>
 210      *              <code>Vector</code> at which to
 211      *              insert the specified <code>source</code>
 212      * @return a new <code>ParameterBlock</code> that contains the
 213      *         specified <code>source</code> at the specified
 214      *         <code>index</code>.
 215      * @see #getSource(int)
 216      */
 217     public ParameterBlock setSource(Object source, int index) {
 218         int oldSize = sources.size();
 219         int newSize = index + 1;
 220         if (oldSize < newSize) {
 221             sources.setSize(newSize);
 222         }
 223         sources.setElementAt(source, index);
 224         return this;
 225     }
 226 
 227     /**
 228      * Returns a source as a <code>RenderedImage</code>.  This method is
 229      * a convenience method.
 230      * An exception will be thrown if the source is not a RenderedImage.
 231      *
 232      * @param index the index of the source to be returned
 233      * @return a <code>RenderedImage</code> that represents the source
 234      *         image that is at the specified index in the
 235      *         <code>sources</code> <code>Vector</code>.
 236      */
 237     public RenderedImage getRenderedSource(int index) {
 238         return (RenderedImage) sources.elementAt(index);
 239     }
 240 
 241     /**
 242      * Returns a source as a RenderableImage.  This method is a
 243      * convenience method.
 244      * An exception will be thrown if the sources is not a RenderableImage.
 245      *
 246      * @param index the index of the source to be returned
 247      * @return a <code>RenderableImage</code> that represents the source
 248      *         image that is at the specified index in the
 249      *         <code>sources</code> <code>Vector</code>.
 250      */
 251     public RenderableImage getRenderableSource(int index) {
 252         return (RenderableImage) sources.elementAt(index);
 253     }
 254 
 255     /**
 256      * Returns the number of source images.
 257      * @return the number of source images in the <code>sources</code>
 258      *         <code>Vector</code>.
 259      */
 260     public int getNumSources() {
 261         return sources.size();
 262     }
 263 
 264     /**
 265      * Returns the entire Vector of sources.
 266      * @return the <code>sources</code> <code>Vector</code>.
 267      * @see #setSources(Vector)
 268      */
 269     public Vector<Object> getSources() {
 270         return sources;
 271     }
 272 
 273     /**
 274      * Sets the entire Vector of sources to a given Vector.
 275      * @param sources the <code>Vector</code> of source images
 276      * @see #getSources
 277      */
 278     public void setSources(Vector<Object> sources) {
 279         this.sources = sources;
 280     }
 281 
 282     /** Clears the list of source images. */
 283     public void removeSources() {
 284         sources = new Vector<>();
 285     }
 286 
 287     /**
 288      * Returns the number of parameters (not including source images).
 289      * @return the number of parameters in the <code>parameters</code>
 290      *         <code>Vector</code>.
 291      */
 292     public int getNumParameters() {
 293         return parameters.size();
 294     }
 295 
 296     /**
 297      * Returns the entire Vector of parameters.
 298      * @return the <code>parameters</code> <code>Vector</code>.
 299      * @see #setParameters(Vector)
 300      */
 301     public Vector<Object> getParameters() {
 302         return parameters;
 303     }
 304 
 305     /**
 306      * Sets the entire Vector of parameters to a given Vector.
 307      * @param parameters the specified <code>Vector</code> of
 308      *        parameters
 309      * @see #getParameters
 310      */
 311     public void setParameters(Vector<Object> parameters) {
 312         this.parameters = parameters;
 313     }
 314 
 315     /** Clears the list of parameters. */
 316     public void removeParameters() {
 317         parameters = new Vector<>();
 318     }
 319 
 320     /**
 321      * Adds an object to the list of parameters.
 322      * @param obj the <code>Object</code> to add to the
 323      *            <code>parameters</code> <code>Vector</code>
 324      * @return a new <code>ParameterBlock</code> containing
 325      *         the specified parameter.
 326      */
 327     public ParameterBlock add(Object obj) {
 328         parameters.addElement(obj);
 329         return this;
 330     }
 331 
 332     /**
 333      * Adds a Byte to the list of parameters.
 334      * @param b the byte to add to the
 335      *            <code>parameters</code> <code>Vector</code>
 336      * @return a new <code>ParameterBlock</code> containing
 337      *         the specified parameter.
 338      */
 339     public ParameterBlock add(byte b) {
 340         return add(new Byte(b));
 341     }
 342 
 343     /**
 344      * Adds a Character to the list of parameters.
 345      * @param c the char to add to the
 346      *            <code>parameters</code> <code>Vector</code>
 347      * @return a new <code>ParameterBlock</code> containing
 348      *         the specified parameter.
 349      */
 350     public ParameterBlock add(char c) {
 351         return add(new Character(c));
 352     }
 353 
 354     /**
 355      * Adds a Short to the list of parameters.
 356      * @param s the short to add to the
 357      *            <code>parameters</code> <code>Vector</code>
 358      * @return a new <code>ParameterBlock</code> containing
 359      *         the specified parameter.
 360      */
 361     public ParameterBlock add(short s) {
 362         return add(new Short(s));
 363     }
 364 
 365     /**
 366      * Adds a Integer to the list of parameters.
 367      * @param i the int to add to the
 368      *            <code>parameters</code> <code>Vector</code>
 369      * @return a new <code>ParameterBlock</code> containing
 370      *         the specified parameter.
 371      */
 372     public ParameterBlock add(int i) {
 373         return add(new Integer(i));
 374     }
 375 
 376     /**
 377      * Adds a Long to the list of parameters.
 378      * @param l the long to add to the
 379      *            <code>parameters</code> <code>Vector</code>
 380      * @return a new <code>ParameterBlock</code> containing
 381      *         the specified parameter.
 382      */
 383     public ParameterBlock add(long l) {
 384         return add(l);
 385     }
 386 
 387     /**
 388      * Adds a Float to the list of parameters.
 389      * @param f the float to add to the
 390      *            <code>parameters</code> <code>Vector</code>
 391      * @return a new <code>ParameterBlock</code> containing
 392      *         the specified parameter.
 393      */
 394     public ParameterBlock add(float f) {
 395         return add(new Float(f));
 396     }
 397 
 398     /**
 399      * Adds a Double to the list of parameters.
 400      * @param d the double to add to the
 401      *            <code>parameters</code> <code>Vector</code>
 402      * @return a new <code>ParameterBlock</code> containing
 403      *         the specified parameter.
 404      */
 405     public ParameterBlock add(double d) {
 406         return add(new Double(d));
 407     }
 408 
 409     /**
 410      * Replaces an Object in the list of parameters.
 411      * If the index lies beyond the current source list,
 412      * the list is extended with nulls as needed.
 413      * @param obj the parameter that replaces the
 414      *        parameter at the specified index in the
 415      *        <code>parameters</code> <code>Vector</code>
 416      * @param index the index of the parameter to be
 417      *        replaced with the specified parameter
 418      * @return a new <code>ParameterBlock</code> containing
 419      *        the specified parameter.
 420      */
 421     public ParameterBlock set(Object obj, int index) {
 422         int oldSize = parameters.size();
 423         int newSize = index + 1;
 424         if (oldSize < newSize) {
 425             parameters.setSize(newSize);
 426         }
 427         parameters.setElementAt(obj, index);
 428         return this;
 429     }
 430 
 431     /**
 432      * Replaces an Object in the list of parameters with a Byte.
 433      * If the index lies beyond the current source list,
 434      * the list is extended with nulls as needed.
 435      * @param b the parameter that replaces the
 436      *        parameter at the specified index in the
 437      *        <code>parameters</code> <code>Vector</code>
 438      * @param index the index of the parameter to be
 439      *        replaced with the specified parameter
 440      * @return a new <code>ParameterBlock</code> containing
 441      *        the specified parameter.
 442      */
 443     public ParameterBlock set(byte b, int index) {
 444         return set(new Byte(b), index);
 445     }
 446 
 447     /**
 448      * Replaces an Object in the list of parameters with a Character.
 449      * If the index lies beyond the current source list,
 450      * the list is extended with nulls as needed.
 451      * @param c the parameter that replaces the
 452      *        parameter at the specified index in the
 453      *        <code>parameters</code> <code>Vector</code>
 454      * @param index the index of the parameter to be
 455      *        replaced with the specified parameter
 456      * @return a new <code>ParameterBlock</code> containing
 457      *        the specified parameter.
 458      */
 459     public ParameterBlock set(char c, int index) {
 460         return set(new Character(c), index);
 461     }
 462 
 463     /**
 464      * Replaces an Object in the list of parameters with a Short.
 465      * If the index lies beyond the current source list,
 466      * the list is extended with nulls as needed.
 467      * @param s the parameter that replaces the
 468      *        parameter at the specified index in the
 469      *        <code>parameters</code> <code>Vector</code>
 470      * @param index the index of the parameter to be
 471      *        replaced with the specified parameter
 472      * @return a new <code>ParameterBlock</code> containing
 473      *        the specified parameter.
 474      */
 475     public ParameterBlock set(short s, int index) {
 476         return set(new Short(s), index);
 477     }
 478 
 479     /**
 480      * Replaces an Object in the list of parameters with an Integer.
 481      * If the index lies beyond the current source list,
 482      * the list is extended with nulls as needed.
 483      * @param i the parameter that replaces the
 484      *        parameter at the specified index in the
 485      *        <code>parameters</code> <code>Vector</code>
 486      * @param index the index of the parameter to be
 487      *        replaced with the specified parameter
 488      * @return a new <code>ParameterBlock</code> containing
 489      *        the specified parameter.
 490      */
 491     public ParameterBlock set(int i, int index) {
 492         return set(new Integer(i), index);
 493     }
 494 
 495     /**
 496      * Replaces an Object in the list of parameters with a Long.
 497      * If the index lies beyond the current source list,
 498      * the list is extended with nulls as needed.
 499      * @param l the parameter that replaces the
 500      *        parameter at the specified index in the
 501      *        <code>parameters</code> <code>Vector</code>
 502      * @param index the index of the parameter to be
 503      *        replaced with the specified parameter
 504      * @return a new <code>ParameterBlock</code> containing
 505      *        the specified parameter.
 506      */
 507     public ParameterBlock set(long l, int index) {
 508         return set(l, index);
 509     }
 510 
 511     /**
 512      * Replaces an Object in the list of parameters with a Float.
 513      * If the index lies beyond the current source list,
 514      * the list is extended with nulls as needed.
 515      * @param f the parameter that replaces the
 516      *        parameter at the specified index in the
 517      *        <code>parameters</code> <code>Vector</code>
 518      * @param index the index of the parameter to be
 519      *        replaced with the specified parameter
 520      * @return a new <code>ParameterBlock</code> containing
 521      *        the specified parameter.
 522      */
 523     public ParameterBlock set(float f, int index) {
 524         return set(new Float(f), index);
 525     }
 526 
 527     /**
 528      * Replaces an Object in the list of parameters with a Double.
 529      * If the index lies beyond the current source list,
 530      * the list is extended with nulls as needed.
 531      * @param d the parameter that replaces the
 532      *        parameter at the specified index in the
 533      *        <code>parameters</code> <code>Vector</code>
 534      * @param index the index of the parameter to be
 535      *        replaced with the specified parameter
 536      * @return a new <code>ParameterBlock</code> containing
 537      *        the specified parameter.
 538      */
 539     public ParameterBlock set(double d, int index) {
 540         return set(new Double(d), index);
 541     }
 542 
 543     /**
 544      * Gets a parameter as an object.
 545      * @param index the index of the parameter to get
 546      * @return an <code>Object</code> representing the
 547      *         the parameter at the specified index
 548      *         into the <code>parameters</code>
 549      *         <code>Vector</code>.
 550      */
 551     public Object getObjectParameter(int index) {
 552         return parameters.elementAt(index);
 553     }
 554 
 555     /**
 556      * A convenience method to return a parameter as a byte.  An
 557      * exception is thrown if the parameter is
 558      * <code>null</code> or not a <code>Byte</code>.
 559      *
 560      * @param index the index of the parameter to be returned.
 561      * @return the parameter at the specified index
 562      *         as a <code>byte</code> value.
 563      * @throws ClassCastException if the parameter at the
 564      *         specified index is not a <code>Byte</code>
 565      * @throws NullPointerException if the parameter at the specified
 566      *         index is <code>null</code>
 567      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 568      *         is negative or not less than the current size of this
 569      *         <code>ParameterBlock</code> object
 570      */
 571     public byte getByteParameter(int index) {
 572         return ((Byte)parameters.elementAt(index)).byteValue();
 573     }
 574 
 575     /**
 576      * A convenience method to return a parameter as a char.  An
 577      * exception is thrown if the parameter is
 578      * <code>null</code> or not a <code>Character</code>.
 579      *
 580      * @param index the index of the parameter to be returned.
 581      * @return the parameter at the specified index
 582      *         as a <code>char</code> value.
 583      * @throws ClassCastException if the parameter at the
 584      *         specified index is not a <code>Character</code>
 585      * @throws NullPointerException if the parameter at the specified
 586      *         index is <code>null</code>
 587      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 588      *         is negative or not less than the current size of this
 589      *         <code>ParameterBlock</code> object
 590      */
 591     public char getCharParameter(int index) {
 592         return ((Character)parameters.elementAt(index)).charValue();
 593     }
 594 
 595     /**
 596      * A convenience method to return a parameter as a short.  An
 597      * exception is thrown if the parameter is
 598      * <code>null</code> or not a <code>Short</code>.
 599      *
 600      * @param index the index of the parameter to be returned.
 601      * @return the parameter at the specified index
 602      *         as a <code>short</code> value.
 603      * @throws ClassCastException if the parameter at the
 604      *         specified index is not a <code>Short</code>
 605      * @throws NullPointerException if the parameter at the specified
 606      *         index is <code>null</code>
 607      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 608      *         is negative or not less than the current size of this
 609      *         <code>ParameterBlock</code> object
 610      */
 611     public short getShortParameter(int index) {
 612         return ((Short)parameters.elementAt(index)).shortValue();
 613     }
 614 
 615     /**
 616      * A convenience method to return a parameter as an int.  An
 617      * exception is thrown if the parameter is
 618      * <code>null</code> or not an <code>Integer</code>.
 619      *
 620      * @param index the index of the parameter to be returned.
 621      * @return the parameter at the specified index
 622      *         as a <code>int</code> value.
 623      * @throws ClassCastException if the parameter at the
 624      *         specified index is not a <code>Integer</code>
 625      * @throws NullPointerException if the parameter at the specified
 626      *         index is <code>null</code>
 627      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 628      *         is negative or not less than the current size of this
 629      *         <code>ParameterBlock</code> object
 630      */
 631     public int getIntParameter(int index) {
 632         return ((Integer)parameters.elementAt(index)).intValue();
 633     }
 634 
 635     /**
 636      * A convenience method to return a parameter as a long.  An
 637      * exception is thrown if the parameter is
 638      * <code>null</code> or not a <code>Long</code>.
 639      *
 640      * @param index the index of the parameter to be returned.
 641      * @return the parameter at the specified index
 642      *         as a <code>long</code> value.
 643      * @throws ClassCastException if the parameter at the
 644      *         specified index is not a <code>Long</code>
 645      * @throws NullPointerException if the parameter at the specified
 646      *         index is <code>null</code>
 647      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 648      *         is negative or not less than the current size of this
 649      *         <code>ParameterBlock</code> object
 650      */
 651     public long getLongParameter(int index) {
 652         return ((Long)parameters.elementAt(index)).longValue();
 653     }
 654 
 655     /**
 656      * A convenience method to return a parameter as a float.  An
 657      * exception is thrown if the parameter is
 658      * <code>null</code> or not a <code>Float</code>.
 659      *
 660      * @param index the index of the parameter to be returned.
 661      * @return the parameter at the specified index
 662      *         as a <code>float</code> value.
 663      * @throws ClassCastException if the parameter at the
 664      *         specified index is not a <code>Float</code>
 665      * @throws NullPointerException if the parameter at the specified
 666      *         index is <code>null</code>
 667      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 668      *         is negative or not less than the current size of this
 669      *         <code>ParameterBlock</code> object
 670      */
 671     public float getFloatParameter(int index) {
 672         return ((Float)parameters.elementAt(index)).floatValue();
 673     }
 674 
 675     /**
 676      * A convenience method to return a parameter as a double.  An
 677      * exception is thrown if the parameter is
 678      * <code>null</code> or not a <code>Double</code>.
 679      *
 680      * @param index the index of the parameter to be returned.
 681      * @return the parameter at the specified index
 682      *         as a <code>double</code> value.
 683      * @throws ClassCastException if the parameter at the
 684      *         specified index is not a <code>Double</code>
 685      * @throws NullPointerException if the parameter at the specified
 686      *         index is <code>null</code>
 687      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
 688      *         is negative or not less than the current size of this
 689      *         <code>ParameterBlock</code> object
 690      */
 691     public double getDoubleParameter(int index) {
 692         return ((Double)parameters.elementAt(index)).doubleValue();
 693     }
 694 
 695     /**
 696      * Returns an array of Class objects describing the types
 697      * of the parameters.
 698      * @return an array of <code>Class</code> objects.
 699      */
 700     public Class<?>[] getParamClasses() {
 701         int numParams = getNumParameters();
 702         Class<?>[] classes = new Class<?>[numParams];
 703         int i;
 704 
 705         for (i = 0; i < numParams; i++) {
 706             Object obj = getObjectParameter(i);
 707             if (obj instanceof Byte) {
 708               classes[i] = byte.class;
 709             } else if (obj instanceof Character) {
 710               classes[i] = char.class;
 711             } else if (obj instanceof Short) {
 712               classes[i] = short.class;
 713             } else if (obj instanceof Integer) {
 714               classes[i] = int.class;
 715             } else if (obj instanceof Long) {
 716               classes[i] = long.class;
 717             } else if (obj instanceof Float) {
 718               classes[i] = float.class;
 719             } else if (obj instanceof Double) {
 720               classes[i] = double.class;
 721             } else {
 722               classes[i] = obj.getClass();
 723             }
 724         }
 725 
 726         return classes;
 727     }
 728 }