Initial Contribution
diff --git a/awt/javax/imageio/metadata/IIOInvalidTreeException.java b/awt/javax/imageio/metadata/IIOInvalidTreeException.java
new file mode 100644
index 0000000..8690b2b
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOInvalidTreeException.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.imageio.metadata;
+
+import org.w3c.dom.Node;
+import javax.imageio.IIOException;
+
+/**
+ * The IIOInvalidTreeException provides notification about
+ * fails of IIOMetadataNodes tree parsing by IIOMetadata object.
+ */
+public class IIOInvalidTreeException extends IIOException {
+
+ /** The offending node. */
+ protected Node offendingNode = null;
+
+ /**
+ * Instantiates an IIOInvalidTreeException with the
+ * specified detailed message and specified offending
+ * Node.
+ *
+ * @param message the detailed message.
+ * @param offendingNode the offending node.
+ */
+ public IIOInvalidTreeException(String message, Node offendingNode) {
+ super(message);
+ this.offendingNode = offendingNode;
+ }
+
+ /**
+ * Instantiates a new IIOInvalidTreeException with the
+ * specified detailed message and specified offending
+ * Node.
+ *
+ * @param message the detailed message.
+ * @param cause the cause of this exception.
+ * @param offendingNode the offending node
+ */
+ public IIOInvalidTreeException(String message, Throwable cause, Node offendingNode) {
+ super(message, cause);
+ this.offendingNode = offendingNode;
+ }
+
+ /**
+ * Gets the offending node.
+ *
+ * @return the offending node.
+ */
+ public Node getOffendingNode() {
+ return offendingNode;
+ }
+}
diff --git a/awt/javax/imageio/metadata/IIOMetadata.java b/awt/javax/imageio/metadata/IIOMetadata.java
new file mode 100644
index 0000000..f2387cc
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOMetadata.java
@@ -0,0 +1,371 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javax.imageio.metadata;
+
+import java.util.ArrayList;
+
+import org.apache.harmony.x.imageio.metadata.IIOMetadataUtils;
+import org.w3c.dom.Node;
+
+/**
+ * The Class IIOMetadata represents the metadata (bundled with an image)
+ * as a Dom-type tree.
+ */
+public abstract class IIOMetadata {
+
+ /** Whether the standard metadata format is supported. */
+ protected boolean standardFormatSupported;
+
+ /** The native metadata format name. */
+ protected String nativeMetadataFormatName;
+
+ /** The native metadata format class name. */
+ protected String nativeMetadataFormatClassName;
+
+ /** The extra metadata format names. */
+ protected String[] extraMetadataFormatNames;
+
+ /** The extra metadata format class names. */
+ protected String[] extraMetadataFormatClassNames;
+
+ /** The default controller. */
+ protected IIOMetadataController defaultController;
+
+ /** The controller. */
+ protected IIOMetadataController controller;
+
+ /**
+ * Instantiates a new IIOMetadata with no data set.
+ */
+ protected IIOMetadata() {}
+
+ /**
+ * Instantiates a new IIOMetadata with the specified data parameters.
+ *
+ * @param standardMetadataFormatSupported whether the standard metadata format is supported
+ * @param nativeMetadataFormatName the native metadata format name
+ * @param nativeMetadataFormatClassName the native metadata format class name
+ * @param extraMetadataFormatNames the extra metadata format names
+ * @param extraMetadataFormatClassNames the extra metadata format class names
+ */
+ protected IIOMetadata(boolean standardMetadataFormatSupported,
+ String nativeMetadataFormatName,
+ String nativeMetadataFormatClassName,
+ String[] extraMetadataFormatNames,
+ String[] extraMetadataFormatClassNames) {
+ standardFormatSupported = standardMetadataFormatSupported;
+ this.nativeMetadataFormatName = nativeMetadataFormatName;
+ this.nativeMetadataFormatClassName = nativeMetadataFormatClassName;
+ if (extraMetadataFormatNames == null) {
+ if (extraMetadataFormatClassNames != null) {
+ throw new IllegalArgumentException(
+ "extraMetadataFormatNames == null && extraMetadataFormatClassNames != null!"
+ );
+ }
+ } else {
+ if (extraMetadataFormatClassNames == null) {
+ throw new IllegalArgumentException(
+ "extraMetadataFormatNames != null && extraMetadataFormatClassNames == null!"
+ );
+ }
+ if (extraMetadataFormatNames.length == 0) {
+ throw new IllegalArgumentException("extraMetadataFormatNames.length == 0!");
+ }
+ if (extraMetadataFormatClassNames.length != extraMetadataFormatNames.length) {
+ throw new IllegalArgumentException(
+ "extraMetadataFormatClassNames.length != extraMetadataFormatNames.length!"
+ );
+ }
+ this.extraMetadataFormatNames = extraMetadataFormatNames.clone();
+ this.extraMetadataFormatClassNames = extraMetadataFormatClassNames.clone();
+ }
+ }
+
+ /**
+ * Gets the metadata as tree-type document.
+ *
+ * @param formatName the format name
+ *
+ * @return the node in tree format
+ */
+ public abstract Node getAsTree(String formatName);
+
+ /**
+ * Checks if the metadata is read only.
+ *
+ * @return true, if the metadata is read only.
+ */
+ public abstract boolean isReadOnly();
+
+ /**
+ * Merges the specified tree with this metadata tree.
+ *
+ * @param formatName the format of the specified tree
+ * @param root the root node of the metadata tree
+ *
+ * @throws IIOInvalidTreeException if the specified tree
+ * is incompatible with the this metadata tree.
+ */
+ public abstract void mergeTree(String formatName, Node root) throws IIOInvalidTreeException;
+
+ /**
+ * Resets the controller.
+ */
+ public abstract void reset();
+
+ /**
+ * Gets the controller associated with this metadata document.
+ *
+ * @return the controller
+ */
+ public IIOMetadataController getController() {
+ return controller;
+ }
+
+ /**
+ * Checks whether this metadata has a controller.
+ *
+ * @return true, if this metadata has a controller
+ */
+ public boolean hasController() {
+ return getController() != null;
+ }
+
+ /**
+ * Activate the controller.
+ *
+ * @return true, if successful
+ */
+ public boolean activateController() {
+ if (!hasController()) {
+ throw new IllegalStateException("hasController() == false!");
+ }
+ return getController().activate(this);
+ }
+
+ /**
+ * Gets the default controller.
+ *
+ * @return the default controller
+ */
+ public IIOMetadataController getDefaultController() {
+ return defaultController;
+ }
+
+ /**
+ * Gets the extra metadata format names.
+ *
+ * @return the extra metadata format names
+ */
+ public String[] getExtraMetadataFormatNames() {
+ return extraMetadataFormatNames == null ? null : extraMetadataFormatNames.clone();
+ }
+
+ /**
+ * Gets the metadata format.
+ *
+ * @param formatName the format name
+ *
+ * @return the metadata format
+ */
+ public IIOMetadataFormat getMetadataFormat(String formatName) {
+ return IIOMetadataUtils.instantiateMetadataFormat(
+ formatName,
+ standardFormatSupported,
+ nativeMetadataFormatName, nativeMetadataFormatClassName,
+ extraMetadataFormatNames, extraMetadataFormatClassNames
+ );
+ }
+
+ /**
+ * Gets the native metadata format name.
+ *
+ * @return the native metadata format name
+ */
+ public String getNativeMetadataFormatName() {
+ return nativeMetadataFormatName;
+ }
+
+ /**
+ * Checks if the standard metadata format is supported.
+ *
+ * @return true, if the standard metadata format is supported
+ */
+ public boolean isStandardMetadataFormatSupported() {
+ return standardFormatSupported;
+ }
+
+ /**
+ * Gets the metadata format names.
+ *
+ * @return the metadata format names
+ */
+ public String[] getMetadataFormatNames() {
+ ArrayList<String> res = new ArrayList<String>();
+
+ String nativeMetadataFormatName = getNativeMetadataFormatName();
+ boolean standardFormatSupported = isStandardMetadataFormatSupported();
+ String extraMetadataFormatNames[] = getExtraMetadataFormatNames();
+
+ if (standardFormatSupported) {
+ res.add(IIOMetadataFormatImpl.standardMetadataFormatName);
+ }
+ if (nativeMetadataFormatName != null) {
+ res.add(nativeMetadataFormatName);
+ }
+ if (extraMetadataFormatNames != null) {
+ for (String extraMetadataFormatName : extraMetadataFormatNames) {
+ res.add(extraMetadataFormatName);
+ }
+ }
+
+ return res.size() > 0 ? res.toArray(new String[0]) : null;
+ }
+
+ /**
+ * Gets the standard chroma node.
+ *
+ * @return the standard chroma node
+ */
+ protected IIOMetadataNode getStandardChromaNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard compression node.
+ *
+ * @return the standard compression node
+ */
+ protected IIOMetadataNode getStandardCompressionNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard data node.
+ *
+ * @return the standard data node
+ */
+ protected IIOMetadataNode getStandardDataNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard dimension node.
+ *
+ * @return the standard dimension node
+ */
+ protected IIOMetadataNode getStandardDimensionNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard document node.
+ *
+ * @return the standard document node
+ */
+ protected IIOMetadataNode getStandardDocumentNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard text node.
+ *
+ * @return the standard text node
+ */
+ protected IIOMetadataNode getStandardTextNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard tile node.
+ *
+ * @return the standard tile node
+ */
+ protected IIOMetadataNode getStandardTileNode() {
+ return null;
+ }
+
+ /**
+ * Gets the standard transparency node.
+ *
+ * @return the standard transparency node
+ */
+ protected IIOMetadataNode getStandardTransparencyNode() {
+ return null;
+ }
+
+ /**
+ * Gets the metadata as a tree in standard format.
+ *
+ * @return the metadata as a tree in standard format
+ */
+ protected final IIOMetadataNode getStandardTree() {
+ // Create root node
+ IIOMetadataNode root = new IIOMetadataNode(IIOMetadataFormatImpl.standardMetadataFormatName);
+
+ Node node;
+ if ((node = getStandardChromaNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardCompressionNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardDataNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardDimensionNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardDocumentNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardTextNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardTileNode()) != null) {
+ root.appendChild(node);
+ }
+ if ((node = getStandardTransparencyNode()) != null) {
+ root.appendChild(node);
+ }
+
+ return root;
+ }
+
+ /**
+ * Sets the controller.
+ *
+ * @param controller the new controller
+ */
+ public void setController(IIOMetadataController controller) {
+ this.controller = controller;
+ }
+
+ /**
+ * Sets the from tree.
+ *
+ * @param formatName the name of the metatdata format of the from tree
+ * @param root the root node of the from tree
+ *
+ * @throws IIOInvalidTreeException if the tree or its format is not compatible with
+ * this metadata.
+ */
+ public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException {
+ reset();
+ mergeTree(formatName, root);
+ }
+}
diff --git a/awt/javax/imageio/metadata/IIOMetadataController.java b/awt/javax/imageio/metadata/IIOMetadataController.java
new file mode 100644
index 0000000..dfd4e5c
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOMetadataController.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Sergey I. Salishev
+ * @version $Revision: 1.2 $
+ */
+package javax.imageio.metadata;
+
+/*
+ * @author Sergey I. Salishev
+ * @version $Revision: 1.2 $
+ */
+
+/**
+ * The IIOMetadataController interface provides a method for
+ * implementing objects to activate the controller without
+ * defining how the controller obtains values.
+ */
+public interface IIOMetadataController {
+
+ /**
+ * Activates a controller.
+ *
+ * @param metadata the metadata to be modified.
+ *
+ * @return true if the IIOMetadata has been modified,
+ * false otherwise.
+ */
+ public boolean activate(IIOMetadata metadata);
+}
+
diff --git a/awt/javax/imageio/metadata/IIOMetadataFormat.java b/awt/javax/imageio/metadata/IIOMetadataFormat.java
new file mode 100644
index 0000000..9e246b4
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOMetadataFormat.java
@@ -0,0 +1,347 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.imageio.metadata;
+
+import javax.imageio.ImageTypeSpecifier;
+import java.util.Locale;
+
+/**
+ * The Interface IIOMetadataFormat is implemented by classes that
+ * describe the rules and allowed elements for a metadata document
+ * tree.
+ */
+public interface IIOMetadataFormat {
+
+ /** The CHILD_POLICY_EMPTY. */
+ int CHILD_POLICY_EMPTY = 0;
+
+ /** The CHILD_POLICY_ALL. */
+ int CHILD_POLICY_ALL = 1;
+
+ /** The CHILD_POLICY_SOME. */
+ int CHILD_POLICY_SOME = 2;
+
+ /** The CHILD_POLICY_CHOICE. */
+ int CHILD_POLICY_CHOICE = 3;
+
+ /** The CHILD_POLICY_SEQUENCE. */
+ int CHILD_POLICY_SEQUENCE = 4;
+
+ /** The CHILD_POLICY_REPEAT. */
+ int CHILD_POLICY_REPEAT = 5;
+
+ /** The maximum value for the child policy. */
+ int CHILD_POLICY_MAX = CHILD_POLICY_REPEAT;
+
+ /** The DATATYPE_STRING. */
+ int DATATYPE_STRING = 0;
+
+ /** The DATATYPE_BOOLEAN. */
+ int DATATYPE_BOOLEAN = 1;
+
+ /** The DATATYPE_INTEGER. */
+ int DATATYPE_INTEGER = 2;
+
+ /** The DATATYPE_FLOAT. */
+ int DATATYPE_FLOAT = 3;
+
+ /** The DATATYPE_DOUBLE. */
+ int DATATYPE_DOUBLE = 4;
+
+ /** The VALUE_NONE. */
+ int VALUE_NONE = 0;
+
+ /** The VALUE_ARBITRARY. */
+ int VALUE_ARBITRARY = 1;
+
+ /** The VALUE_RANGE. */
+ int VALUE_RANGE = 2;
+
+ /** The VALUE_RANGE_MIN_INCLUSIVE_MASK. */
+ int VALUE_RANGE_MIN_INCLUSIVE_MASK = 4;
+
+ /** The VALUE_RANGE_MAX_INCLUSIVE_MASK. */
+ int VALUE_RANGE_MAX_INCLUSIVE_MASK = 8;
+
+ /** The VALUE_ENUMERATION. */
+ int VALUE_ENUMERATION = 16;
+
+ /** The VALUE_LIST. */
+ int VALUE_LIST = 32;
+
+ /** The VALUE_RANGE_MIN_INCLUSIVE. */
+ int VALUE_RANGE_MIN_INCLUSIVE = VALUE_RANGE | VALUE_RANGE_MIN_INCLUSIVE_MASK;
+
+ /** The VALUE_RANGE_MAX_INCLUSIVE. */
+ int VALUE_RANGE_MAX_INCLUSIVE = VALUE_RANGE | VALUE_RANGE_MAX_INCLUSIVE_MASK;
+
+ /** The VALUE_RANGE_MIN_MAX_INCLUSIVE. */
+ int VALUE_RANGE_MIN_MAX_INCLUSIVE =
+ VALUE_RANGE | VALUE_RANGE_MIN_INCLUSIVE_MASK | VALUE_RANGE_MAX_INCLUSIVE_MASK;
+
+ /**
+ * Tells whether the specified element is allowed for the specified
+ * image type.
+ *
+ * @param elementName the element name
+ * @param imageType the image type
+ *
+ * @return true, if the specified element is allowed for the specified
+ * image type
+ */
+ boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType);
+
+ /**
+ * Gets data type of the specified attribute of the specified element.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the attribute's data type
+ */
+ int getAttributeDataType(String elementName, String attrName);
+
+ /**
+ * Gets the default value of the specified attribute of the specified element.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the attribute's default value
+ */
+ String getAttributeDefaultValue(String elementName, String attrName);
+
+ /**
+ * Gets the user-friendly description of the attribute.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ * @param locale the locale giving the desired language for the
+ * description
+ *
+ * @return the attribute description
+ */
+ String getAttributeDescription(String elementName, String attrName, Locale locale);
+
+ /**
+ * Gets the attribute enumerations.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the attribute enumerations
+ */
+ String[] getAttributeEnumerations(String elementName, String attrName);
+
+ /**
+ * Gets the maximum length of the attribute list.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the maximum length of the attribute list
+ */
+ int getAttributeListMaxLength(String elementName, String attrName);
+
+ /**
+ * Gets the minimum length of the attribute list.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the minimum length of the attribute list
+ */
+ int getAttributeListMinLength(String elementName, String attrName);
+
+ /**
+ * Gets the maximum value allowed for the attribute.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the maximum value allowed for the attribute
+ */
+ String getAttributeMaxValue(String elementName, String attrName);
+
+ /**
+ * Gets the minimum value allowed for the attribute.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the minimum value allowed for the attribute
+ */
+ String getAttributeMinValue(String elementName, String attrName);
+
+ /**
+ * Gets the attribute names allowed for the specified element.
+ *
+ * @param elementName the element name
+ *
+ * @return the attribute names
+ */
+ String[] getAttributeNames(String elementName);
+
+ /**
+ * Gets the attribute value type.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return the attribute value type
+ */
+ int getAttributeValueType(String elementName, String attrName);
+
+ /**
+ * Checks whether the specified attribute is required
+ * for the specified element.
+ *
+ * @param elementName the element name
+ * @param attrName the attribute name
+ *
+ * @return true, if the specified attribute is required for the
+ * specified element
+ */
+ boolean isAttributeRequired(String elementName, String attrName);
+
+ /**
+ * Gets the names of the possible child elements for the given element.
+ *
+ * @param elementName the element name
+ *
+ * @return the child names
+ */
+ String[] getChildNames(String elementName);
+
+ /**
+ * Gets the constant describing the element's child policy.
+ *
+ * @param elementName the element name
+ *
+ * @return the child policy
+ */
+ int getChildPolicy(String elementName);
+
+ /**
+ * Gets the user-friendly description of the element.
+ *
+ * @param elementName the element name
+ * @param locale the locale giving the desired language for the
+ * description
+ *
+ * @return the element description
+ */
+ String getElementDescription(String elementName, Locale locale);
+
+ /**
+ * Gets the maximum number of children allowed for the element.
+ *
+ * @param elementName the element name
+ *
+ * @return the maximum number of children allowed for the element
+ */
+ int getElementMaxChildren(String elementName);
+
+ /**
+ * Gets the minimum number of children allowed for the element.
+ *
+ * @param elementName the element name
+ *
+ * @return the minimum number of children allowed for the element
+ */
+ int getElementMinChildren(String elementName);
+
+ /**
+ * Gets the maximum object array length allowed for the element.
+ *
+ * @param elementName the element name
+ *
+ * @return the maximum object array length allowed for the element
+ */
+ int getObjectArrayMaxLength(String elementName);
+
+ /**
+ * Gets the minimum object array length allowed for the element.
+ *
+ * @param elementName the element name
+ *
+ * @return the minimum object array length allowed for the element
+ */
+ int getObjectArrayMinLength(String elementName);
+
+ /**
+ * Gets the object class corresponding to the specified element.
+ *
+ * @param elementName the element name
+ *
+ * @return the object class corresponding to the specified element
+ */
+ Class<?> getObjectClass(String elementName);
+
+ /**
+ * Gets the object default value for the element.
+ *
+ * @param elementName the element name
+ *
+ * @return the object default value for the element
+ */
+ Object getObjectDefaultValue(String elementName);
+
+ /**
+ * Gets the object enumerations.
+ *
+ * @param elementName the element name
+ *
+ * @return the object enumerations
+ */
+ Object[] getObjectEnumerations(String elementName);
+
+ /**
+ * Gets the maximum value allowed for the element's object.
+ *
+ * @param elementName the element name
+ *
+ * @return the maximum value allowed for the element's object
+ */
+ Comparable<?> getObjectMaxValue(String elementName);
+
+ /**
+ * Gets the minimum value allowed for the element's object.
+ *
+ * @param elementName the element name
+ *
+ * @return the minimum value allowed for the element's object
+ */
+ Comparable<?> getObjectMinValue(String elementName);
+
+ /**
+ * Gets the constant that indicates the type of the element's value.
+ *
+ * @param elementName the element name
+ *
+ * @return the constant that indicates the type of the element's value
+ */
+ int getObjectValueType(String elementName);
+
+ /**
+ * Gets the name of the root element.
+ *
+ * @return the name of the root element
+ */
+ String getRootName();
+}
diff --git a/awt/javax/imageio/metadata/IIOMetadataFormatImpl.java b/awt/javax/imageio/metadata/IIOMetadataFormatImpl.java
new file mode 100644
index 0000000..438ae90
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOMetadataFormatImpl.java
@@ -0,0 +1,939 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.imageio.metadata;
+
+import javax.imageio.ImageTypeSpecifier;
+import java.util.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * The IIOMetadataFormatImpl class provides an implementation of the
+ * IIOMetadataFormat interface.
+ */
+public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat {
+
+ /** The Constant standardMetadataFormatName. */
+ @SuppressWarnings({"ConstantDeclaredInAbstractClass"})
+ public static final String standardMetadataFormatName = "javax_imageio_1.0";
+
+ /** The standard format. */
+ @SuppressWarnings({"StaticNonFinalField"})
+ private static IIOMetadataFormatImpl standardFormat;
+
+ /** The root name. */
+ private String rootName;
+
+ /** The element hash. */
+ private HashMap<String, Element> elementHash = new HashMap<String, Element>();
+
+ /** The resource base name. */
+ private String resourceBaseName = getClass().getName() + "Resources";
+
+ /**
+ * Instantiates an IIOMetadataFormatImpl with the specified root
+ * name and child policy (not CHILD_POLICY_REPEAT).
+ *
+ * @param rootName the name of root element.
+ * @param childPolicy the child policy defined by one of the
+ * CHILD_POLICY_* constants (except CHILD_POLICY_REPEAT).
+ */
+ public IIOMetadataFormatImpl(String rootName, int childPolicy) {
+ if (rootName == null) {
+ throw new IllegalArgumentException("rootName is null");
+ }
+ if (
+ childPolicy < CHILD_POLICY_EMPTY ||
+ childPolicy > CHILD_POLICY_MAX ||
+ childPolicy == CHILD_POLICY_REPEAT
+ ) {
+ throw new IllegalArgumentException("childPolicy is not one of the predefined constants");
+ }
+
+ this.rootName = rootName;
+ Element root = new Element();
+ root.name = rootName;
+ root.childPolicy = childPolicy;
+ elementHash.put(rootName, root);
+ }
+
+ /**
+ * Instantiates an IIOMetadataFormatImpl with the specified root
+ * name and CHILD_POLICY_REPEAT child policy.
+ *
+ * @param rootName the name of root element.
+ * @param minChildren the minimum number of children.
+ * @param maxChildren the maximum number of children
+ */
+ public IIOMetadataFormatImpl(String rootName, int minChildren, int maxChildren) {
+ if (rootName == null) {
+ throw new IllegalArgumentException("rootName is null");
+ }
+ if (minChildren < 0) {
+ throw new IllegalArgumentException("minChildren < 0!");
+ }
+ if (minChildren > maxChildren) {
+ throw new IllegalArgumentException("minChildren > maxChildren!");
+ }
+
+ this.rootName = rootName;
+ Element root = new Element();
+ root.name = rootName;
+ root.minChildren = minChildren;
+ root.maxChildren = maxChildren;
+ root.childPolicy = CHILD_POLICY_REPEAT;
+ elementHash.put(rootName, root);
+ }
+
+ @SuppressWarnings({"AbstractMethodOverridesAbstractMethod"})
+ public abstract boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType);
+
+ /**
+ * Adds a new attribute to an existing element.
+ *
+ * @param elementName the name of the element to which the new attribute
+ * will be added.
+ * @param attrName the attribute name.
+ * @param dataType the data type of the new attribute.
+ * @param required the flag which indicates whether this attribute
+ * must be present.
+ * @param listMinLength the minimum legal number of list items.
+ * @param listMaxLength the the maximum legal number of list items.
+ */
+ protected void addAttribute(
+ String elementName, String attrName, int dataType,
+ boolean required, int listMinLength, int listMaxLength
+ ) {
+ 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!");
+ }
+
+ Element element = findElement(elementName);
+ Attlist attr = new Attlist();
+ attr.name = attrName;
+ attr.dataType = dataType;
+ attr.required = required;
+ attr.listMinLength = listMinLength;
+ attr.listMaxLength = listMaxLength;
+ attr.valueType = VALUE_LIST;
+
+ element.attributes.put(attrName, attr);
+ }
+
+ /**
+ * Adds a new attribute to an existing element.
+ *
+ * @param elementName the name of the element to which the new attribute
+ * will be added.
+ * @param attrName the attribute name.
+ * @param dataType the data type of the new attribute.
+ * @param required the flag which indicates whether this attribute
+ * must be present.
+ * @param defaultValue the default value of the attribute.
+ */
+ protected void addAttribute(
+ String elementName, String attrName, int dataType,
+ boolean required, String defaultValue
+ ) {
+ if (attrName == null) {
+ throw new IllegalArgumentException("attrName == null!");
+ }
+ if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
+ throw new IllegalArgumentException("Invalid value for dataType!");
+ }
+
+ Element element = findElement(elementName);
+ Attlist attr = new Attlist();
+ attr.name = attrName;
+ attr.dataType = dataType;
+ attr.required = required;
+ attr.defaultValue = defaultValue;
+ attr.valueType = VALUE_ARBITRARY;
+
+ element.attributes.put(attrName, attr);
+ }
+
+ /**
+ * Adds a new attribute to an existing element.
+ *
+ * @param elementName the name of the element to which the new attribute
+ * will be added.
+ * @param attrName the attribute name.
+ * @param dataType the data type of the new attribute.
+ * @param required the flag which indicates whether this attribute
+ * must be present.
+ * @param defaultValue the default value of the attribute.
+ * @param enumeratedValues the legal values for the attribute as
+ * a list of strings.
+ */
+ protected void addAttribute(
+ String elementName, String attrName, int dataType,
+ boolean required, String defaultValue, List<String> enumeratedValues
+ ) {
+ 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 || enumeratedValues.isEmpty()) {
+ throw new IllegalArgumentException("enumeratedValues is empty or null");
+ }
+
+ try {
+ for (String enumeratedValue : enumeratedValues) {
+ if (enumeratedValue == null) {
+ throw new IllegalArgumentException("enumeratedValues contains a null!");
+ }
+ }
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("enumeratedValues contains a non-String value!");
+ }
+
+ Element element = findElement(elementName);
+ Attlist attr = new Attlist();
+ attr.name = attrName;
+ attr.dataType = dataType;
+ attr.required = required;
+ attr.defaultValue = defaultValue;
+ attr.enumeratedValues = enumeratedValues;
+ attr.valueType = VALUE_ENUMERATION;
+
+ element.attributes.put(attrName, attr);
+ }
+
+ /**
+ * Adds a new attribute to an existing element.
+ *
+ * @param elementName the name of the element to which the new attribute
+ * will be added.
+ * @param attrName the attribute name.
+ * @param dataType the data type of the new attribute.
+ * @param required the flag which indicates whether this attribute
+ * must be present.
+ * @param defaultValue the default value of attribute.
+ * @param minValue the minimum legal value of an attribute.
+ * @param maxValue the maximum legal value of an attribute.
+ * @param minInclusive the flag which indicates
+ * whether the minValue is inclusive.
+ * @param maxInclusive the flag which indicates
+ * whether the maxValue is inclusive.
+ */
+ protected void addAttribute(
+ String elementName, String attrName, int dataType,
+ boolean required, String defaultValue,
+ String minValue, String maxValue,
+ boolean minInclusive, boolean maxInclusive
+ ) {
+ if (attrName == null) {
+ throw new IllegalArgumentException("attrName == null!");
+ }
+ if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
+ throw new IllegalArgumentException("Invalid value for dataType!");
+ }
+
+ Element element = findElement(elementName);
+ Attlist attr = new Attlist();
+ attr.name = attrName;
+ attr.dataType = dataType;
+ attr.required = required;
+ attr.defaultValue = defaultValue;
+ attr.minValue = minValue;
+ attr.maxValue = maxValue;
+ attr.minInclusive = minInclusive;
+ attr.maxInclusive = maxInclusive;
+
+ attr.valueType = VALUE_RANGE;
+ attr.valueType |= minInclusive ? VALUE_RANGE_MIN_INCLUSIVE_MASK : 0;
+ attr.valueType |= maxInclusive ? VALUE_RANGE_MAX_INCLUSIVE_MASK : 0;
+
+ element.attributes.put(attrName, attr);
+ }
+
+ /**
+ * Adds a new attribute with boolean data type to an existing
+ * element.
+ *
+ * @param elementName the name of the element to which the new attribute
+ * will be added.
+ * @param attrName the attribute name.
+ * @param hasDefaultValue the flag which indicates whether this attribute
+ * must have a default value.
+ * @param defaultValue the default value.
+ */
+ protected void addBooleanAttribute(
+ String elementName, String attrName,
+ boolean hasDefaultValue, boolean defaultValue
+ ) {
+ String defaultVal = hasDefaultValue ? (defaultValue ? "TRUE" : "FALSE") : null;
+ ArrayList<String> values = new ArrayList<String>(2);
+ values.add("TRUE");
+ values.add("FALSE");
+
+ addAttribute(elementName, attrName, DATATYPE_BOOLEAN, true, defaultVal, values);
+ }
+
+ /**
+ * Adds an existing element to the list of child elements
+ * of the specified parent element.
+ *
+ * @param elementName the name of the element to be added.
+ * @param parentName the parent element name.
+ */
+ protected void addChildElement(String elementName, String parentName) {
+ Element parent = findElement(parentName);
+ Element element = findElement(elementName);
+ parent.children.add(element.name);
+ }
+
+ /**
+ * Adds a new element type to this IIOMetadataFormat with
+ * a child policy (if policy is not CHILD_POLICY_REPEAT).
+ *
+ * @param elementName the name of the element to be added.
+ * @param parentName the parent element name.
+ * @param childPolicy one of the CHILD_POLICY_* constants defined
+ * by IIOMetadataFormat.
+ */
+ protected void addElement(String elementName, String parentName, int childPolicy) {
+ if (
+ childPolicy < CHILD_POLICY_EMPTY ||
+ childPolicy > CHILD_POLICY_MAX ||
+ childPolicy == CHILD_POLICY_REPEAT
+ ) {
+ throw new IllegalArgumentException("childPolicy is not one of the predefined constants");
+ }
+
+ Element parent = findElement(parentName);
+ Element element = new Element();
+ element.name = elementName;
+ element.childPolicy = childPolicy;
+ elementHash.put(elementName, element);
+ parent.children.add(elementName);
+ }
+
+ /**
+ * Adds a new element type to this IIOMetadataFormat with
+ * CHILD_POLICY_REPEAT and the specified minimum and maximum
+ * number of child elements.
+ *
+ * @param elementName the element name to be added.
+ * @param parentName the parent element name.
+ * @param minChildren the minimum number of child elements.
+ * @param maxChildren the maximum number of child elements.
+ */
+ protected void addElement(
+ String elementName, String parentName,
+ int minChildren, int maxChildren
+ ) {
+ if (minChildren < 0) {
+ throw new IllegalArgumentException("minChildren < 0!");
+ }
+ if (minChildren > maxChildren) {
+ throw new IllegalArgumentException("minChildren > maxChildren!");
+ }
+
+ Element parent = findElement(parentName);
+ Element element = new Element();
+ element.name = elementName;
+ element.childPolicy = CHILD_POLICY_REPEAT;
+ element.minChildren = minChildren;
+ element.maxChildren = maxChildren;
+ elementHash.put(elementName, element);
+ parent.children.add(elementName);
+ }
+
+ /**
+ * Adds an Object reference with the specified class type to be
+ * stored as element's value.
+ *
+ * @param elementName the element name.
+ * @param classType the class indicates the legal types for
+ * the object's value.
+ * @param arrayMinLength the minimum legal length for the array.
+ * @param arrayMaxLength the maximum legal length for the array.
+ */
+ protected void addObjectValue(
+ String elementName, Class<?> classType,
+ int arrayMinLength, int arrayMaxLength
+ ) {
+ Element element = findElement(elementName);
+
+ ObjectValue objVal = new ObjectValue();
+ objVal.classType = classType;
+ objVal.arrayMaxLength = arrayMaxLength;
+ objVal.arrayMinLength = arrayMinLength;
+ objVal.valueType = VALUE_LIST;
+
+ element.objectValue = objVal;
+ }
+
+ /**
+ * Adds an Object reference with the specified class type to be
+ * stored as an element's value.
+ *
+ * @param elementName the element name.
+ * @param classType the class indicates the legal types for
+ * the object's value.
+ * @param required a flag indicated that this object value
+ * must be present.
+ * @param defaultValue the default value, or null.
+ */
+ protected <T> void addObjectValue(
+ String elementName, Class<T> classType,
+ boolean required, T defaultValue
+ ) {
+ // note: reqired is an unused parameter
+ Element element = findElement(elementName);
+
+ ObjectValue<T> objVal = new ObjectValue<T>();
+ objVal.classType = classType;
+ objVal.defaultValue = defaultValue;
+ objVal.valueType = VALUE_ARBITRARY;
+
+ element.objectValue = objVal;
+ }
+
+ /**
+ * Adds an Object reference with the specified class type to be
+ * stored as the element's value.
+ *
+ * @param elementName the element name.
+ * @param classType the class indicates the legal types for
+ * the object value.
+ * @param required a flag indicated that this object value
+ * must be present.
+ * @param defaultValue the default value, or null.
+ * @param enumeratedValues the list of legal values for the object.
+ */
+ protected <T> void addObjectValue(
+ String elementName, Class<T> classType,
+ boolean required, T defaultValue,
+ List<? extends T> enumeratedValues
+ ) {
+ // note: reqired is an unused parameter
+ if (enumeratedValues == null || enumeratedValues.isEmpty()) {
+ throw new IllegalArgumentException("enumeratedValues is empty or null");
+ }
+
+ try {
+ for (T enumeratedValue : enumeratedValues) {
+ if (enumeratedValue == null) {
+ throw new IllegalArgumentException("enumeratedValues contains a null!");
+ }
+ }
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("enumeratedValues contains a value not of class classType!");
+ }
+
+ Element element = findElement(elementName);
+
+ ObjectValue<T> objVal = new ObjectValue<T>();
+ objVal.classType = classType;
+ objVal.defaultValue = defaultValue;
+ objVal.enumeratedValues = enumeratedValues;
+ objVal.valueType = VALUE_ENUMERATION;
+
+ element.objectValue = objVal;
+ }
+
+ /**
+ * Adds an Object reference with the specified class type to be
+ * stored as the element's value.
+ *
+ * @param elementName the element name.
+ * @param classType the class indicates the legal types for
+ * the object value.
+ * @param defaultValue the default value, or null.
+ * @param minValue the minimum legal value for the object value.
+ * @param maxValue the maximum legal value for the object value.
+ * @param minInclusive the flag which indicates
+ * whether the minValue is inclusive.
+ * @param maxInclusive the flag which indicates
+ * whether the maxValue is inclusive.
+ */
+ 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 = findElement(elementName);
+
+ ObjectValue<T> objVal = new ObjectValue<T>();
+ objVal.classType = classType;
+ objVal.defaultValue = defaultValue;
+ objVal.minValue = minValue;
+ objVal.maxValue = maxValue;
+ objVal.minInclusive = minInclusive;
+ objVal.maxInclusive = maxInclusive;
+
+ objVal.valueType = VALUE_RANGE;
+ objVal.valueType |= minInclusive ? VALUE_RANGE_MIN_INCLUSIVE_MASK : 0;
+ objVal.valueType |= maxInclusive ? VALUE_RANGE_MAX_INCLUSIVE_MASK : 0;
+
+ element.objectValue = objVal;
+ }
+
+ public int getAttributeDataType(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ return attr.dataType;
+ }
+
+ public String getAttributeDefaultValue(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ return attr.defaultValue;
+ }
+
+ public String getAttributeDescription(String elementName, String attrName, Locale locale) {
+ findAttribute(elementName, attrName);
+ return getResourceString(elementName + "/" + attrName, locale);
+ }
+
+ public String[] getAttributeEnumerations(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ if (attr.valueType != VALUE_ENUMERATION) {
+ throw new IllegalArgumentException("Attribute is not an enumeration!");
+ }
+
+ return attr.enumeratedValues.toArray(new String[attr.enumeratedValues.size()]);
+ }
+
+ public int getAttributeListMaxLength(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ if (attr.valueType != VALUE_LIST) {
+ throw new IllegalArgumentException("Attribute is not a list!");
+ }
+ return attr.listMaxLength;
+ }
+
+ public int getAttributeListMinLength(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ if (attr.valueType != VALUE_LIST) {
+ throw new IllegalArgumentException("Attribute is not a list!");
+ }
+ return attr.listMinLength;
+ }
+
+ public String getAttributeMaxValue(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ if ((attr.valueType & VALUE_RANGE) == 0) {
+ throw new IllegalArgumentException("Attribute is not a range!");
+ }
+ return attr.maxValue;
+ }
+
+ public String getAttributeMinValue(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ if ((attr.valueType & VALUE_RANGE) == 0) {
+ throw new IllegalArgumentException("Attribute is not a range!");
+ }
+ return attr.minValue;
+ }
+
+ public String[] getAttributeNames(String elementName) {
+ Element element = findElement(elementName);
+ return element.attributes.keySet().toArray(new String[element.attributes.size()]);
+ }
+
+ public int getAttributeValueType(String elementName, String attrName) {
+ Attlist attr = findAttribute(elementName, attrName);
+ return attr.valueType;
+ }
+
+ public String[] getChildNames(String elementName) {
+ Element element = findElement(elementName);
+ if (element.childPolicy == CHILD_POLICY_EMPTY) { // Element cannot have children
+ return null;
+ }
+ return element.children.toArray(new String[element.children.size()]);
+ }
+
+ public int getChildPolicy(String elementName) {
+ Element element = findElement(elementName);
+ return element.childPolicy;
+ }
+
+ public String getElementDescription(String elementName, Locale locale) {
+ findElement(elementName); // Check if there is such element
+ return getResourceString(elementName, locale);
+ }
+
+ public int getElementMaxChildren(String elementName) {
+ Element element = findElement(elementName);
+ if (element.childPolicy != CHILD_POLICY_REPEAT) {
+ throw new IllegalArgumentException("Child policy is not CHILD_POLICY_REPEAT!");
+ }
+ return element.maxChildren;
+ }
+
+ public int getElementMinChildren(String elementName) {
+ Element element = findElement(elementName);
+ if (element.childPolicy != CHILD_POLICY_REPEAT) {
+ throw new IllegalArgumentException("Child policy is not CHILD_POLICY_REPEAT!");
+ }
+ return element.minChildren;
+ }
+
+ public int getObjectArrayMaxLength(String elementName) {
+ Element element = findElement(elementName);
+ ObjectValue v = element.objectValue;
+ if (v == null || v.valueType != VALUE_LIST) {
+ throw new IllegalArgumentException("Not a list!");
+ }
+ return v.arrayMaxLength;
+ }
+
+ public int getObjectArrayMinLength(String elementName) {
+ Element element = findElement(elementName);
+ ObjectValue v = element.objectValue;
+ if (v == null || v.valueType != VALUE_LIST) {
+ throw new IllegalArgumentException("Not a list!");
+ }
+ return v.arrayMinLength;
+ }
+
+ public Class<?> getObjectClass(String elementName) {
+ ObjectValue v = findObjectValue(elementName);
+ return v.classType;
+ }
+
+ public Object getObjectDefaultValue(String elementName) {
+ ObjectValue v = findObjectValue(elementName);
+ return v.defaultValue;
+ }
+
+ public Object[] getObjectEnumerations(String elementName) {
+ Element element = findElement(elementName);
+ ObjectValue v = element.objectValue;
+ if (v == null || v.valueType != VALUE_ENUMERATION) {
+ throw new IllegalArgumentException("Not an enumeration!");
+ }
+ return v.enumeratedValues.toArray();
+ }
+
+ public Comparable<?> getObjectMaxValue(String elementName) {
+ Element element = findElement(elementName);
+ ObjectValue v = element.objectValue;
+ if (v == null || (v.valueType & VALUE_RANGE) == 0) {
+ throw new IllegalArgumentException("Not a range!");
+ }
+ return v.maxValue;
+ }
+
+ public Comparable<?> getObjectMinValue(String elementName) {
+ Element element = findElement(elementName);
+ ObjectValue v = element.objectValue;
+ if (v == null || (v.valueType & VALUE_RANGE) == 0) {
+ throw new IllegalArgumentException("Not a range!");
+ }
+ return v.minValue;
+ }
+
+ public int getObjectValueType(String elementName) {
+ Element element = findElement(elementName);
+ if (element.objectValue == null) {
+ return VALUE_NONE;
+ }
+ return element.objectValue.valueType;
+ }
+
+ /**
+ * Gets the resource base name for locating ResourceBundles.
+ *
+ * @return the current resource base name.
+ */
+ protected String getResourceBaseName() {
+ return resourceBaseName;
+ }
+
+ public String getRootName() {
+ return rootName;
+ }
+
+ /**
+ * Gets the standard format instance.
+ *
+ * @return the IIOMetadataFormat instance.
+ */
+ public static IIOMetadataFormat getStandardFormatInstance() {
+ if (standardFormat == null) {
+ standardFormat = new IIOStandardMetadataFormat();
+ }
+
+ return standardFormat;
+ }
+
+ public boolean isAttributeRequired(String elementName, String attrName) {
+ return findAttribute(elementName, attrName).required;
+ }
+
+ /**
+ * Removes the specified attribute from the specified element.
+ *
+ * @param elementName the specified element name.
+ * @param attrName the specified attribute name.
+ */
+ protected void removeAttribute(String elementName, String attrName) {
+ Element element = findElement(elementName);
+ element.attributes.remove(attrName);
+ }
+
+ /**
+ * Removes the specified element from this format.
+ *
+ * @param elementName the specified element name.
+ */
+ protected void removeElement(String elementName) {
+ Element element;
+ if ((element = elementHash.get(elementName)) != null) {
+ elementHash.remove(elementName);
+ for (Element e : elementHash.values()) {
+ e.children.remove(element.name);
+ }
+ }
+ }
+
+ /**
+ * Removes the object value from the specified element.
+ *
+ * @param elementName the element name.
+ */
+ protected void removeObjectValue(String elementName) {
+ Element element = findElement(elementName);
+ element.objectValue = null;
+ }
+
+ /**
+ * Sets a new base name for ResourceBundles containing
+ * descriptions of elements and attributes for this format.
+ *
+ * @param resourceBaseName the new resource base name.
+ */
+ protected void setResourceBaseName(String resourceBaseName) {
+ if (resourceBaseName == null) {
+ throw new IllegalArgumentException("resourceBaseName == null!");
+ }
+ this.resourceBaseName = resourceBaseName;
+ }
+
+ /**
+ * The Class Element.
+ */
+ @SuppressWarnings({"ClassWithoutConstructor"})
+ private class Element {
+
+ /** The name. */
+ String name;
+
+ /** The children. */
+ ArrayList<String> children = new ArrayList<String>();
+
+ /** The attributes. */
+ HashMap<String, Attlist> attributes = new HashMap<String, Attlist>();
+
+ /** The min children. */
+ int minChildren;
+
+ /** The max children. */
+ int maxChildren;
+
+ /** The child policy. */
+ int childPolicy;
+
+ /** The object value. */
+ ObjectValue objectValue;
+ }
+
+ /**
+ * The Class Attlist.
+ */
+ @SuppressWarnings({"ClassWithoutConstructor"})
+ private class Attlist {
+
+ /** The name. */
+ String name;
+
+ /** The data type. */
+ int dataType;
+
+ /** The required. */
+ boolean required;
+
+ /** The list min length. */
+ int listMinLength;
+
+ /** The list max length. */
+ int listMaxLength;
+
+ /** The default value. */
+ String defaultValue;
+
+ /** The enumerated values. */
+ List<String> enumeratedValues;
+
+ /** The min value. */
+ String minValue;
+
+ /** The max value. */
+ String maxValue;
+
+ /** The min inclusive. */
+ boolean minInclusive;
+
+ /** The max inclusive. */
+ boolean maxInclusive;
+
+ /** The value type. */
+ int valueType;
+ }
+
+ /**
+ * The Class ObjectValue.
+ */
+ @SuppressWarnings({"ClassWithoutConstructor"})
+ private class ObjectValue<T> {
+
+ /** The class type. */
+ Class<T> classType;
+
+ /** The array min length. */
+ int arrayMinLength;
+
+ /** The array max length. */
+ int arrayMaxLength;
+
+ /** The default value. */
+ T defaultValue;
+
+ /** The enumerated values. */
+ List<? extends T> enumeratedValues;
+
+ /** The min value. */
+ Comparable<? super T> minValue;
+
+ /** The max value. */
+ Comparable<? super T> maxValue;
+
+ /** The min inclusive. */
+ boolean minInclusive;
+
+ /** The max inclusive. */
+ boolean maxInclusive;
+
+ /** The value type. */
+ int valueType;
+ }
+
+ /**
+ * Find element.
+ *
+ * @param name the name
+ *
+ * @return the element
+ */
+ private Element findElement(String name) {
+ Element element;
+ if ((element = elementHash.get(name)) == null) {
+ throw new IllegalArgumentException("element name is null or no such element: " + name);
+ }
+
+ return element;
+ }
+
+ /**
+ * Find attribute.
+ *
+ * @param elementName the element name
+ * @param attributeName the attribute name
+ *
+ * @return the attlist
+ */
+ private Attlist findAttribute(String elementName, String attributeName) {
+ Element element = findElement(elementName);
+ Attlist attribute;
+ if ((attribute = element.attributes.get(attributeName)) == null) {
+ throw new IllegalArgumentException("attribute name is null or no such attribute: " + attributeName);
+ }
+
+ return attribute;
+ }
+
+ /**
+ * Find object value.
+ *
+ * @param elementName the element name
+ *
+ * @return the object value
+ */
+ private ObjectValue findObjectValue(String elementName) {
+ Element element = findElement(elementName);
+ ObjectValue v = element.objectValue;
+ if (v == null) {
+ throw new IllegalArgumentException("No object within element");
+ }
+ return v;
+ }
+
+ /**
+ * Gets the resource string.
+ *
+ * @param key the key
+ * @param locale the locale
+ *
+ * @return the resource string
+ */
+ private String getResourceString(String key, Locale locale) {
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ // Get the context class loader and try to locate the bundle with it first
+ ClassLoader contextClassloader = AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+
+ // Now try to get the resource bundle
+ ResourceBundle rb;
+ try {
+ rb = ResourceBundle.getBundle(resourceBaseName, locale, contextClassloader);
+ } catch (MissingResourceException e) {
+ try {
+ rb = ResourceBundle.getBundle(resourceBaseName, locale);
+ } catch (MissingResourceException e1) {
+ return null;
+ }
+ }
+
+ try {
+ return rb.getString(key);
+ } catch (MissingResourceException e) {
+ return null;
+ } catch (ClassCastException e) {
+ return null; // Not a string resource
+ }
+ }
+}
diff --git a/awt/javax/imageio/metadata/IIOMetadataNode.java b/awt/javax/imageio/metadata/IIOMetadataNode.java
new file mode 100644
index 0000000..d5ab7a5
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOMetadataNode.java
@@ -0,0 +1,675 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.imageio.metadata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+//???AWT
+//import org.w3c.dom.TypeInfo;
+//import org.w3c.dom.UserDataHandler;
+
+/**
+ * The Class IIOMetadataNode represents a node of the
+ * (DOM-style) metadata tree.
+ */
+public class IIOMetadataNode implements Element, NodeList {
+
+ /** The node name. */
+ private String nodeName;
+
+ /** The node value. */
+ private String nodeValue;
+
+ /** The attributes. */
+ private IIOMetadataNodeList attrs = new IIOMetadataNodeList(new ArrayList<IIOMetadataNode>());
+
+ /** The parent node. */
+ private IIOMetadataNode parent;
+
+ /** The first child node. */
+ private IIOMetadataNode firstChild;
+
+ /** The last child node. */
+ private IIOMetadataNode lastChild;
+
+ /** The previous sibling. */
+ private IIOMetadataNode previousSibling;
+
+ /** The next sibling. */
+ private IIOMetadataNode nextSibling;
+
+ /** The number of children. */
+ private int nChildren;
+
+ /** The user object associated with this node. */
+ private Object userObject;
+
+ /** The text content of this node. */
+ private String textContent;
+
+ /**
+ * Instantiates a new empty node.
+ */
+ public IIOMetadataNode() {
+ }
+
+ /**
+ * Instantiates a new empty node with the specified name.
+ *
+ * @param nodeName the node name
+ */
+ public IIOMetadataNode(String nodeName) {
+ this.nodeName = nodeName;
+ }
+
+ /**
+ * Instantiates a new IIOMetadataNode with the specified
+ * name and value.
+ *
+ * @param nodeName the node name
+ * @param nodeValue the node value
+ */
+ private IIOMetadataNode(String nodeName, String nodeValue) {
+ this.nodeName = nodeName;
+ this.nodeValue = nodeValue;
+ }
+
+ public String getTagName() {
+ return nodeName;
+ }
+
+ public String getAttribute(String name) {
+ Attr attrNode = (Attr) attrs.getNamedItem(name);
+ return (attrNode == null) ? "" : attrNode.getValue();
+ }
+
+ public void setAttribute(String name, String value) throws DOMException {
+ Attr attr = (Attr) attrs.getNamedItem(name);
+ if (attr != null) {
+ attr.setValue(value);
+ } else {
+ attrs.list.add(new IIOMetadataAttr(name, value, this));
+ }
+ }
+
+ public void removeAttribute(String name) throws DOMException {
+ IIOMetadataAttr attr = (IIOMetadataAttr) attrs.getNamedItem(name);
+ if (attr != null) {
+ attr.setOwnerElement(null);
+ attrs.list.remove(attr);
+ }
+ }
+
+ public Attr getAttributeNode(String name) {
+ return (Attr) attrs.getNamedItem(name);
+ }
+
+ public Attr setAttributeNode(Attr newAttr) throws DOMException {
+ // Check if this attribute is already in use.
+ Element owner = newAttr.getOwnerElement();
+ if (owner != null) {
+ if (owner == this) { // Replacing an attribute node by itself has no effect
+ return null;
+ } else {
+ throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, "Attribute is already in use");
+ }
+ }
+
+ String name = newAttr.getName();
+ Attr oldAttr = getAttributeNode(name);
+ if (oldAttr != null) {
+ removeAttributeNode(oldAttr);
+ }
+
+ IIOMetadataAttr iioAttr;
+ if (newAttr instanceof IIOMetadataAttr) {
+ iioAttr = (IIOMetadataAttr) newAttr;
+ iioAttr.setOwnerElement(this);
+ } else {
+ iioAttr = new IIOMetadataAttr(name, newAttr.getValue(), this);
+ }
+
+ attrs.list.add(iioAttr);
+
+ return oldAttr;
+ }
+
+ public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
+ if (!attrs.list.remove(oldAttr)) { // Not found
+ throw new DOMException(DOMException.NOT_FOUND_ERR, "No such attribute!");
+ }
+
+ ((IIOMetadataAttr)oldAttr).setOwnerElement(null);
+
+ return oldAttr;
+ }
+
+ public NodeList getElementsByTagName(String name) {
+ ArrayList<IIOMetadataNode> nodes = new ArrayList<IIOMetadataNode>();
+
+ // Non-recursive tree walk
+ Node pos = this;
+
+ while (pos != null) {
+ if (pos.getNodeName().equals(name)) {
+ nodes.add((IIOMetadataNode)pos);
+ }
+
+ Node nextNode = pos.getFirstChild();
+
+ while (nextNode == null) {
+ if (pos == this) {
+ break;
+ }
+
+ nextNode = pos.getNextSibling();
+
+ if (nextNode == null) {
+ pos = pos.getParentNode();
+
+ if (pos == null || pos == this) {
+ nextNode = null;
+ break;
+ }
+ }
+ }
+ pos = nextNode;
+ }
+
+ return new IIOMetadataNodeList(nodes);
+ }
+
+ public String getAttributeNS(String namespaceURI, String localName) throws DOMException {
+ return getAttribute(localName);
+ }
+
+ public void setAttributeNS(String namespaceURI, String qualifiedName, String value) throws DOMException {
+ setAttribute(qualifiedName, value);
+ }
+
+ public void removeAttributeNS(String namespaceURI, String localName) throws DOMException {
+ removeAttribute(localName);
+ }
+
+ public Attr getAttributeNodeNS(String namespaceURI, String localName) throws DOMException {
+ return getAttributeNode(localName);
+ }
+
+ public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
+ return setAttributeNode(newAttr);
+ }
+
+ public NodeList getElementsByTagNameNS(String namespaceURI, String localName) throws DOMException {
+ return getElementsByTagName(localName);
+ }
+
+ public boolean hasAttribute(String name) {
+ return attrs.getNamedItem(name) != null;
+ }
+
+ public boolean hasAttributeNS(String namespaceURI, String localName) throws DOMException {
+ return hasAttribute(localName);
+ }
+
+ //???AWT
+ /*
+ public TypeInfo getSchemaTypeInfo() {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }*/
+
+ public void setIdAttribute(String name, boolean isId) throws DOMException {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) throws DOMException {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public void setIdAttributeNode(Attr idAttr, boolean isId) throws DOMException {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public String getNodeName() {
+ return nodeName;
+ }
+
+ public String getNodeValue() throws DOMException {
+ return nodeValue;
+ }
+
+ public void setNodeValue(String nodeValue) throws DOMException {
+ this.nodeValue = nodeValue;
+ }
+
+ public short getNodeType() {
+ return ELEMENT_NODE;
+ }
+
+ public Node getParentNode() {
+ return parent;
+ }
+
+ public NodeList getChildNodes() {
+ return this;
+ }
+
+ public Node getFirstChild() {
+ return firstChild;
+ }
+
+ public Node getLastChild() {
+ return lastChild;
+ }
+
+ public Node getPreviousSibling() {
+ return previousSibling;
+ }
+
+ public Node getNextSibling() {
+ return nextSibling;
+ }
+
+ public NamedNodeMap getAttributes() {
+ return attrs;
+ }
+
+ public Document getOwnerDocument() {
+ return null;
+ }
+
+ public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+ if (newChild == null) {
+ throw new IllegalArgumentException("newChild == null!");
+ }
+
+ IIOMetadataNode newIIOChild = (IIOMetadataNode) newChild;
+ IIOMetadataNode refIIOChild = (IIOMetadataNode) refChild;
+
+ newIIOChild.parent = this;
+
+ if (refIIOChild == null) {
+ newIIOChild.nextSibling = null;
+ newIIOChild.previousSibling = lastChild;
+
+ // Fix this node
+ lastChild = newIIOChild;
+ if (firstChild == null) {
+ firstChild = newIIOChild;
+ }
+ } else {
+ newIIOChild.nextSibling = refIIOChild;
+ newIIOChild.previousSibling = refIIOChild.previousSibling;
+
+ // Fix this node
+ if (firstChild == refIIOChild) {
+ firstChild = newIIOChild;
+ }
+
+ // Fix next node
+ if (refIIOChild != null) {
+ refIIOChild.previousSibling = newIIOChild;
+ }
+ }
+
+ // Fix prev node
+ if (newIIOChild.previousSibling != null) {
+ newIIOChild.previousSibling.nextSibling = newIIOChild;
+ }
+
+ nChildren++;
+
+ return newIIOChild;
+ }
+
+ public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+ if (newChild == null) {
+ throw new IllegalArgumentException("newChild == null!");
+ }
+
+ IIOMetadataNode newIIOChild = (IIOMetadataNode) newChild;
+ IIOMetadataNode oldIIOChild = (IIOMetadataNode) oldChild;
+
+ IIOMetadataNode next = oldIIOChild.nextSibling;
+ IIOMetadataNode previous = oldIIOChild.previousSibling;
+
+ // Fix new node
+ newIIOChild.parent = this;
+ newIIOChild.nextSibling = next;
+ newIIOChild.previousSibling = previous;
+
+ // Fix this node
+ if (lastChild == oldIIOChild) {
+ lastChild = newIIOChild;
+ }
+ if (firstChild == oldIIOChild) {
+ firstChild = newIIOChild;
+ }
+
+ // Fix siblings
+ if (next != null) {
+ next.previousSibling = newIIOChild;
+ }
+ if (previous != null) {
+ previous.nextSibling = newIIOChild;
+ }
+
+ // Fix old child
+ oldIIOChild.parent = null;
+ oldIIOChild.nextSibling = next;
+ oldIIOChild.previousSibling = previous;
+
+ return oldIIOChild;
+ }
+
+ public Node removeChild(Node oldChild) throws DOMException {
+ if (oldChild == null) {
+ throw new IllegalArgumentException("oldChild == null!");
+ }
+
+ IIOMetadataNode oldIIOChild = (IIOMetadataNode) oldChild;
+
+ // Fix next and previous
+ IIOMetadataNode previous = oldIIOChild.previousSibling;
+ IIOMetadataNode next = oldIIOChild.nextSibling;
+
+ if (previous != null) {
+ previous.nextSibling = next;
+ }
+ if (next != null) {
+ next.previousSibling = previous;
+ }
+
+ // Fix this node
+ if (lastChild == oldIIOChild) {
+ lastChild = previous;
+ }
+ if (firstChild == oldIIOChild) {
+ firstChild = next;
+ }
+ nChildren--;
+
+ // Fix old child
+ oldIIOChild.parent = null;
+ oldIIOChild.previousSibling = null;
+ oldIIOChild.nextSibling = null;
+
+ return oldIIOChild;
+ }
+
+ public Node appendChild(Node newChild) throws DOMException {
+ return insertBefore(newChild, null);
+ }
+
+ public boolean hasChildNodes() {
+ return nChildren != 0;
+ }
+
+ public Node cloneNode(boolean deep) {
+ IIOMetadataNode cloned = new IIOMetadataNode(nodeName);
+ cloned.setUserObject(getUserObject());
+
+ if (deep) { // Clone recursively
+ IIOMetadataNode c = firstChild;
+ while (c != null) {
+ cloned.insertBefore(c.cloneNode(true), null);
+ c = c.nextSibling;
+ }
+ }
+
+ return cloned; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void normalize() {
+ // Do nothing
+ }
+
+ public boolean isSupported(String feature, String version) {
+ return false;
+ }
+
+ public String getNamespaceURI() {
+ return null;
+ }
+
+ public String getPrefix() {
+ return null;
+ }
+
+ public void setPrefix(String prefix) throws DOMException {
+ // Do nothing
+ }
+
+ public String getLocalName() {
+ return nodeName;
+ }
+
+ public boolean hasAttributes() {
+ return attrs.list.size() > 0;
+ }
+
+ public String getBaseURI() {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public short compareDocumentPosition(Node other) throws DOMException {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public String getTextContent() throws DOMException {
+ return textContent;
+ }
+
+ public void setTextContent(String textContent) throws DOMException {
+ this.textContent = textContent;
+ }
+
+ public boolean isSameNode(Node other) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public String lookupPrefix(String namespaceURI) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public boolean isDefaultNamespace(String namespaceURI) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public String lookupNamespaceURI(String prefix) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public boolean isEqualNode(Node arg) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public Object getFeature(String feature, String version) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ //???AWT
+ /*
+ public Object setUserData(String key, Object data, UserDataHandler handler) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }*/
+
+ public Object getUserData(String key) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ public Node item(int index) {
+ if (index < 0 || index >= nChildren) {
+ return null;
+ }
+
+ Node n;
+ for (n = getFirstChild(); index > 0; index--) {
+ n = n.getNextSibling();
+ }
+
+ return n;
+ }
+
+ public int getLength() {
+ return nChildren;
+ }
+
+ /**
+ * Gets the user object associated with this node.
+ *
+ * @return the user object associated with this node
+ */
+ public Object getUserObject() {
+ return userObject;
+ }
+
+ /**
+ * Sets the user object associated with this node.
+ *
+ * @param userObject the new user object associated with this node
+ */
+ public void setUserObject(Object userObject) {
+ this.userObject = userObject;
+ }
+
+ /**
+ * The Class IIOMetadataAttr.
+ */
+ private class IIOMetadataAttr extends IIOMetadataNode implements Attr {
+
+ /** The owner element. */
+ private Element ownerElement;
+
+ /**
+ * Instantiates a new iIO metadata attr.
+ *
+ * @param name the name
+ * @param value the value
+ * @param owner the owner
+ */
+ public IIOMetadataAttr(String name, String value, Element owner) {
+ super(name, value);
+ this.ownerElement = owner;
+ }
+
+ public String getName() {
+ return getNodeName();
+ }
+
+ public boolean getSpecified() {
+ return true;
+ }
+
+ public String getValue() {
+ return nodeValue;
+ }
+
+ public void setValue(String value) throws DOMException {
+ nodeValue = value;
+ }
+
+ public Element getOwnerElement() {
+ return ownerElement;
+ }
+
+ /**
+ * Sets the owner element.
+ *
+ * @param ownerElement the new owner element
+ */
+ public void setOwnerElement(Element ownerElement) {
+ this.ownerElement = ownerElement;
+ }
+
+ public boolean isId() {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
+ }
+
+ @Override
+ public short getNodeType() {
+ return ATTRIBUTE_NODE;
+ }
+ }
+
+ /**
+ * The Class IIOMetadataNodeList.
+ */
+ private class IIOMetadataNodeList implements NodeList, NamedNodeMap {
+
+ /** The list. */
+ private List<IIOMetadataNode> list;
+
+ /**
+ * Instantiates a new iIO metadata node list.
+ *
+ * @param list the list
+ */
+ IIOMetadataNodeList(List<IIOMetadataNode> list) {
+ this.list = list;
+ }
+
+ public Node item(int index) {
+ try {
+ return list.get(index);
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+
+ public int getLength() {
+ return list.size();
+ }
+
+ public Node getNamedItem(String name) {
+ for(IIOMetadataNode node:list) {
+ if (name.equals(node.getNodeName())) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ public Node setNamedItem(Node arg) throws DOMException {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
+ }
+
+ public Node removeNamedItem(String name) throws DOMException {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
+ }
+
+ public Node getNamedItemNS(String namespaceURI, String localName) throws DOMException {
+ return getNamedItem(localName);
+ }
+
+ public Node setNamedItemNS(Node arg) throws DOMException {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
+ }
+
+ public Node removeNamedItemNS(String namespaceURI, String localName) throws DOMException {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
+ }
+ }
+}
diff --git a/awt/javax/imageio/metadata/IIOStandardMetadataFormat.java b/awt/javax/imageio/metadata/IIOStandardMetadataFormat.java
new file mode 100644
index 0000000..94d2125
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOStandardMetadataFormat.java
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.imageio.metadata;
+
+import javax.imageio.ImageTypeSpecifier;
+import java.util.ArrayList;
+
+/**
+ * The Class IIOStandardMetadataFormat describes the rules of the
+ * standard metadata format.
+ */
+class IIOStandardMetadataFormat extends IIOMetadataFormatImpl {
+
+ /**
+ * Instantiates a new IIOStandardMetadataFormat.
+ */
+ public IIOStandardMetadataFormat() {
+ super(standardMetadataFormatName, CHILD_POLICY_SOME);
+ buildDTD();
+ }
+
+ @Override
+ public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) {
+ return true;
+ }
+
+ /**
+ * Builds the dtd that describes the standard metadata format.
+ */
+ private void buildDTD() {
+ // CHROMA
+ addElement("Chroma", standardMetadataFormatName, CHILD_POLICY_SOME);
+
+ addElement("ColorSpaceType", "Chroma", CHILD_POLICY_EMPTY);
+
+ ArrayList<String> values = new ArrayList<String>(27);
+ values.add("XYZ");
+ values.add("Lab");
+ values.add("Luv");
+ values.add("YCbCr");
+ values.add("Yxy");
+ values.add("YCCK");
+ values.add("PhotoYCC");
+ values.add("RGB");
+ values.add("GRAY");
+ values.add("HSV");
+ values.add("HLS");
+ values.add("CMYK");
+ values.add("CMY");
+ values.add("2CLR");
+ values.add("3CLR");
+ values.add("4CLR");
+ values.add("5CLR");
+ values.add("6CLR");
+ values.add("7CLR");
+ values.add("8CLR");
+ values.add("9CLR");
+ values.add("ACLR");
+ values.add("BCLR");
+ values.add("CCLR");
+ values.add("DCLR");
+ values.add("ECLR");
+ values.add("FCLR");
+ addAttribute("ColorSpaceType", "name", DATATYPE_STRING, true, null, values);
+
+ addElement("NumChannels", "Chroma", CHILD_POLICY_EMPTY);
+ addAttribute("NumChannels", "value", DATATYPE_INTEGER, true, 0, Integer.MAX_VALUE); // list - why?
+
+ addElement("Gamma", "Chroma", CHILD_POLICY_EMPTY);
+ addAttribute("Gamma", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("BlackIsZero", "Chroma", CHILD_POLICY_EMPTY);
+ addBooleanAttribute("BlackIsZero", "value", true, true);
+
+ addElement("Palette", "Chroma", 0, Integer.MAX_VALUE); // CHILD_POLICY_REPEAT
+ addElement("PaletteEntry", "Palette", CHILD_POLICY_EMPTY);
+ addAttribute("PaletteEntry", "index", DATATYPE_INTEGER, true, null);
+ addAttribute("PaletteEntry", "red", DATATYPE_INTEGER, true, null);
+ addAttribute("PaletteEntry", "green", DATATYPE_INTEGER, true, null);
+ addAttribute("PaletteEntry", "blue", DATATYPE_INTEGER, true, null);
+ addAttribute("PaletteEntry", "alpha", DATATYPE_INTEGER, false, "255");
+
+ addElement("BackgroundIndex", "Chroma", CHILD_POLICY_EMPTY);
+ addAttribute("BackgroundIndex", "value", DATATYPE_INTEGER, true, null);
+
+ addElement("BackgroundColor", "Chroma", CHILD_POLICY_EMPTY);
+ addAttribute("BackgroundColor", "red", DATATYPE_INTEGER, true, null);
+ addAttribute("BackgroundColor", "green", DATATYPE_INTEGER, true, null);
+ addAttribute("BackgroundColor", "blue", DATATYPE_INTEGER, true, null);
+
+ // COMPRESSION
+ addElement("Compression", standardMetadataFormatName, CHILD_POLICY_SOME);
+
+ addElement("CompressionTypeName", "Compression", CHILD_POLICY_EMPTY);
+ addAttribute("CompressionTypeName", "value", DATATYPE_STRING, true, null);
+
+ addElement("Lossless", "Compression", CHILD_POLICY_EMPTY);
+ addBooleanAttribute("Lossless", "value", true, true);
+
+ addElement("NumProgressiveScans", "Compression", CHILD_POLICY_EMPTY);
+ addAttribute("NumProgressiveScans", "value", DATATYPE_INTEGER, true, null);
+
+ addElement("BitRate", "Compression", CHILD_POLICY_EMPTY);
+ addAttribute("BitRate", "value", DATATYPE_FLOAT, true, null);
+
+ // DATA
+ addElement("Data", standardMetadataFormatName, CHILD_POLICY_SOME);
+
+ addElement("PlanarConfiguration", "Data", CHILD_POLICY_EMPTY);
+ values = new ArrayList<String>(4);
+ values.add("PixelInterleaved");
+ values.add("PlaneInterleaved");
+ values.add("LineInterleaved");
+ values.add("TileInterleaved");
+ addAttribute("PlanarConfiguration", "value", DATATYPE_STRING, true, null, values);
+
+ addElement("SampleFormat", "Data", CHILD_POLICY_EMPTY);
+ values = new ArrayList<String>(4);
+ values.add("SignedIntegral");
+ values.add("UnsignedIntegral");
+ values.add("Real");
+ values.add("Index");
+ addAttribute("SampleFormat", "value", DATATYPE_STRING, true, null, values);
+
+ addElement("BitsPerSample", "Data", CHILD_POLICY_EMPTY);
+ addAttribute("BitsPerSample", "value", DATATYPE_INTEGER, true, 1, Integer.MAX_VALUE); // list
+
+ addElement("SignificantBitsPerSample", "Data", CHILD_POLICY_EMPTY);
+ addAttribute(
+ "SignificantBitsPerSample", "value",
+ DATATYPE_INTEGER, true, 1, Integer.MAX_VALUE
+ ); // list
+
+ addElement("SampleMSB", "Data", CHILD_POLICY_EMPTY);
+ addAttribute("SampleMSB", "value", DATATYPE_INTEGER, true, 1, Integer.MAX_VALUE); // list
+
+ // DIMENSION
+ addElement("Dimension", standardMetadataFormatName, CHILD_POLICY_SOME);
+
+ addElement("PixelAspectRatio", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("PixelAspectRatio", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("ImageOrientation", "Dimension", CHILD_POLICY_EMPTY);
+ values = new ArrayList<String>(8);
+ values.add("Normal");
+ values.add("Rotate90");
+ values.add("Rotate180");
+ values.add("Rotate270");
+ values.add("FlipH");
+ values.add("FlipV");
+ values.add("FlipHRotate90");
+ values.add("FlipVRotate90");
+ addAttribute("ImageOrientation", "value", DATATYPE_STRING, true, null, values);
+
+ addElement("HorizontalPixelSize", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("HorizontalPixelSize", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("VerticalPixelSize", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("VerticalPixelSize", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("HorizontalPhysicalPixelSpacing", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("HorizontalPhysicalPixelSpacing", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("VerticalPhysicalPixelSpacing", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("VerticalPhysicalPixelSpacing", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("HorizontalPosition", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("HorizontalPosition", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("VerticalPosition", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("VerticalPosition", "value", DATATYPE_FLOAT, true, null);
+
+ addElement("HorizontalPixelOffset", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("HorizontalPixelOffset", "value", DATATYPE_INTEGER, true, null);
+
+ addElement("VerticalPixelOffset", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("VerticalPixelOffset", "value", DATATYPE_INTEGER, true, null);
+
+ addElement("HorizontalScreenSize", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("HorizontalScreenSize", "value", DATATYPE_INTEGER, true, null);
+
+ addElement("VerticalScreenSize", "Dimension", CHILD_POLICY_EMPTY);
+ addAttribute("VerticalScreenSize", "value", DATATYPE_INTEGER, true, null);
+
+ // DOCUMENT
+ addElement("Document", standardMetadataFormatName, CHILD_POLICY_SOME);
+
+ addElement("FormatVersion", "Document", CHILD_POLICY_EMPTY);
+ addAttribute("FormatVersion", "value", DATATYPE_STRING, true, null);
+
+ addElement("SubimageInterpretation", "Document", CHILD_POLICY_EMPTY);
+ values = new ArrayList<String>(14);
+ values.add("Standalone");
+ values.add("SinglePage");
+ values.add("FullResolution");
+ values.add("ReducedResolution");
+ values.add("PyramidLayer");
+ values.add("Preview");
+ values.add("VolumeSlice");
+ values.add("ObjectView");
+ values.add("Panorama");
+ values.add("AnimationFrame");
+ values.add("TransparencyMask");
+ values.add("CompositingLayer");
+ values.add("SpectralSlice");
+ values.add("Unknown");
+ addAttribute("SubimageInterpretation", "value", DATATYPE_STRING, true, null, values);
+
+ addElement("ImageCreationTime", "Document", CHILD_POLICY_EMPTY);
+ addAttribute("ImageCreationTime", "year", DATATYPE_INTEGER, true, null);
+ addAttribute(
+ "ImageCreationTime", "month",
+ DATATYPE_INTEGER, true, null, "1", "12", true, true
+ );
+ addAttribute(
+ "ImageCreationTime", "day",
+ DATATYPE_INTEGER, true, null, "1", "31", true, true
+ );
+ addAttribute(
+ "ImageCreationTime", "hour",
+ DATATYPE_INTEGER, false, "0", "0", "23", true, true
+ );
+ addAttribute(
+ "ImageCreationTime", "minute",
+ DATATYPE_INTEGER, false, "0", "0", "59", true, true
+ );
+ addAttribute(
+ "ImageCreationTime", "second",
+ DATATYPE_INTEGER, false, "0", "0", "60", true, true
+ );
+
+ addElement("ImageModificationTime", "Document", CHILD_POLICY_EMPTY);
+ addAttribute("ImageModificationTime", "year", DATATYPE_INTEGER, true, null);
+ addAttribute(
+ "ImageModificationTime", "month",
+ DATATYPE_INTEGER, true, null, "1", "12", true, true
+ );
+ addAttribute(
+ "ImageModificationTime", "day",
+ DATATYPE_INTEGER, true, null, "1", "31", true, true
+ );
+ addAttribute(
+ "ImageModificationTime", "hour",
+ DATATYPE_INTEGER, false, "0", "0", "23", true, true
+ );
+ addAttribute(
+ "ImageModificationTime", "minute",
+ DATATYPE_INTEGER, false, "0", "0", "59", true, true
+ );
+ addAttribute(
+ "ImageModificationTime", "second",
+ DATATYPE_INTEGER, false, "0", "0", "60", true, true
+ );
+
+ // TEXT
+ addElement("Text", standardMetadataFormatName, 0, Integer.MAX_VALUE); // CHILD_POLICY_REPEAT
+
+ addElement("TextEntry", "Text", CHILD_POLICY_EMPTY);
+ addAttribute("TextEntry", "keyword", DATATYPE_STRING, false, null);
+ addAttribute("TextEntry", "value", DATATYPE_STRING, true, null);
+ addAttribute("TextEntry", "language", DATATYPE_STRING, false, null);
+ addAttribute("TextEntry", "encoding", DATATYPE_STRING, false, null);
+ values = new ArrayList<String>(5);
+ values.add("none");
+ values.add("lzw");
+ values.add("zip");
+ values.add("bzip");
+ values.add("other");
+ addAttribute("TextEntry", "compression", DATATYPE_STRING, false, "none", values);
+
+ // TRANSPARENCY
+ addElement("Transparency", standardMetadataFormatName, CHILD_POLICY_SOME);
+
+ addElement("Alpha", "Transparency", CHILD_POLICY_EMPTY);
+ values = new ArrayList<String>(3);
+ values.add("none");
+ values.add("premultiplied");
+ values.add("nonpremultiplied");
+ addAttribute("Alpha", "value", DATATYPE_STRING, false, "none", values);
+
+ addElement("TransparentIndex", "Transparency", CHILD_POLICY_EMPTY);
+ addAttribute("TransparentIndex", "value", DATATYPE_INTEGER, true, null);
+
+ addElement("TransparentColor", "Transparency", CHILD_POLICY_EMPTY);
+ addAttribute("TransparentColor", "value", DATATYPE_INTEGER, true, 0, Integer.MAX_VALUE);
+
+ addElement("TileTransparencies", "Transparency", 0, Integer.MAX_VALUE); // CHILD_POLICY_REPEAT
+
+ addElement("TransparentTile", "TileTransparencies", CHILD_POLICY_EMPTY);
+ addAttribute("TransparentTile", "x", DATATYPE_INTEGER, true, null);
+ addAttribute("TransparentTile", "y", DATATYPE_INTEGER, true, null);
+
+ addElement("TileOpacities", "Transparency", 0, Integer.MAX_VALUE); // CHILD_POLICY_REPEAT
+
+ addElement("OpaqueTile", "TileOpacities", CHILD_POLICY_EMPTY);
+ addAttribute("OpaqueTile", "x", DATATYPE_INTEGER, true, null);
+ addAttribute("OpaqueTile", "y", DATATYPE_INTEGER, true, null);
+ }
+}
+
diff --git a/awt/javax/imageio/metadata/IIOStandardMetadataFormatResources.properties b/awt/javax/imageio/metadata/IIOStandardMetadataFormatResources.properties
new file mode 100644
index 0000000..d185808
--- /dev/null
+++ b/awt/javax/imageio/metadata/IIOStandardMetadataFormatResources.properties
@@ -0,0 +1,133 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Descriptions of elements and attributes of the plugin neutral metadata format
+# (see IIOStandardMetadataFormat)
+
+# Messages for EN locale
+Chroma=Chroma (color) information
+ColorSpaceType=The raw color space of the image
+ColorSpaceType/name=The raw color space of the image
+NumChannels=The number of channels in the raw image, including alpha
+NumChannels/value=The number of channels in the raw image, including alpha
+Gamma=The image gamma
+Gamma/value=The image gamma
+BlackIsZero=True if smaller values represent darker shades
+BlackIsZero/value=True if smaller values represent darker shades
+Palette=Palette-color information
+PaletteEntry=A palette entry
+PaletteEntry/index=The index of the palette entry
+PaletteEntry/red=The red value for the palette entry
+PaletteEntry/green=The green value for the palette entry
+PaletteEntry/blue=The blue value for the palette entry
+PaletteEntry/alpha=The alpha value for the palette entry
+BackgroundIndex=A palette index to be used as a background
+BackgroundIndex/value=A palette index to be used as a background
+BackgroundColor=An RGB triple to be used as a background
+BackgroundColor/red=The red background value
+BackgroundColor/green=The green background value
+BackgroundColor/blue=The blue background value
+
+Compression=Compression information
+CompressionTypeName=The name of the compression scheme in use
+CompressionTypeName/value=The name of the compression scheme in use
+Lossless=True if the compression scheme is lossless
+Lossless/value=True if the compression scheme is lossless
+NumProgressiveScans=The number of progressive scans used in the image encoding
+NumProgressiveScans/value=The number of progressive scans used in the image encoding
+BitRate=The estimated bit rate of the compression scheme
+BitRate/value=The estimated bit rate of the compression scheme
+
+Data=Information on the image layout
+PlanarConfiguration=The organization of image samples in the stream
+PlanarConfiguration/value=The organization of image samples in the stream
+SampleFormat=The numeric format of image samples
+SampleFormat/value=The numeric format of image samples
+BitsPerSample=The number of bits per sample
+BitsPerSample/value=A list of integers, one per channel
+SignificantBitsPerSample=The number of significant bits per sample
+SignificantBitsPerSample/value=A list of integers, one per channel
+SampleMSB=The position of the most significant bit of each sample
+SampleMSB/value=A list of integers, one per channel
+
+Dimension=Dimension information
+PixelAspectRatio=The width of a pixel divided by its height
+PixelAspectRatio/value=The width of a pixel divided by its height
+ImageOrientation=The desired orientation of the image in terms of flips and counter-clockwise rotations
+ImageOrientation/value=The desired orientation of the image in terms of flips and counter-clockwise rotations
+HorizontalPixelSize=The width of a pixel, in millimeters, as it should be rendered on media
+HorizontalPixelSize/value=The width of a pixel, in millimeters, as it should be rendered on media
+VerticalPixelSize=The height of a pixel, in millimeters, as it should be rendered on media
+VerticalPixelSize/value=The height of a pixel, in millimeters, as it should be rendered on media
+HorizontalPhysicalPixelSpacing=The horizontal distance in the subject of the image, in millimeters, represented by one pixel at the center of the image
+HorizontalPhysicalPixelSpacing/value=The horizontal distance in the subject of the image, in millimeters, represented by one pixel at the center of the image
+VerticalPhysicalPixelSpacing=The vertical distance in the subject of the image, in millimeters, represented by one pixel at the center of the image
+VerticalPhysicalPixelSpacing/value=The vertical distance in the subject of the image, in millimeters, represented by one pixel at the center of the image
+HorizontalPosition=The horizontal position, in millimeters, where the image should be rendered on media
+HorizontalPosition/value=The horizontal position, in millimeters, where the image should be rendered on media
+VerticalPosition=The vertical position, in millimeters, where the image should be rendered on media
+VerticalPosition/value=The vertical position, in millimeters, where the image should be rendered on media
+HorizontalPixelOffset=The horizonal position, in pixels, where the image should be rendered onto a raster display
+HorizontalPixelOffset/value=The horizonal position, in pixels, where the image should be rendered onto a raster display
+VerticalPixelOffset=The vertical position, in pixels, where the image should be rendered onto a raster display
+VerticalPixelOffset/value=The vertical position, in pixels, where the image should be rendered onto a raster display
+HorizontalScreenSize=The width, in pixels, of the raster display into which the image should be rendered
+HorizontalScreenSize/value=The width, in pixels, of the raster display into which the image should be rendered
+VerticalScreenSize=The height, in pixels, of the raster display into which the image should be rendered
+VerticalScreenSize/value=The height, in pixels, of the raster display into which the image should be rendered
+
+Document=Document information
+FormatVersion=The version of the format used by the stream
+FormatVersion/value=The version of the format used by the stream
+SubimageInterpretation=The interpretation of this image in relation to the other images stored in the same stream
+SubimageInterpretation/value=The interpretation of this image in relation to the other images stored in the same stream
+ImageCreationTime=The time of image creation
+ImageCreationTime/year=The full year (e.g., 1967, not 67)
+ImageCreationTime/month=The month, with January = 1
+ImageCreationTime/day=The day of the month
+ImageCreationTime/hour=The hour from 0 to 23
+ImageCreationTime/minute=The minute from 0 to 59
+ImageCreationTime/second=The second from 0 to 60 (60 = leap second)
+ImageModificationTime=The time of the last image modification
+ImageModificationTime/year=The full year (e.g., 1967, not 67)
+ImageModificationTime/month=The month, with January = 1
+ImageModificationTime/day=The day of the month
+ImageModificationTime/hour=The hour from 0 to 23
+ImageModificationTime/minute=The minute from 0 to 59
+ImageModificationTime/second=The second from 0 to 60 (60 = leap second)
+
+Text=Text information
+TextEntry=A text entry
+TextEntry/keyword=A keyword associated with the text entry
+TextEntry/value=the text entry
+TextEntry/language=The language of the text
+TextEntry/encoding=The encoding of the text
+TextEntry/compression=The method used to compress the text
+
+Transparency=Transparency information
+Alpha=The type of alpha information contained in the image
+Alpha/value=The type of alpha information contained in the image
+TransparentIndex=A palette index to be treated as transparent
+TransparentIndex/value=A palette index to be treated as transparent
+TransparentColor=An RGB color to be treated as transparent
+TransparentColor/value=An RGB color to be treated as transparent
+TileTransparencies=A list of completely transparent tiles
+TransparentTile=The index of a completely transparent tile
+TransparentTile/x=The tile's X index
+TransparentTile/y=The tile's Y index
+TileOpacities=A list of completely opaque tiles
+OpaqueTile=The index of a completely opaque tile
+OpaqueTile/x=The tile's X index
+OpaqueTile/y=The tile's Y index