/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.imageio.metadata;

import java.util.Locale;
import javax.imageio.ImageTypeSpecifier;

/**
 * An object describing the structure of metadata documents returned
 * from {@code IIOMetadata.getAsTree} and passed to
 * {@code IIOMetadata.setFromTree} and {@code mergeTree}.
 * Document structures are described by a set of constraints on the
 * type and number of child elements that may belong to a given parent
 * element type, the names, types, and values of attributes that may
 * belong to an element, and the type and values of
 * {@code Object} reference that may be stored at a node.
 *
 * <p> N.B: classes that implement this interface should contain a
 * method declared as {@code public static getInstance()} which
 * returns an instance of the class.  Commonly, an implementation will
 * construct only a single instance and cache it for future
 * invocations of {@code getInstance}.
 * <p> In the event that the plugin is provided as part of a named module,
 * that module must export the package containing the implementation class
 * to the <pre>java.desktop</pre> module via a qualified export.
 * An unqualified export is not recommended unless also needed for
 * some other reason. Failing to export the package will result in
 * access failure at runtime.
 *
 * <p> The structures that may be described by this class are a subset
 * of those expressible using XML document type definitions (DTDs),
 * with the addition of some basic information on the datatypes of
 * attributes and the ability to store an {@code Object}
 * reference within a node.  In the future, XML Schemas could be used
 * to represent these structures, and many others.
 *
 * <p> The differences between
 * {@code IIOMetadataFormat}-described structures and DTDs are as
 * follows:
 *
 * <ul>
 * <li> Elements may not contain text or mix text with embedded
 * tags.
 *
 * <li> The children of an element must conform to one of a few simple
 * patterns, described in the documentation for the
 * {@code CHILD_*} constants;
 *
 * <li> The in-memory representation of an elements may contain a
 * reference to an {@code Object}.  There is no provision for
 * representing such objects textually.
 * </ul>
 *
 */
public interface IIOMetadataFormat {

    // Child policies

    /**
     * A constant returned by {@code getChildPolicy} to indicate
     * that an element may not have any children.  In other words, it
     * is required to be a leaf node.
     */
    int CHILD_POLICY_EMPTY = 0;

    /**
     * A constant returned by {@code getChildPolicy} to indicate
     * that an element must have a single instance of each of its
     * legal child elements, in order.  In DTD terms, the contents of
     * the element are defined by a sequence {@code a,b,c,d,...}.
     */
    int CHILD_POLICY_ALL = 1;

    /**
     * A constant returned by {@code getChildPolicy} to indicate
     * that an element must have zero or one instance of each of its
     * legal child elements, in order.  In DTD terms, the contents of
     * the element are defined by a sequence
     * {@code a?,b?,c?,d?,...}.
     */
    int CHILD_POLICY_SOME = 2;

    /**
     * A constant returned by {@code getChildPolicy} to indicate
     * that an element must have zero or one children, selected from
     * among its legal child elements.  In DTD terms, the contents of
     * the element are defined by a selection
     * {@code a|b|c|d|...}.
     */
    int CHILD_POLICY_CHOICE = 3;

    /**
     * A constant returned by {@code getChildPolicy} to indicate
     * that an element must have a sequence of instances of any of its
     * legal child elements.  In DTD terms, the contents of the
     * element are defined by a sequence {@code (a|b|c|d|...)*}.
     */
    int CHILD_POLICY_SEQUENCE = 4;

    /**
     * A constant returned by {@code getChildPolicy} to indicate
     * that an element must have zero or more instances of its unique
     * legal child element.  In DTD terms, the contents of the element
     * are defined by a starred expression {@code a*}.
     */
    int CHILD_POLICY_REPEAT = 5;

    /**
     * The largest valid {@code CHILD_POLICY_*} constant,
     * to be used for range checks.
     */
    int CHILD_POLICY_MAX = CHILD_POLICY_REPEAT;

    /**
     * A constant returned by {@code getObjectValueType} to
     * indicate the absence of a user object.
     */
    int VALUE_NONE = 0;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set a single, arbitrary value.
     */
    int VALUE_ARBITRARY = 1;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set a range of values.  Both the minimum
     * and maximum values of the range are exclusive.  It is
     * recommended that ranges of integers be inclusive on both ends,
     * and that exclusive ranges be used only for floating-point data.
     *
     * @see #VALUE_RANGE_MIN_MAX_INCLUSIVE
     */
    int VALUE_RANGE = 2;

    /**
     * A value that may be or'ed with {@code VALUE_RANGE} to
     * obtain {@code VALUE_RANGE_MIN_INCLUSIVE}, and with
     * {@code VALUE_RANGE_MAX_INCLUSIVE} to obtain
     * {@code VALUE_RANGE_MIN_MAX_INCLUSIVE}.
     *
     * <p> Similarly, the value may be and'ed with the value of
     * {@code getAttributeValueType} or
     * {@code getObjectValueType} to determine if the minimum
     * value of the range is inclusive.
     */
    int VALUE_RANGE_MIN_INCLUSIVE_MASK = 4;

    /**
     * A value that may be or'ed with {@code VALUE_RANGE} to
     * obtain {@code VALUE_RANGE_MAX_INCLUSIVE}, and with
     * {@code VALUE_RANGE_MIN_INCLUSIVE} to obtain
     * {@code VALUE_RANGE_MIN_MAX_INCLUSIVE}.
     *
     * <p> Similarly, the value may be and'ed with the value of
     * {@code getAttributeValueType} or
     * {@code getObjectValueType} to determine if the maximum
     * value of the range is inclusive.
     */
    int VALUE_RANGE_MAX_INCLUSIVE_MASK = 8;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set to a range of values.  The minimum
     * (but not the maximum) value of the range is inclusive.
     */
    int VALUE_RANGE_MIN_INCLUSIVE = VALUE_RANGE |
        VALUE_RANGE_MIN_INCLUSIVE_MASK;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set to a range of values.  The maximum
     * (but not the minimum) value of the range is inclusive.
     */
    int VALUE_RANGE_MAX_INCLUSIVE = VALUE_RANGE |
        VALUE_RANGE_MAX_INCLUSIVE_MASK;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set a range of values.  Both the minimum
     * and maximum values of the range are inclusive.  It is
     * recommended that ranges of integers be inclusive on both ends,
     * and that exclusive ranges be used only for floating-point data.
     */
    int VALUE_RANGE_MIN_MAX_INCLUSIVE =
        VALUE_RANGE |
        VALUE_RANGE_MIN_INCLUSIVE_MASK |
        VALUE_RANGE_MAX_INCLUSIVE_MASK;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set one of a number of enumerated values.
     * In the case of attributes, these values are
     * {@code String}s; for objects, they are
     * {@code Object}s implementing a given class or interface.
     *
     * <p> Attribute values of type {@code DATATYPE_BOOLEAN}
     * should be marked as enumerations.
     */
    int VALUE_ENUMERATION = 16;

    /**
     * A constant returned by {@code getAttributeValueType} and
     * {@code getObjectValueType} to indicate that the attribute
     * or user object may be set to a list or array of values.  In the
     * case of attributes, the list will consist of
     * whitespace-separated values within a {@code String}; for
     * objects, an array will be used.
     */
    int VALUE_LIST = 32;

    /**
     * A constant returned by {@code getAttributeDataType}
     * indicating that the value of an attribute is a general Unicode
     * string.
     */
    int DATATYPE_STRING = 0;

    /**
     * A constant returned by {@code getAttributeDataType}
     * indicating that the value of an attribute is one of the boolean
     * values 'true' or 'false'.
     * Attribute values of type DATATYPE_BOOLEAN should be marked as
     * enumerations, and the permitted values should be the string
     * literal values "TRUE" or "FALSE", although a plugin may also
     * recognise lower or mixed case equivalents.
     */
    int DATATYPE_BOOLEAN = 1;

    /**
     * A constant returned by {@code getAttributeDataType}
     * indicating that the value of an attribute is a string
     * representation of an integer.
     */
    int DATATYPE_INTEGER = 2;

    /**
     * A constant returned by {@code getAttributeDataType}
     * indicating that the value of an attribute is a string
     * representation of a decimal floating-point number.
     */
    int DATATYPE_FLOAT = 3;

    /**
     * A constant returned by {@code getAttributeDataType}
     * indicating that the value of an attribute is a string
     * representation of a double-precision decimal floating-point
     * number.
     */
    int DATATYPE_DOUBLE = 4;

    // Root

    /**
     * Returns the name of the root element of the format.
     *
     * @return a {@code String}.
     */
    String getRootName();

    // Multiplicity

    /**
     * Returns {@code true} if the element (and the subtree below
     * it) is allowed to appear in a metadata document for an image of
     * the given type, defined by an {@code ImageTypeSpecifier}.
     * For example, a metadata document format might contain an
     * element that describes the primary colors of the image, which
     * would not be allowed when writing a grayscale image.
     *
     * @param elementName the name of the element being queried.
     * @param imageType an {@code ImageTypeSpecifier} indicating
     * the type of the image that will be associated with the
     * metadata.
     *
     * @return {@code true} if the node is meaningful for images
     * of the given type.
     */
    boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType);

    /**
     * Returns the minimum number of children of the named element
     * with child policy {@code CHILD_POLICY_REPEAT}.  For
     * example, an element representing color primary information
     * might be required to have at least 3 children, one for each
     * primary.
     *
     * @param elementName the name of the element being queried.
     *
     * @return an {@code int}.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element does
     * not have a child policy of {@code CHILD_POLICY_REPEAT}.
     */
    int getElementMinChildren(String elementName);

    /**
     * Returns the maximum number of children of the named element
     * with child policy {@code CHILD_POLICY_REPEAT}.  For
     * example, an element representing an entry in an 8-bit color
     * palette might be allowed to repeat up to 256 times.  A value of
     * {@code Integer.MAX_VALUE} may be used to specify that
     * there is no upper bound.
     *
     * @param elementName the name of the element being queried.
     *
     * @return an {@code int}.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element does
     * not have a child policy of {@code CHILD_POLICY_REPEAT}.
     */
    int getElementMaxChildren(String elementName);

    /**
     * Returns a {@code String} containing a description of the
     * named element, or {@code null}.  The description will be
     * localized for the supplied {@code Locale} if possible.
     *
     * <p> If {@code locale} is {@code null}, the current
     * default {@code Locale} returned by {@code Locale.getLocale}
     * will be used.
     *
     * @param elementName the name of the element.
     * @param locale the {@code Locale} for which localization
     * will be attempted.
     *
     * @return the element description.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null}, or is not a legal element name for this format.
     */
    String getElementDescription(String elementName, Locale locale);

    // Children

    /**
     * Returns one of the constants starting with
     * {@code CHILD_POLICY_}, indicating the legal pattern of
     * children for the named element.
     *
     * @param elementName the name of the element being queried.
     *
     * @return one of the {@code CHILD_POLICY_*} constants.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     */
    int getChildPolicy(String elementName);

    /**
     * Returns an array of {@code String}s indicating the names
     * of the element which are allowed to be children of the named
     * element, in the order in which they should appear.  If the
     * element cannot have children, {@code null} is returned.
     *
     * @param elementName the name of the element being queried.
     *
     * @return an array of {@code String}s, or null.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     */
    String[] getChildNames(String elementName);

    // Attributes

    /**
     * Returns an array of {@code String}s listing the names of
     * the attributes that may be associated with the named element.
     *
     * @param elementName the name of the element being queried.
     *
     * @return an array of {@code String}s.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     */
    String[] getAttributeNames(String elementName);

    /**
     * Returns one of the constants starting with {@code VALUE_},
     * indicating whether the values of the given attribute within the
     * named element are arbitrary, constrained to lie within a
     * specified range, constrained to be one of a set of enumerated
     * values, or are a whitespace-separated list of arbitrary values.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return one of the {@code VALUE_*} constants.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     */
    int getAttributeValueType(String elementName, String attrName);

    /**
     * Returns one of the constants starting with
     * {@code DATATYPE_}, indicating the format and
     * interpretation of the value of the given attribute within the
     * named element.  If {@code getAttributeValueType} returns
     * {@code VALUE_LIST}, then the legal value is a
     * whitespace-spearated list of values of the returned datatype.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return one of the {@code DATATYPE_*} constants.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     */
    int getAttributeDataType(String elementName, String attrName);

    /**
     * Returns {@code true} if the named attribute must be
     * present within the named element.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return {@code true} if the attribute must be present.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     */
    boolean isAttributeRequired(String elementName, String attrName);

    /**
     * Returns the default value of the named attribute, if it is not
     * explicitly present within the named element, as a
     * {@code String}, or {@code null} if no default value
     * is available.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return a {@code String} containing the default value, or
     * {@code null}.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     */
    String getAttributeDefaultValue(String elementName, String attrName);

    /**
     * Returns an array of {@code String}s containing the legal
     * enumerated values for the given attribute within the named
     * element.  This method should only be called if
     * {@code getAttributeValueType} returns
     * {@code VALUE_ENUMERATION}.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return an array of {@code String}s.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     * @throws IllegalArgumentException if the given attribute is
     * not defined as an enumeration.
     */
    String[] getAttributeEnumerations(String elementName, String attrName);

    /**
     * Returns the minimum legal value for the attribute.  Whether
     * this value is inclusive or exclusive may be determined by the
     * value of {@code getAttributeValueType}.  The value is
     * returned as a {@code String}; its interpretation is
     * dependent on the value of {@code getAttributeDataType}.
     * This method should only be called if
     * {@code getAttributeValueType} returns
     * {@code VALUE_RANGE_*}.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return a {@code String} containing the smallest legal
     * value for the attribute.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     * @throws IllegalArgumentException if the given attribute is
     * not defined as a range.
     */
    String getAttributeMinValue(String elementName, String attrName);

    /**
     * Returns the maximum legal value for the attribute.  Whether
     * this value is inclusive or exclusive may be determined by the
     * value of {@code getAttributeValueType}.  The value is
     * returned as a {@code String}; its interpretation is
     * dependent on the value of {@code getAttributeDataType}.
     * This method should only be called if
     * {@code getAttributeValueType} returns
     * {@code VALUE_RANGE_*}.
     *
     * @param elementName the name of the element being queried, as a
     * {@code String}.
     * @param attrName the name of the attribute being queried.
     *
     * @return a {@code String} containing the largest legal
     * value for the attribute.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     * @throws IllegalArgumentException if the given attribute is
     * not defined as a range.
     */
    String getAttributeMaxValue(String elementName, String attrName);

    /**
     * Returns the minimum number of list items that may be used to
     * define this attribute.  The attribute itself is defined as a
     * {@code String} containing multiple whitespace-separated
     * items.  This method should only be called if
     * {@code getAttributeValueType} returns
     * {@code VALUE_LIST}.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return the smallest legal number of list items for the
     * attribute.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     * @throws IllegalArgumentException if the given attribute is
     * not defined as a list.
     */
    int getAttributeListMinLength(String elementName, String attrName);

    /**
     * Returns the maximum number of list items that may be used to
     * define this attribute.  A value of
     * {@code Integer.MAX_VALUE} may be used to specify that
     * there is no upper bound.  The attribute itself is defined as a
     * {@code String} containing multiple whitespace-separated
     * items.  This method should only be called if
     * {@code getAttributeValueType} returns
     * {@code VALUE_LIST}.
     *
     * @param elementName the name of the element being queried.
     * @param attrName the name of the attribute being queried.
     *
     * @return the largest legal number of list items for the
     * attribute.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     * @throws IllegalArgumentException if the given attribute is
     * not defined as a list.
     */
    int getAttributeListMaxLength(String elementName, String attrName);

    /**
     * Returns a {@code String} containing a description of the
     * named attribute, or {@code null}.  The description will be
     * localized for the supplied {@code Locale} if possible.
     *
     * <p> If {@code locale} is {@code null}, the current
     * default {@code Locale} returned by {@code Locale.getLocale}
     * will be used.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute.
     * @param locale the {@code Locale} for which localization
     * will be attempted.
     *
     * @return the attribute description.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null}, or is not a legal element name for this format.
     * @throws IllegalArgumentException if {@code attrName} is
     * {@code null} or is not a legal attribute name for this
     * element.
     */
    String getAttributeDescription(String elementName, String attrName,
                                   Locale locale);

    // Object value

    /**
     * Returns one of the enumerated values starting with
     * {@code VALUE_}, indicating the type of values
     * (enumeration, range, or array) that are allowed for the
     * {@code Object} reference.  If no object value can be
     * stored within the given element, the result of this method will
     * be {@code VALUE_NONE}.
     *
     * <p> {@code Object} references whose legal values are
     * defined as a range must implement the {@code Comparable}
     * interface.
     *
     * @param elementName the name of the element being queried.
     *
     * @return one of the {@code VALUE_*} constants.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     *
     * @see Comparable
     */
    int getObjectValueType(String elementName);

    /**
     * Returns the {@code Class} type of the {@code Object}
     * reference stored within the element.  If this element may not
     * contain an {@code Object} reference, an
     * {@code IllegalArgumentException} will be thrown.  If the
     * class type is an array, this field indicates the underlying
     * class type (<i>e.g</i>, for an array of {@code int}s, this
     * method would return {@code int.class}).
     *
     * <p> {@code Object} references whose legal values are
     * defined as a range must implement the {@code Comparable}
     * interface.
     *
     * @param elementName the name of the element being queried.
     *
     * @return a {@code Class} object.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     */
    Class<?> getObjectClass(String elementName);

    /**
     * Returns an {@code Object}s containing the default
     * value for the {@code Object} reference within
     * the named element.
     *
     * @param elementName the name of the element being queried.
     *
     * @return an {@code Object}.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     */
    Object getObjectDefaultValue(String elementName);

    /**
     * Returns an array of {@code Object}s containing the legal
     * enumerated values for the {@code Object} reference within
     * the named element.  This method should only be called if
     * {@code getObjectValueType} returns
     * {@code VALUE_ENUMERATION}.
     *
     * <p> The {@code Object} associated with a node that accepts
     * enumerated values must be equal to one of the values returned by
     * this method, as defined by the {@code ==} operator (as
     * opposed to the {@code Object.equals} method).
     *
     * @param elementName the name of the element being queried.
     *
     * @return an array of {@code Object}s.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     * @throws IllegalArgumentException if the {@code Object}
     * is not defined as an enumeration.
     */
    Object[] getObjectEnumerations(String elementName);

    /**
     * Returns the minimum legal value for the {@code Object}
     * reference within the named element.  Whether this value is
     * inclusive or exclusive may be determined by the value of
     * {@code getObjectValueType}.  This method should only be
     * called if {@code getObjectValueType} returns one of the
     * constants starting with {@code VALUE_RANGE}.
     *
     * @param elementName the name of the element being queried.
     *
     * @return the smallest legal value for the attribute.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     * @throws IllegalArgumentException if the {@code Object}
     * is not defined as a range.
     */
    Comparable<?> getObjectMinValue(String elementName);

    /**
     * Returns the maximum legal value for the {@code Object}
     * reference within the named element.  Whether this value is
     * inclusive or exclusive may be determined by the value of
     * {@code getObjectValueType}.  This method should only be
     * called if {@code getObjectValueType} returns one of the
     * constants starting with {@code VALUE_RANGE}.
     *
     * @return the smallest legal value for the attribute.
     *
     * @param elementName the name of the element being queried.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     * @throws IllegalArgumentException if the {@code Object}
     * is not defined as a range.
     */
    Comparable<?> getObjectMaxValue(String elementName);

    /**
     * Returns the minimum number of array elements that may be used
     * to define the {@code Object} reference within the named
     * element.  This method should only be called if
     * {@code getObjectValueType} returns
     * {@code VALUE_LIST}.
     *
     * @param elementName the name of the element being queried.
     *
     * @return the smallest valid array length for the
     * {@code Object} reference.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     * @throws IllegalArgumentException if the {@code Object} is not
     * an array.
     */
    int getObjectArrayMinLength(String elementName);

    /**
     * Returns the maximum number of array elements that may be used
     * to define the {@code Object} reference within the named
     * element.  A value of {@code Integer.MAX_VALUE} may be used
     * to specify that there is no upper bound.  This method should
     * only be called if {@code getObjectValueType} returns
     * {@code VALUE_LIST}.
     *
     * @param elementName the name of the element being queried.
     *
     * @return the largest valid array length for the
     * {@code Object} reference.
     *
     * @throws IllegalArgumentException if {@code elementName}
     * is {@code null} or is not a legal element name for this
     * format.
     * @throws IllegalArgumentException if the named element cannot
     * contain an object value (<i>i.e.</i>, if
     * {@code getObjectValueType(elementName) == VALUE_NONE}).
     * @throws IllegalArgumentException if the {@code Object} is not
     * an array.
     */
    int getObjectArrayMaxLength(String elementName);
}
