null).
   */
  private Object defaultValue;
  /**
   * The possible legal values of the parameter (may be null).
   */
  private Set> legalValues;
  /**
   * The minimum value of the parameter (may be null).
   */
  private Comparable> minValue;
  /**
   * The maximum value of the parameter (may be null).
   */
  private Comparable> maxValue;
  /**
   * The hash code of this instance.
   */
  private transient Integer hashCode;
  /**
   * The toString() result of this instance.
   */
  private transient String string;
  /**
   * Constructs a new {@link OpenMBeanParameterInfo} using the specified
   * name, description and open type.  None of these values may be
   * null and the name and description may not be equal
   * to the empty string.
   *
   * @param name the name of the parameter.
   * @param desc a description of the parameter.
   * @param type the open type of the parameter.
   * @throws IllegalArgumentException if the name, description or
   *                                  open type are null
   *                                  or the name or description are
   *                                  the empty string.
   */
  public OpenMBeanParameterInfoSupport(String name, String desc, OpenType> type)
  {
    super(name, type == null ? null : type.getClassName(), desc);
    if (name == null)
      throw new IllegalArgumentException("The name may not be null.");
    if (desc == null)
      throw new IllegalArgumentException("The description may not be null.");
    if (type == null)
      throw new IllegalArgumentException("The type may not be null.");
    if (name.length() == 0)
      throw new IllegalArgumentException("The name may not be the empty string.");
    if (desc.length() == 0)
      throw new IllegalArgumentException("The description may not be the " +
                                         "empty string.");
    openType = type;
  }
  /**
   * Constructs a new {@link OpenMBeanParameterInfo} using the
   * specified name, description, open type and default value.  The
   * name, description and open type cannot be null and
   * the name and description may not be equal to the empty string.
   * The default value may be null.  If non-null, it must
   * be a valid value of the given open type.  Default values are not
   * applicable to the open types, {@link ArrayType} and {@link
   * TabularType}.
   *
   * @param name the name of the parameter.
   * @param desc a description of the parameter.
   * @param type the open type of the parameter.
   * @param defaultValue the default value of the parameter.
   * @throws IllegalArgumentException if the name, description or
   *                                  open type are null
   *                                  or the name or description are
   *                                  the empty string.
   * @throws OpenDataException if defaultValue is non-null
   *                           and is either not a value of the given
   *                           open type or the open type is an instance
   *                           of {@link ArrayType} or {@link TabularType}.
   */
  public  OpenMBeanParameterInfoSupport(String name, String desc, OpenType type,
                                           T defaultValue)
    throws OpenDataException
  {
    this(name, desc, type, defaultValue, null);
  }
  /**
   * 
   * Constructs a new {@link OpenMBeanParameterInfo} using the
   * specified name, description, open type, default, maximum and
   * minimum values.  The name, description and open type cannot be
   * null and the name and description may not be equal
   * to the empty string.  The default, maximum and minimum values may
   * be null.  The following conditions apply when the
   * parameters mentioned are non-null:
   * 
   * 
   * - The values must be valid values for the given open type.*
- Default values are not applicable to the open types, {@link
   * ArrayType} and {@link TabularType}.*
- The minimum value must be smaller than or equal to the maximum value
   * (literally, minValue.compareTo(maxValue) <= 0.
*- The minimum value must be smaller than or equal to the default value
   * (literally, minValue.compareTo(defaultValue) <= 0.
*- The default value must be smaller than or equal to the maximum value
   * (literally, defaultValue.compareTo(maxValue) <= 0.
*
*
   * @param name the name of the parameter.
   * @param desc a description of the parameter.
   * @param type the open type of the parameter.
   * @param defaultValue the default value of the parameter, ornull.
   * @param minimumValue the minimum value of the parameter, or null.
   * @param maximumValue the maximum value of the parameter, or null.
   * @throws IllegalArgumentException if the name, description or
   *                                  open type are null
   *                                  or the name or description are
   *                                  the empty string.
   * @throws OpenDataException if any condition in the list above is broken.
   */
  @SuppressWarnings("unchecked")
  public  OpenMBeanParameterInfoSupport(String name, String desc, OpenType type,
                                           T defaultValue, Comparable minimumValue,
                                           Comparable maximumValue)
    throws OpenDataException
  {
    this(name, desc, type);
    if (defaultValue != null && !(type.isValue(defaultValue)))
      throw new OpenDataException("The default value is not a member of the " +
                                  "open type given.");
    if (minimumValue != null && !(type.isValue(minimumValue)))
      throw new OpenDataException("The minimum value is not a member of the " +
                                  "open type given.");
    if (maximumValue != null && !(type.isValue(maximumValue)))
      throw new OpenDataException("The maximum value is not a member of the " +
                                  "open type given.");
    if (defaultValue != null && (type instanceof ArrayType ||
                                 type instanceof TabularType))
      throw new OpenDataException("Default values are not applicable for " +
                                  "array or tabular types.");
    if (minimumValue != null && maximumValue != null
        && minimumValue.compareTo((T) maximumValue) > 0)
      throw new OpenDataException("The minimum value is greater than the " +
                                  "maximum.");
    if (minimumValue != null && defaultValue != null
        && minimumValue.compareTo(defaultValue) > 0)
      throw new OpenDataException("The minimum value is greater than the " +
                                  "default.");
    if (defaultValue != null && maximumValue != null
        && maximumValue.compareTo(defaultValue) < 0)
      throw new OpenDataException("The default value is greater than the " +
                                  "maximum.");
    this.defaultValue = defaultValue;
    minValue = minimumValue;
    maxValue = maximumValue;
  }
  /**
   * 
   * Constructs a new {@link OpenMBeanParameterInfo} using the
   * specified name, description, open type, default value and
   * set of legal values.  The name, description and open type cannot be
   * null and the name and description may not be equal
   * to the empty string.  The default, maximum and minimum values may
   * be null.  The following conditions apply when the
   * parameters mentioned are non-null:
   * 
   * 
   * - The default value and each of the legal values must be a valid
   * value for the given open type.*
- Default and legal values are not applicable to the open types, {@link
   * ArrayType} and {@link TabularType}.*
- The default value is not in the set of legal values.*
*
   * The legal values are copied from the array into a unmodifiable set,
   * so future modifications to the array have no effect.
   * 
   *
   * @param name the name of the parameter.
   * @param desc a description of the parameter.
   * @param type the open type of the parameter.
   * @param defaultValue the default value of the parameter, or null.
   * @param legalValues the legal values of the parameter.  May be
   *                    null or an empty array.
   * @throws IllegalArgumentException if the name, description or
   *                                  open type are null
   *                                  or the name or description are
   *                                  the empty string.
   * @throws OpenDataException if any condition in the list above is broken.
   */
  public  OpenMBeanParameterInfoSupport(String name, String desc, OpenType type,
                                           T defaultValue, T[] legalValues)
    throws OpenDataException
  {
    this(name, desc, type);
    if (defaultValue != null && !(type.isValue(defaultValue)))
      throw new OpenDataException("The default value is not a member of the " +
                                  "open type given.");
    if (defaultValue != null && (type instanceof ArrayType ||
                                 type instanceof TabularType))
      throw new OpenDataException("Default values are not applicable for " +
                                  "array or tabular types.");
    if (legalValues != null && (type instanceof ArrayType ||
                                type instanceof TabularType))
      throw new OpenDataException("Legal values are not applicable for " +
                                  "array or tabular types.");
    if (legalValues != null && legalValues.length > 0)
      {
        Set lv = new HashSet(legalValues.length);
        for (int a = 0; a < legalValues.length; ++a)
          {
            if (legalValues[a] != null &&
                !(type.isValue(legalValues[a])))
              throw new OpenDataException("The legal value, "
                                          + legalValues[a] +
                                          "is not a member of the " +
                                          "open type given.");
            lv.add(legalValues[a]);
          }
        if (defaultValue != null && !(lv.contains(defaultValue)))
          throw new OpenDataException("The default value is not in the set " +
                                      "of legal values.");
        this.legalValues = Collections.unmodifiableSet(lv);
      }
    this.defaultValue = defaultValue;
  }
  /**
   * Compares this parameter with the supplied object.  This returns
   * true iff the object is an instance of {@link OpenMBeanParameterInfo}
   * with an equal name and open type and the same default, minimum,
   * maximum and legal values.
   *
   * @param obj the object to compare.
   * @return true if the object is a {@link OpenMBeanParameterInfo}
   *         instance,
   *         name.equals(object.getName()),
   *         openType.equals(object.getOpenType()),
   *         defaultValue.equals(object.getDefaultValue()),
   *         minValue.equals(object.getMinValue()),
   *         maxValue.equals(object.getMaxValue()),
   *         and legalValues.equals(object.getLegalValues()).
   */
  public boolean equals(Object obj)
  {
    if (!(obj instanceof OpenMBeanParameterInfo))
      return false;
    OpenMBeanParameterInfo o = (OpenMBeanParameterInfo) obj;
    return getName().equals(o.getName()) &&
      openType.equals(o.getOpenType()) &&
      (defaultValue == null ? o.getDefaultValue() == null :
       defaultValue.equals(o.getDefaultValue())) &&
      (minValue == null ? o.getMinValue() == null :
       minValue.equals(o.getMinValue())) &&
      (maxValue == null ? o.getMaxValue() == null :
       maxValue.equals(o.getMaxValue())) &&
      (legalValues == null ? o.getLegalValues() == null :
       legalValues.equals(o.getLegalValues()));
  }
  /**
   * Returns the default value of this parameter, or null
   * if there is no default value.
   *
   * @return the default value of the parameter, or null
   *         if there is no default.
   */
  public Object getDefaultValue()
  {
    return defaultValue;
  }
  /**
   * Returns a {@link java.util.Set} enumerating the legal values
   * of this parameter, or null if no such limited
   * set exists for this parameter.
   *
   * @return a set of legal values, or null if no such
   *         set exists.
   */
  public Set> getLegalValues()
  {
    return legalValues;
  }
  /**
   * Returns the maximum value of this parameter, or null
   * if there is no maximum.
   *
   * @return the maximum value, or null if none exists.
   */
  public Comparable> getMaxValue()
  {
    return maxValue;
  }
  /**
   * Returns the minimum value of this parameter, or null
   * if there is no minimum.
   *
   * @return the minimum value, or null if none exists.
   */
  public Comparable> getMinValue()
  {
    return minValue;
  }
  /**
   * Returns the open type instance which represents the type of this
   * parameter.
   *
   * @return the open type of this parameter.
   */
  public OpenType> getOpenType()
  {
    return openType;
  }
  /**
   * Returns true if this parameter has a default value
   * (i.e. the value is non-null).
   *
   * @return true if this parameter has a default.
   */
  public boolean hasDefaultValue()
  {
    return defaultValue != null;
  }
  /**
   * 
   * Returns the hashcode of the parameter information as the sum of
   * the hashcodes of the name, open type, default value, maximum
   * value, minimum value and the set of legal values.
   * 
   * 
   * As instances of this class are immutable, the hash code
   * is computed just once for each instance and reused
   * throughout its life.
   * 
   *
   * @return the hashcode of the parameter information.
   */
  public int hashCode()
  {
    if (hashCode == null)
      hashCode = Integer.valueOf(getName().hashCode() +
                                 openType.hashCode() +
                                 (defaultValue == null ? 0 :
                                  defaultValue.hashCode()) +
                                 (minValue == null ? 0 :
                                  minValue.hashCode()) +
                                 (maxValue == null ? 0 :
                                  maxValue.hashCode()) +
                                 (legalValues == null ? 0 :
                                  legalValues.hashCode()));
    return hashCode.intValue();
  }
  /**
   * Returns true if there is a set of legal values for this
   * parameter (i.e. the value is non-null).
   *
   * @return true if a set of legal values exists for this
   *         parameter.
   */
  public boolean hasLegalValues()
  {
    return legalValues != null;
  }
  /**
   * Returns true if there is a maximum value for this parameter
   * (i.e. the value is non-null).
   *
   * @return true if a maximum value exists for this parameter.
   */
  public boolean hasMaxValue()
  {
    return maxValue != null;
  }
  /**
   * Returns true if there is a minimum value for this parameter.
   * (i.e. the value is non-null).
   *
   * @return true if a minimum value exists for this parameter.
   */
  public boolean hasMinValue()
  {
    return minValue != null;
  }
  /**
   * Returns true if the specified object is a valid value for
   * this parameter.
   *
   * @param obj the object to test.
   * @return true if obj is a valid value for this
   *         parameter.
   */
  public boolean isValue(Object obj)
  {
    return openType.isValue(obj);
  }
  /**
   * 
   * Returns a textual representation of this instance.  This
   * is constructed using the class name
   * (javax.management.openmbean.OpenMBeanParameterInfo)
   * along with the name, open type, default, minimum, maximum
   * and legal values of the parameter.
   * 
   * 
   * As instances of this class are immutable, the return value
   * is computed just once for each instance and reused
   * throughout its life.
   * 
   *
   * @return a @link{java.lang.String} instance representing
   *         the instance in textual form.
   */
  public String toString()
  {
    if (string == null)
      string = getClass().getName()
        + "[name=" + getName()
        + ",openType=" + openType
        + ",defaultValue=" + defaultValue
        + ",minValue=" + minValue
        + ",maxValue=" + maxValue
        + ",legalValues=" + legalValues
        + "]";
    return string;
  }
}