/*
 * Copyright 2000-2004 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.imageio.metadata;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.imageio.ImageTypeSpecifier;
import com.sun.imageio.plugins.common.StandardMetadataFormat;

/**
 * A concrete class providing a reusable implementation of the
 * <code>IIOMetadataFormat</code> interface.  In addition, a static
 * instance representing the standard, plug-in neutral
 * <code>javax_imageio_1.0</code> format is provided by the
 * <code>getStandardFormatInstance</code> method.
 *
 * <p> In order to supply localized descriptions of elements and
 * attributes, a <code>ResourceBundle</code> with a base name of
 * <code>this.getClass().getName() + "Resources"</code> should be
 * supplied via the usual mechanism used by
 * <code>ResourceBundle.getBundle</code>.  Briefly, the subclasser
 * supplies one or more additional classes according to a naming
 * convention (by default, the fully-qualified name of the subclass
 * extending <code>IIMetadataFormatImpl</code>, plus the string
 * "Resources", plus the country, language, and variant codes
 * separated by underscores).  At run time, calls to
 * <code>getElementDescription</code> or
 * <code>getAttributeDescription</code> will attempt to load such
 * classes dynamically according to the supplied locale, and will use
 * either the element name, or the element name followed by a '/'
 * character followed by the attribute name as a key.  This key will
 * be supplied to the <code>ResourceBundle</code>'s
 * <code>getString</code> method, and the resulting localized
 * description of the node or attribute is returned.
 *
 * <p> The subclass may supply a different base name for the resource
 * bundles using the <code>setResourceBaseName</code> method.
 *
 * <p> A subclass may choose its own localization mechanism, if so
 * desired, by overriding the supplied implementations of
 * <code>getElementDescription</code> and
 * <code>getAttributeDescription</code>.
 *
 * @see ResourceBundle#getBundle(String,Locale)
 *
 */
public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat {

    /**
     * A <code>String</code> constant containing the standard format
     * name, <code>"javax_imageio_1.0"</code>.
     */
    public static final String standardMetadataFormatName =
        "javax_imageio_1.0";

    private static IIOMetadataFormat standardFormat = null;

    private String resourceBaseName = this.getClass().getName() + "Resources";

    private String rootName;

    // Element name (String) -> Element
    private HashMap elementMap = new HashMap();

    class Element {
        String elementName;

        int childPolicy;
        int minChildren = 0;
        int maxChildren = 0;

        // Child names (Strings)
        List childList = new ArrayList();

        // Parent names (Strings)
        List parentList = new ArrayList();

        // List of attribute names in the order they were added
        List attrList = new ArrayList();
        // Attr name (String) -> Attribute
        Map attrMap = new HashMap();

        ObjectValue objectValue;
    }

    class Attribute {
        String attrName;

        int valueType = VALUE_ARBITRARY;
        int dataType;
        boolean required;
        String defaultValue = null;

        // enumeration
        List enumeratedValues;

        // range
        String minValue;
        String maxValue;

        // list
        int listMinLength;
        int listMaxLength;
    }

    class ObjectValue {
        int valueType = VALUE_NONE;
        Class classType = null;
        Object defaultValue = null;

        // Meaningful only if valueType == VALUE_ENUMERATION
        List enumeratedValues = null;

        // Meaningful only if valueType == VALUE_RANGE
        Comparable minValue = null;
        Comparable maxValue = null;

        // Meaningful only if valueType == VALUE_LIST
        int arrayMinLength = 0;
        int arrayMaxLength = 0;
    }

    /**
     * Constructs a blank <code>IIOMetadataFormatImpl</code> instance,
     * with a given root element name and child policy (other than
     * <code>CHILD_POLICY_REPEAT</code>).  Additional elements, and
     * their attributes and <code>Object</code> reference information
     * may be added using the various <code>add</code> methods.
     *
     * @param rootName the name of the root element.
     * @param childPolicy one of the <code>CHILD_POLICY_*</code> constants,
     * other than <code>CHILD_POLICY_REPEAT</code>.
     *
     * @exception IllegalArgumentException if <code>rootName</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>childPolicy</code> is
     * not one of the predefined constants.
     */
    public IIOMetadataFormatImpl(String rootName,
                                 int childPolicy) {
        if (rootName == null) {
            throw new IllegalArgumentException("rootName == null!");
        }
        if (childPolicy < CHILD_POLICY_EMPTY ||
            childPolicy > CHILD_POLICY_MAX ||
            childPolicy == CHILD_POLICY_REPEAT) {
            throw new IllegalArgumentException("Invalid value for childPolicy!");
        }

        this.rootName = rootName;

        Element root = new Element();
        root.elementName = rootName;
        root.childPolicy = childPolicy;

        elementMap.put(rootName, root);
    }

    /**
     * Constructs a blank <code>IIOMetadataFormatImpl</code> instance,
     * with a given root element name and a child policy of
     * <code>CHILD_POLICY_REPEAT</code>.  Additional elements, and
     * their attributes and <code>Object</code> reference information
     * may be added using the various <code>add</code> methods.
     *
     * @param rootName the name of the root element.
     * @param minChildren the minimum number of children of the node.
     * @param maxChildren the maximum number of children of the node.
     *
     * @exception IllegalArgumentException if <code>rootName</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>minChildren</code>
     * is negative or larger than <code>maxChildren</code>.
     */
    public IIOMetadataFormatImpl(String rootName,
                                 int minChildren,
                                 int maxChildren) {
        if (rootName == null) {
            throw new IllegalArgumentException("rootName == null!");
        }
        if (minChildren < 0) {
            throw new IllegalArgumentException("minChildren < 0!");
        }
        if (minChildren > maxChildren) {
            throw new IllegalArgumentException("minChildren > maxChildren!");
        }

        Element root = new Element();
        root.elementName = rootName;
        root.childPolicy = CHILD_POLICY_REPEAT;
        root.minChildren = minChildren;
        root.maxChildren = maxChildren;

        this.rootName = rootName;
        elementMap.put(rootName, root);
    }

    /**
     * Sets a new base name for locating <code>ResourceBundle</code>s
     * containing descriptions of elements and attributes for this
     * format.
     *
     * <p> Prior to the first time this method is called, the base
     * name will be equal to <code>this.getClass().getName() +
     * "Resources"</code>.
     *
     * @param resourceBaseName a <code>String</code> containg the new
     * base name.
     *
     * @exception IllegalArgumentException if
     * <code>resourceBaseName</code> is <code>null</code>.
     *
     * @see #getResourceBaseName
     */
    protected void setResourceBaseName(String resourceBaseName) {
        if (resourceBaseName == null) {
            throw new IllegalArgumentException("resourceBaseName == null!");
        }
        this.resourceBaseName = resourceBaseName;
    }

    /**
     * Returns the currently set base name for locating
     * <code>ResourceBundle</code>s.
     *
     * @return a <code>String</code> containing the base name.
     *
     * @see #setResourceBaseName
     */
    protected String getResourceBaseName() {
        return resourceBaseName;
    }

    /**
     * Utility method for locating an element.
     *
     * @param mustAppear if <code>true</code>, throw an
     * <code>IllegalArgumentException</code> if no such node exists;
     * if <code>false</code>, just return null.
     */
    private Element getElement(String elementName, boolean mustAppear) {
        if (mustAppear && (elementName == null)) {
            throw new IllegalArgumentException("element name is null!");
        }
        Element element = (Element)elementMap.get(elementName);
        if (mustAppear && (element == null)) {
            throw new IllegalArgumentException("No such element: " +
                                               elementName);
        }
        return element;
    }

    private Element getElement(String elementName) {
        return getElement(elementName, true);
    }

    // Utility method for locating an attribute
    private Attribute getAttribute(String elementName, String attrName) {
        Element element = getElement(elementName);
        Attribute attr = (Attribute)element.attrMap.get(attrName);
        if (attr == null) {
            throw new IllegalArgumentException("No such attribute \"" +
                                               attrName + "\"!");
        }
        return attr;
    }

    // Setup

    /**
     * Adds a new element type to this metadata document format with a
     * child policy other than <code>CHILD_POLICY_REPEAT</code>.
     *
     * @param elementName the name of the new element.
     * @param parentName the name of the element that will be the
     * parent of the new element.
     * @param childPolicy one of the <code>CHILD_POLICY_*</code>
     * constants, other than <code>CHILD_POLICY_REPEAT</code>,
     * indicating the child policy of the new element.
     *
     * @exception IllegalArgumentException if <code>parentName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>childPolicy</code>
     * is not one of the predefined constants.
     */
    protected void addElement(String elementName,
                              String parentName,
                              int childPolicy) {
        Element parent = getElement(parentName);
        if (childPolicy < CHILD_POLICY_EMPTY ||
            childPolicy > CHILD_POLICY_MAX ||
            childPolicy == CHILD_POLICY_REPEAT) {
            throw new IllegalArgumentException
                ("Invalid value for childPolicy!");
        }

        Element element = new Element();
        element.elementName = elementName;
        element.childPolicy = childPolicy;

        parent.childList.add(elementName);
        element.parentList.add(parentName);

        elementMap.put(elementName, element);
    }

    /**
     * Adds a new element type to this metadata document format with a
     * child policy of <code>CHILD_POLICY_REPEAT</code>.
     *
     * @param elementName the name of the new element.
     * @param parentName the name of the element that will be the
     * parent of the new element.
     * @param minChildren the minimum number of children of the node.
     * @param maxChildren the maximum number of children of the node.
     *
     * @exception IllegalArgumentException if <code>parentName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>minChildren</code>
     * is negative or larger than <code>maxChildren</code>.
     */
    protected void addElement(String elementName,
                              String parentName,
                              int minChildren,
                              int maxChildren) {
        Element parent = getElement(parentName);
        if (minChildren < 0) {
            throw new IllegalArgumentException("minChildren < 0!");
        }
        if (minChildren > maxChildren) {
            throw new IllegalArgumentException("minChildren > maxChildren!");
        }

        Element element = new Element();
        element.elementName = elementName;
        element.childPolicy = CHILD_POLICY_REPEAT;
        element.minChildren = minChildren;
        element.maxChildren = maxChildren;

        parent.childList.add(elementName);
        element.parentList.add(parentName);

        elementMap.put(elementName, element);
    }

    /**
     * Adds an existing element to the list of legal children for a
     * given parent node type.
     *
     * @param parentName the name of the element that will be the
     * new parent of the element.
     * @param elementName the name of the element to be addded as a
     * child.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>parentName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     */
    protected void addChildElement(String elementName, String parentName) {
        Element parent = getElement(parentName);
        Element element = getElement(elementName);
        parent.childList.add(elementName);
        element.parentList.add(parentName);
    }

    /**
     * Removes an element from the format.  If no element with the
     * given name was present, nothing happens and no exception is
     * thrown.
     *
     * @param elementName the name of the element to be removed.
     */
    protected void removeElement(String elementName) {
        Element element = getElement(elementName, false);
        if (element != null) {
            Iterator iter = element.parentList.iterator();
            while (iter.hasNext()) {
                String parentName = (String)iter.next();
                Element parent = getElement(parentName, false);
                if (parent != null) {
                    parent.childList.remove(elementName);
                }
            }
            elementMap.remove(elementName);
        }
    }

    /**
     * Adds a new attribute to a previously defined element that may
     * be set to an arbitrary value.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute being added.
     * @param dataType the data type (string format) of the attribute,
     * one of the <code>DATATYPE_*</code> constants.
     * @param required <code>true</code> if the attribute must be present.
     * @param defaultValue the default value for the attribute, or
     * <code>null</code>.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>attrName</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of the predefined constants.
     */
    protected void addAttribute(String elementName,
                                String attrName,
                                int dataType,
                                boolean required,
                                String defaultValue) {
        Element element = getElement(elementName);
        if (attrName == null) {
            throw new IllegalArgumentException("attrName == null!");
        }
        if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
            throw new IllegalArgumentException("Invalid value for dataType!");
        }

        Attribute attr = new Attribute();
        attr.attrName = attrName;
        attr.valueType = VALUE_ARBITRARY;
        attr.dataType = dataType;
        attr.required = required;
        attr.defaultValue = defaultValue;

        element.attrList.add(attrName);
        element.attrMap.put(attrName, attr);
    }

    /**
     * Adds a new attribute to a previously defined element that will
     * be defined by a set of enumerated values.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute being added.
     * @param dataType the data type (string format) of the attribute,
     * one of the <code>DATATYPE_*</code> constants.
     * @param required <code>true</code> if the attribute must be present.
     * @param defaultValue the default value for the attribute, or
     * <code>null</code>.
     * @param enumeratedValues a <code>List</code> of
     * <code>String</code>s containing the legal values for the
     * attribute.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>attrName</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of the predefined constants.
     * @exception IllegalArgumentException if
     * <code>enumeratedValues</code> is <code>null</code>.
     * @exception IllegalArgumentException if
     * <code>enumeratedValues</code> does not contain at least one
     * entry.
     * @exception IllegalArgumentException if
     * <code>enumeratedValues</code> contains an element that is not a
     * <code>String</code> or is <code>null</code>.
     */
    protected void addAttribute(String elementName,
                                String attrName,
                                int dataType,
                                boolean required,
                                String defaultValue,
                                List<String> enumeratedValues) {
        Element element = getElement(elementName);
        if (attrName == null) {
            throw new IllegalArgumentException("attrName == null!");
        }
        if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
            throw new IllegalArgumentException("Invalid value for dataType!");
        }
        if (enumeratedValues == null) {
            throw new IllegalArgumentException("enumeratedValues == null!");
        }
        if (enumeratedValues.size() == 0) {
            throw new IllegalArgumentException("enumeratedValues is empty!");
        }
        Iterator iter = enumeratedValues.iterator();
        while (iter.hasNext()) {
            Object o = iter.next();
            if (o == null) {
                throw new IllegalArgumentException
                    ("enumeratedValues contains a null!");
            }
            if (!(o instanceof String)) {
                throw new IllegalArgumentException
                    ("enumeratedValues contains a non-String value!");
            }
        }

        Attribute attr = new Attribute();
        attr.attrName = attrName;
        attr.valueType = VALUE_ENUMERATION;
        attr.dataType = dataType;
        attr.required = required;
        attr.defaultValue = defaultValue;
        attr.enumeratedValues = enumeratedValues;

        element.attrList.add(attrName);
        element.attrMap.put(attrName, attr);
    }

    /**
     * Adds a new attribute to a previously defined element that will
     * be defined by a range of values.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute being added.
     * @param dataType the data type (string format) of the attribute,
     * one of the <code>DATATYPE_*</code> constants.
     * @param required <code>true</code> if the attribute must be present.
     * @param defaultValue the default value for the attribute, or
     * <code>null</code>.
     * @param minValue the smallest (inclusive or exclusive depending
     * on the value of <code>minInclusive</code>) legal value for the
     * attribute, as a <code>String</code>.
     * @param maxValue the largest (inclusive or exclusive depending
     * on the value of <code>minInclusive</code>) legal value for the
     * attribute, as a <code>String</code>.
     * @param minInclusive <code>true</code> if <code>minValue</code>
     * is inclusive.
     * @param maxInclusive <code>true</code> if <code>maxValue</code>
     * is inclusive.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>attrName</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of the predefined constants.
     */
    protected void addAttribute(String elementName,
                                String attrName,
                                int dataType,
                                boolean required,
                                String defaultValue,
                                String minValue,
                                String maxValue,
                                boolean minInclusive,
                                boolean maxInclusive) {
        Element element = getElement(elementName);
        if (attrName == null) {
            throw new IllegalArgumentException("attrName == null!");
        }
        if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
            throw new IllegalArgumentException("Invalid value for dataType!");
        }

        Attribute attr = new Attribute();
        attr.attrName = attrName;
        attr.valueType = VALUE_RANGE;
        if (minInclusive) {
            attr.valueType |= VALUE_RANGE_MIN_INCLUSIVE_MASK;
        }
        if (maxInclusive) {
            attr.valueType |= VALUE_RANGE_MAX_INCLUSIVE_MASK;
        }
        attr.dataType = dataType;
        attr.required = required;
        attr.defaultValue = defaultValue;
        attr.minValue = minValue;
        attr.maxValue = maxValue;

        element.attrList.add(attrName);
        element.attrMap.put(attrName, attr);
    }

    /**
     * Adds a new attribute to a previously defined element that will
     * be defined by a list of values.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute being added.
     * @param dataType the data type (string format) of the attribute,
     * one of the <code>DATATYPE_*</code> constants.
     * @param required <code>true</code> if the attribute must be present.
     * @param listMinLength the smallest legal number of list items.
     * @param listMaxLength the largest legal number of list items.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>attrName</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of the predefined constants.
     * @exception IllegalArgumentException if
     * <code>listMinLength</code> is negative or larger than
     * <code>listMaxLength</code>.
     */
    protected void addAttribute(String elementName,
                                String attrName,
                                int dataType,
                                boolean required,
                                int listMinLength,
                                int listMaxLength) {
        Element element = getElement(elementName);
        if (attrName == null) {
            throw new IllegalArgumentException("attrName == null!");
        }
        if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
            throw new IllegalArgumentException("Invalid value for dataType!");
        }
        if (listMinLength < 0 || listMinLength > listMaxLength) {
            throw new IllegalArgumentException("Invalid list bounds!");
        }

        Attribute attr = new Attribute();
        attr.attrName = attrName;
        attr.valueType = VALUE_LIST;
        attr.dataType = dataType;
        attr.required = required;
        attr.listMinLength = listMinLength;
        attr.listMaxLength = listMaxLength;

        element.attrList.add(attrName);
        element.attrMap.put(attrName, attr);
    }

    /**
     * Adds a new attribute to a previously defined element that will
     * be defined by the enumerated values <code>TRUE</code> and
     * <code>FALSE</code>, with a datatype of
     * <code>DATATYPE_BOOLEAN</code>.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute being added.
     * @param hasDefaultValue <code>true</code> if a default value
     * should be present.
     * @param defaultValue the default value for the attribute as a
     * <code>boolean</code>, ignored if <code>hasDefaultValue</code>
     * is <code>false</code>.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     * @exception IllegalArgumentException if <code>attrName</code> is
     * <code>null</code>.
     */
    protected void addBooleanAttribute(String elementName,
                                       String attrName,
                                       boolean hasDefaultValue,
                                       boolean defaultValue) {
        List values = new ArrayList();
        values.add("TRUE");
        values.add("FALSE");

        String dval = null;
        if (hasDefaultValue) {
            dval = defaultValue ? "TRUE" : "FALSE";
        }
        addAttribute(elementName,
                     attrName,
                     DATATYPE_BOOLEAN,
                     true,
                     dval,
                     values);
    }

    /**
     * Removes an attribute from a previously defined element.  If no
     * attribute with the given name was present in the given element,
     * nothing happens and no exception is thrown.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute being removed.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this format.
     */
    protected void removeAttribute(String elementName, String attrName) {
        Element element = getElement(elementName);
        element.attrList.remove(attrName);
        element.attrMap.remove(attrName);
    }

    /**
     * Allows an <code>Object</code> reference of a given class type
     * to be stored in nodes implementing the named element.  The
     * value of the <code>Object</code> is unconstrained other than by
     * its class type.
     *
     * <p> If an <code>Object</code> reference was previously allowed,
     * the previous settings are overwritten.
     *
     * @param elementName the name of the element.
     * @param classType a <code>Class</code> variable indicating the
     * legal class type for the object value.
     * @param required <code>true</code> if an object value must be present.
     * @param defaultValue the default value for the
     * <code>Object</code> reference, or <code>null</code>.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this format.
     */
    protected <T> void addObjectValue(String elementName,
                                      Class<T> classType,
                                      boolean required,
                                      T defaultValue)
    {
        Element element = getElement(elementName);
        ObjectValue obj = new ObjectValue();
        obj.valueType = VALUE_ARBITRARY;
        obj.classType = classType;
        obj.defaultValue = defaultValue;

        element.objectValue = obj;
    }

    /**
     * Allows an <code>Object</code> reference of a given class type
     * to be stored in nodes implementing the named element.  The
     * value of the <code>Object</code> must be one of the values
     * given by <code>enumeratedValues</code>.
     *
     * <p> If an <code>Object</code> reference was previously allowed,
     * the previous settings are overwritten.
     *
     * @param elementName the name of the element.
     * @param classType a <code>Class</code> variable indicating the
     * legal class type for the object value.
     * @param required <code>true</code> if an object value must be present.
     * @param defaultValue the default value for the
     * <code>Object</code> reference, or <code>null</code>.
     * @param enumeratedValues a <code>List</code> of
     * <code>Object</code>s containing the legal values for the
     * object reference.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this format.
     * @exception IllegalArgumentException if
     * <code>enumeratedValues</code> is <code>null</code>.
     * @exception IllegalArgumentException if
     * <code>enumeratedValues</code> does not contain at least one
     * entry.
     * @exception IllegalArgumentException if
     * <code>enumeratedValues</code> contains an element that is not
     * an instance of the class type denoted by <code>classType</code>
     * or is <code>null</code>.
     */
    protected <T> void addObjectValue(String elementName,
                                      Class<T> classType,
                                      boolean required,
                                      T defaultValue,
                                      List<? extends T> enumeratedValues)
    {
        Element element = getElement(elementName);
        if (enumeratedValues == null) {
            throw new IllegalArgumentException("enumeratedValues == null!");
        }
        if (enumeratedValues.size() == 0) {
            throw new IllegalArgumentException("enumeratedValues is empty!");
        }
        Iterator iter = enumeratedValues.iterator();
        while (iter.hasNext()) {
            Object o = iter.next();
            if (o == null) {
                throw new IllegalArgumentException("enumeratedValues contains a null!");
            }
            if (!classType.isInstance(o)) {
                throw new IllegalArgumentException("enumeratedValues contains a value not of class classType!");
            }
        }

        ObjectValue obj = new ObjectValue();
        obj.valueType = VALUE_ENUMERATION;
        obj.classType = classType;
        obj.defaultValue = defaultValue;
        obj.enumeratedValues = enumeratedValues;

        element.objectValue = obj;
    }

    /**
     * Allows an <code>Object</code> reference of a given class type
     * to be stored in nodes implementing the named element.  The
     * value of the <code>Object</code> must be within the range given
     * by <code>minValue</code> and <code>maxValue</code>.
     * Furthermore, the class type must implement the
     * <code>Comparable</code> interface.
     *
     * <p> If an <code>Object</code> reference was previously allowed,
     * the previous settings are overwritten.
     *
     * @param elementName the name of the element.
     * @param classType a <code>Class</code> variable indicating the
     * legal class type for the object value.
     * @param defaultValue the default value for the
     * @param minValue the smallest (inclusive or exclusive depending
     * on the value of <code>minInclusive</code>) legal value for the
     * object value, as a <code>String</code>.
     * @param maxValue the largest (inclusive or exclusive depending
     * on the value of <code>minInclusive</code>) legal value for the
     * object value, as a <code>String</code>.
     * @param minInclusive <code>true</code> if <code>minValue</code>
     * is inclusive.
     * @param maxInclusive <code>true</code> if <code>maxValue</code>
     * is inclusive.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this
     * format.
     */
    protected <T extends Object & Comparable<? super T>> void
        addObjectValue(String elementName,
                       Class<T> classType,
                       T defaultValue,
                       Comparable<? super T> minValue,
                       Comparable<? super T> maxValue,
                       boolean minInclusive,
                       boolean maxInclusive)
    {
        Element element = getElement(elementName);
        ObjectValue obj = new ObjectValue();
        obj.valueType = VALUE_RANGE;
        if (minInclusive) {
            obj.valueType |= VALUE_RANGE_MIN_INCLUSIVE_MASK;
        }
        if (maxInclusive) {
            obj.valueType |= VALUE_RANGE_MAX_INCLUSIVE_MASK;
        }
        obj.classType = classType;
        obj.defaultValue = defaultValue;
        obj.minValue = minValue;
        obj.maxValue = maxValue;

        element.objectValue = obj;
    }

    /**
     * Allows an <code>Object</code> reference of a given class type
     * to be stored in nodes implementing the named element.  The
     * value of the <code>Object</code> must an array of objects of
     * class type given by <code>classType</code>, with at least
     * <code>arrayMinLength</code> and at most
     * <code>arrayMaxLength</code> elements.
     *
     * <p> If an <code>Object</code> reference was previously allowed,
     * the previous settings are overwritten.
     *
     * @param elementName the name of the element.
     * @param classType a <code>Class</code> variable indicating the
     * legal class type for the object value.
     * @param arrayMinLength the smallest legal length for the array.
     * @param arrayMaxLength the largest legal length for the array.
     *
     * @exception IllegalArgumentException if <code>elementName</code> is
     * not a legal element name for this format.
     */
    protected void addObjectValue(String elementName,
                                  Class<?> classType,
                                  int arrayMinLength,
                                  int arrayMaxLength) {
        Element element = getElement(elementName);
        ObjectValue obj = new ObjectValue();
        obj.valueType = VALUE_LIST;
        obj.classType = classType;
        obj.arrayMinLength = arrayMinLength;
        obj.arrayMaxLength = arrayMaxLength;

        element.objectValue = obj;
    }

    /**
     * Disallows an <code>Object</code> reference from being stored in
     * nodes implementing the named element.
     *
     * @param elementName the name of the element.
     *
     * @exception IllegalArgumentException if <code>elementName</code> is
     * not a legal element name for this format.
     */
    protected void removeObjectValue(String elementName) {
        Element element = getElement(elementName);
        element.objectValue = null;
    }

    // Utility method

    // Methods from IIOMetadataFormat

    // Root

    public String getRootName() {
        return rootName;
    }

    // Multiplicity

    public abstract boolean canNodeAppear(String elementName,
                                          ImageTypeSpecifier imageType);

    public int getElementMinChildren(String elementName) {
        Element element = getElement(elementName);
        if (element.childPolicy != CHILD_POLICY_REPEAT) {
            throw new IllegalArgumentException("Child policy not CHILD_POLICY_REPEAT!");
        }
        return element.minChildren;
    }

    public int getElementMaxChildren(String elementName) {
        Element element = getElement(elementName);
        if (element.childPolicy != CHILD_POLICY_REPEAT) {
            throw new IllegalArgumentException("Child policy not CHILD_POLICY_REPEAT!");
        }
        return element.maxChildren;
    }

    private String getResource(String key, Locale locale) {
        if (locale == null) {
            locale = Locale.getDefault();
        }

        /**
         * If an applet supplies an implementation of IIOMetadataFormat and
         * resource bundles, then the resource bundle will need to be
         * accessed via the applet class loader. So first try the context
         * class loader to locate the resource bundle.
         * If that throws MissingResourceException, then try the
         * system class loader.
         */
        ClassLoader loader = (ClassLoader)
            java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction() {
                   public Object run() {
                       return Thread.currentThread().getContextClassLoader();
                   }
            });

        ResourceBundle bundle = null;
        try {
            bundle = ResourceBundle.getBundle(resourceBaseName,
                                              locale, loader);
        } catch (MissingResourceException mre) {
            try {
                bundle = ResourceBundle.getBundle(resourceBaseName, locale);
            } catch (MissingResourceException mre1) {
                return null;
            }
        }

        try {
            return bundle.getString(key);
        } catch (MissingResourceException e) {
            return null;
        }
    }

    /**
     * Returns a <code>String</code> containing a description of the
     * named element, or <code>null</code>.  The desciption will be
     * localized for the supplied <code>Locale</code> if possible.
     *
     * <p> The default implementation will first locate a
     * <code>ResourceBundle</code> using the current resource base
     * name set by <code>setResourceBaseName</code> and the supplied
     * <code>Locale</code>, using the fallback mechanism described in
     * the comments for <code>ResourceBundle.getBundle</code>.  If a
     * <code>ResourceBundle</code> is found, the element name will be
     * used as a key to its <code>getString</code> method, and the
     * result returned.  If no <code>ResourceBundle</code> is found,
     * or no such key is present, <code>null</code> will be returned.
     *
     * <p> If <code>locale</code> is <code>null</code>, the current
     * default <code>Locale</code> returned by <code>Locale.getLocale</code>
     * will be used.
     *
     * @param elementName the name of the element.
     * @param locale the <code>Locale</code> for which localization
     * will be attempted.
     *
     * @return the element description.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this format.
     *
     * @see #setResourceBaseName
     */
    public String getElementDescription(String elementName,
                                        Locale locale) {
        Element element = getElement(elementName);
        return getResource(elementName, locale);
    }

    // Children

    public int getChildPolicy(String elementName) {
        Element element = getElement(elementName);
        return element.childPolicy;
    }

    public String[] getChildNames(String elementName) {
        Element element = getElement(elementName);
        if (element.childPolicy == CHILD_POLICY_EMPTY) {
            return null;
        }
        return (String[])element.childList.toArray(new String[0]);
    }

    // Attributes

    public String[] getAttributeNames(String elementName) {
        Element element = getElement(elementName);
        List names = element.attrList;

        String[] result = new String[names.size()];
        return (String[])names.toArray(result);
    }

    public int getAttributeValueType(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        return attr.valueType;
    }

    public int getAttributeDataType(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        return attr.dataType;
    }

    public boolean isAttributeRequired(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        return attr.required;
    }

    public String getAttributeDefaultValue(String elementName,
                                           String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        return attr.defaultValue;
    }

    public String[] getAttributeEnumerations(String elementName,
                                             String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        if (attr.valueType != VALUE_ENUMERATION) {
            throw new IllegalArgumentException
                ("Attribute not an enumeration!");
        }

        List values = attr.enumeratedValues;
        Iterator iter = values.iterator();
        String[] result = new String[values.size()];
        return (String[])values.toArray(result);
    }

    public String getAttributeMinValue(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        if (attr.valueType != VALUE_RANGE &&
            attr.valueType != VALUE_RANGE_MIN_INCLUSIVE &&
            attr.valueType != VALUE_RANGE_MAX_INCLUSIVE &&
            attr.valueType != VALUE_RANGE_MIN_MAX_INCLUSIVE) {
            throw new IllegalArgumentException("Attribute not a range!");
        }

        return attr.minValue;
    }

    public String getAttributeMaxValue(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        if (attr.valueType != VALUE_RANGE &&
            attr.valueType != VALUE_RANGE_MIN_INCLUSIVE &&
            attr.valueType != VALUE_RANGE_MAX_INCLUSIVE &&
            attr.valueType != VALUE_RANGE_MIN_MAX_INCLUSIVE) {
            throw new IllegalArgumentException("Attribute not a range!");
        }

        return attr.maxValue;
    }

    public int getAttributeListMinLength(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        if (attr.valueType != VALUE_LIST) {
            throw new IllegalArgumentException("Attribute not a list!");
        }

        return attr.listMinLength;
    }

    public int getAttributeListMaxLength(String elementName, String attrName) {
        Attribute attr = getAttribute(elementName, attrName);
        if (attr.valueType != VALUE_LIST) {
            throw new IllegalArgumentException("Attribute not a list!");
        }

        return attr.listMaxLength;
    }

    /**
     * Returns a <code>String</code> containing a description of the
     * named attribute, or <code>null</code>.  The desciption will be
     * localized for the supplied <code>Locale</code> if possible.
     *
     * <p> The default implementation will first locate a
     * <code>ResourceBundle</code> using the current resource base
     * name set by <code>setResourceBaseName</code> and the supplied
     * <code>Locale</code>, using the fallback mechanism described in
     * the comments for <code>ResourceBundle.getBundle</code>.  If a
     * <code>ResourceBundle</code> is found, the element name followed
     * by a "/" character followed by the attribute name
     * (<code>elementName + "/" + attrName</code>) will be used as a
     * key to its <code>getString</code> method, and the result
     * returned.  If no <code>ResourceBundle</code> is found, or no
     * such key is present, <code>null</code> will be returned.
     *
     * <p> If <code>locale</code> is <code>null</code>, the current
     * default <code>Locale</code> returned by <code>Locale.getLocale</code>
     * will be used.
     *
     * @param elementName the name of the element.
     * @param attrName the name of the attribute.
     * @param locale the <code>Locale</code> for which localization
     * will be attempted, or <code>null</code>.
     *
     * @return the attribute description.
     *
     * @exception IllegalArgumentException if <code>elementName</code>
     * is <code>null</code>, or is not a legal element name for this format.
     * @exception IllegalArgumentException if <code>attrName</code> is
     * <code>null</code> or is not a legal attribute name for this
     * element.
     *
     * @see #setResourceBaseName
     */
    public String getAttributeDescription(String elementName,
                                          String attrName,
                                          Locale locale) {
        Element element = getElement(elementName);
        if (attrName == null) {
            throw new IllegalArgumentException("attrName == null!");
        }
        Attribute attr = (Attribute)element.attrMap.get(attrName);
        if (attr == null) {
            throw new IllegalArgumentException("No such attribute!");
        }

        String key = elementName + "/" + attrName;
        return getResource(key, locale);
    }

    private ObjectValue getObjectValue(String elementName) {
        Element element = getElement(elementName);
        ObjectValue objv = (ObjectValue)element.objectValue;
        if (objv == null) {
            throw new IllegalArgumentException("No object within element " +
                                               elementName + "!");
        }
        return objv;
    }

    public int getObjectValueType(String elementName) {
        Element element = getElement(elementName);
        ObjectValue objv = (ObjectValue)element.objectValue;
        if (objv == null) {
            return VALUE_NONE;
        }
        return objv.valueType;
    }

    public Class<?> getObjectClass(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        return objv.classType;
    }

    public Object getObjectDefaultValue(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        return objv.defaultValue;
    }

    public Object[] getObjectEnumerations(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        if (objv.valueType != VALUE_ENUMERATION) {
            throw new IllegalArgumentException("Not an enumeration!");
        }
        List vlist = objv.enumeratedValues;
        Object[] values = new Object[vlist.size()];
        return vlist.toArray(values);
    }

    public Comparable<?> getObjectMinValue(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        if ((objv.valueType & VALUE_RANGE) != VALUE_RANGE) {
            throw new IllegalArgumentException("Not a range!");
        }
        return objv.minValue;
    }

    public Comparable<?> getObjectMaxValue(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        if ((objv.valueType & VALUE_RANGE) != VALUE_RANGE) {
            throw new IllegalArgumentException("Not a range!");
        }
        return objv.maxValue;
    }

    public int getObjectArrayMinLength(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        if (objv.valueType != VALUE_LIST) {
            throw new IllegalArgumentException("Not a list!");
        }
        return objv.arrayMinLength;
    }

    public int getObjectArrayMaxLength(String elementName) {
        ObjectValue objv = getObjectValue(elementName);
        if (objv.valueType != VALUE_LIST) {
            throw new IllegalArgumentException("Not a list!");
        }
        return objv.arrayMaxLength;
    }

    // Standard format descriptor

    private synchronized static void createStandardFormat() {
        if (standardFormat == null) {
            standardFormat = new StandardMetadataFormat();
        }
    }

    /**
     * Returns an <code>IIOMetadataFormat</code> object describing the
     * standard, plug-in neutral <code>javax.imageio_1.0</code>
     * metadata document format described in the comment of the
     * <code>javax.imageio.metadata</code> package.
     *
     * @return a predefined <code>IIOMetadataFormat</code> instance.
     */
    public static IIOMetadataFormat getStandardFormatInstance() {
        createStandardFormat();
        return standardFormat;
    }
}
