1 /* IIOMetadataFormatImpl.java --
2    Copyright (C) 2004  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package javax.imageio.metadata;
40 
41 import org.w3c.dom.Attr;
42 import org.w3c.dom.DOMException;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.NamedNodeMap;
46 import org.w3c.dom.Node;
47 import org.w3c.dom.NodeList;
48 import org.w3c.dom.TypeInfo;
49 import org.w3c.dom.UserDataHandler;
50 import java.util.ArrayList;
51 import java.util.HashMap;
52 import java.util.Map;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Locale;
56 import java.util.ResourceBundle;
57 import java.util.MissingResourceException;
58 import javax.imageio.ImageTypeSpecifier;
59 
60 public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
61 {
62   /**
63    * The standard metadata format name constant set to
64    * "javax_imageio_1.0".
65    */
66   public static final String standardMetadataFormatName = "javax_imageio_1.0";
67 
68   private String rootName;
69 
70   // These maps assume that each element name is unique.
71 
72   private Map nodes = new HashMap();
73 
74   // A mapping from element name to child policy.
75   private Map childPolicies = new HashMap();
76 
77   // A mapping from element name to the permissible number of
78   // children.  Values in this map are length-two integer arrays; the
79   // first index is the minimum bound, the second index is the maximum
80   // bound.
81   private Map childRanges = new HashMap();
82 
83   private String resourceBaseName;
84 
85   // Package-private so that it may be used in IIOMetadataNode.
86   static class IIOMetadataNodeAttr extends IIOMetadataNode
87     implements Attr
88   {
89     protected Element owner;
90     protected String name;
91     protected int dataType;
92     protected boolean required;
93     protected String defaultValue;
94 
IIOMetadataNodeAttr(Element owner, String name, String defaultValue)95     public IIOMetadataNodeAttr (Element owner,
96 				String name,
97 				String defaultValue)
98     {
99       this (owner, name, IIOMetadataFormat.DATATYPE_STRING,
100             true, defaultValue);
101     }
102 
IIOMetadataNodeAttr(Element owner, String name, int dataType, boolean required, String defaultValue)103     public IIOMetadataNodeAttr (Element owner,
104 				String name,
105 				int dataType,
106 				boolean required,
107 				String defaultValue)
108     {
109       this.owner = owner;
110       this.name = name;
111       this.dataType = dataType;
112       this.required = required;
113       this.defaultValue = defaultValue;
114     }
115 
getName()116     public String getName ()
117     {
118       return name;
119     }
120 
getOwnerElement()121     public Element getOwnerElement ()
122     {
123       return owner;
124     }
125 
getDataType()126     public int getDataType ()
127     {
128       return dataType;
129     }
130 
getSchemaTypeInfo()131     public TypeInfo getSchemaTypeInfo ()
132     {
133       return null;
134     }
135 
getSpecified()136     public boolean getSpecified ()
137     {
138       return false;
139     }
140 
getValue()141     public String getValue ()
142     {
143       return defaultValue;
144     }
145 
isId()146     public boolean isId()
147     {
148       return false;
149     }
150 
setValue(String value)151     public void setValue (String value)
152     {
153     }
154 
155     // new methods
156 
isRequired()157     public boolean isRequired ()
158     {
159       return required;
160     }
161   }
162 
163   private class IIOMetadataNodeAttrEnumerated extends IIOMetadataNodeAttr
164   {
165     protected List enumeratedValues;
166 
IIOMetadataNodeAttrEnumerated(Element owner, String name, int dataType, boolean required, String defaultValue, List enumeratedValues)167     public IIOMetadataNodeAttrEnumerated (Element owner,
168 					  String name,
169 					  int dataType,
170 					  boolean required,
171 					  String defaultValue,
172 					  List enumeratedValues)
173     {
174       super (owner, name, dataType, required, defaultValue);
175       this.enumeratedValues = new ArrayList (enumeratedValues);
176     }
177 
getEnumerations()178     public Object[] getEnumerations ()
179     {
180       return enumeratedValues.toArray ();
181     }
182   }
183 
184   private class IIOMetadataNodeAttrBounded extends IIOMetadataNodeAttr
185   {
186     protected String minValue;
187     protected String maxValue;
188     protected boolean minInclusive;
189     protected boolean maxInclusive;
190 
IIOMetadataNodeAttrBounded(Element owner, String name, int dataType, boolean required, String defaultValue, String minValue, String maxValue, boolean minInclusive, boolean maxInclusive)191     public IIOMetadataNodeAttrBounded (Element owner,
192 				       String name,
193 				       int dataType,
194 				       boolean required,
195 				       String defaultValue,
196 				       String minValue,
197 				       String maxValue,
198 				       boolean minInclusive,
199 				       boolean maxInclusive)
200     {
201       super (owner, name, dataType, required, defaultValue);
202       this.minValue = minValue;
203       this.maxValue = maxValue;
204       this.minInclusive = minInclusive;
205       this.maxInclusive = maxInclusive;
206     }
207 
getMinValue()208     public String getMinValue ()
209     {
210       return minValue;
211     }
212 
getMaxValue()213     public String getMaxValue ()
214     {
215       return maxValue;
216     }
217   }
218 
219   private class IIOMetadataNodeAttrList extends IIOMetadataNodeAttr
220   {
221     protected int listMinLength;
222     protected int listMaxLength;
223 
IIOMetadataNodeAttrList(Element owner, String name, int dataType, boolean required, int listMinLength, int listMaxLength)224     public IIOMetadataNodeAttrList (Element owner,
225 				    String name,
226 				    int dataType,
227 				    boolean required,
228 				    int listMinLength,
229 				    int listMaxLength)
230     {
231       super (owner, name, dataType, required, null);
232       this.listMinLength = listMinLength;
233       this.listMaxLength = listMaxLength;
234     }
235 
getListMinLength()236     public int getListMinLength ()
237     {
238       return listMinLength;
239     }
240 
getListMaxLength()241     public int getListMaxLength ()
242     {
243       return listMaxLength;
244     }
245   }
246 
247   private class NodeObject
248   {
249     protected Element owner;
250     protected Class classType;
251     protected boolean required;
252     protected Object defaultValue;
253     protected int valueType;
254 
NodeObject(Element owner, Class classType, boolean required, Object defaultValue)255     public NodeObject (Element owner,
256                        Class classType,
257                        boolean required,
258                        Object defaultValue)
259     {
260       this.owner = owner;
261       this.classType = classType;
262       this.required = required;
263       this.defaultValue = defaultValue;
264       valueType = IIOMetadataFormat.VALUE_ARBITRARY;
265     }
266 
getValueType()267     public int getValueType ()
268     {
269       return valueType;
270     }
271 
getClassType()272     public Class getClassType ()
273     {
274       return classType;
275     }
276 
getOwnerElement()277     public Element getOwnerElement ()
278     {
279       return owner;
280     }
281 
getDefaultValue()282     public Object getDefaultValue ()
283     {
284       return defaultValue;
285     }
286 
isRequired()287     public boolean isRequired ()
288     {
289       return required;
290     }
291   }
292 
293   private class NodeObjectEnumerated extends NodeObject
294   {
295     protected List enumeratedValues;
296 
NodeObjectEnumerated(Element owner, Class classType, boolean required, Object defaultValue, List enumeratedValues)297     public NodeObjectEnumerated (Element owner,
298                                  Class classType,
299                                  boolean required,
300                                  Object defaultValue,
301                                  List enumeratedValues)
302     {
303       super (owner, classType, false, defaultValue);
304       this.enumeratedValues = enumeratedValues;
305       valueType = IIOMetadataFormat.VALUE_ENUMERATION;
306     }
307 
getEnumerations()308     public Object[] getEnumerations ()
309     {
310       return enumeratedValues.toArray();
311     }
312   }
313 
314   private class NodeObjectBounded extends NodeObject
315   {
316     protected Comparable minValue;
317     protected Comparable maxValue;
318     protected boolean minInclusive;
319     protected boolean maxInclusive;
320 
NodeObjectBounded(Element owner, Class classType, Object defaultValue, Comparable minValue, Comparable maxValue, boolean minInclusive, boolean maxInclusive)321     public NodeObjectBounded (Element owner,
322                               Class classType,
323                               Object defaultValue,
324                               Comparable minValue,
325                               Comparable maxValue,
326                               boolean minInclusive,
327                               boolean maxInclusive)
328     {
329       super (owner, classType, false, defaultValue);
330       this.minValue = minValue;
331       this.maxValue = maxValue;
332       this.minInclusive = minInclusive;
333       this.maxInclusive = maxInclusive;
334       if (minInclusive)
335         {
336           if (maxInclusive)
337             valueType = IIOMetadataFormat.VALUE_RANGE_MIN_MAX_INCLUSIVE;
338           else
339             valueType = IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE;
340         }
341       else
342         {
343           if (maxInclusive)
344             valueType = IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE;
345           else
346             valueType = IIOMetadataFormat.VALUE_RANGE;
347         }
348     }
349 
getMinValue()350     public Comparable getMinValue ()
351     {
352       return minValue;
353     }
354 
getMaxValue()355     public Comparable getMaxValue ()
356     {
357       return maxValue;
358     }
359   }
360 
361   private class NodeObjectArray extends NodeObject
362   {
363     protected Integer arrayMinLength;
364     protected Integer arrayMaxLength;
365 
NodeObjectArray(Element owner, Class classType, int arrayMinLength, int arrayMaxLength)366     public NodeObjectArray (Element owner,
367                             Class classType,
368                             int arrayMinLength,
369                             int arrayMaxLength)
370     {
371       super (owner, classType, false, null);
372       this.arrayMinLength = new Integer (arrayMinLength);
373       this.arrayMaxLength = new Integer (arrayMaxLength);
374       valueType = IIOMetadataFormat.VALUE_LIST;
375     }
376 
getArrayMinLength()377     public Comparable getArrayMinLength ()
378     {
379       return arrayMinLength;
380     }
381 
getArrayMaxLength()382     public Comparable getArrayMaxLength ()
383     {
384       return arrayMaxLength;
385     }
386   }
387 
388   /**
389    * Construct a blank IIOMetadataFormatImpl with the given root name
390    * and child policy.
391    *
392    * @param rootName the root element name
393    * @param childPolicy the child policy of the root element
394    *
395    * @exception IllegalArgumentException if rootName is null
396    * @exception IllegalArgumentException if childPolicy is
397    * CHILD_POLICY_REPEAT or if childPolicy is not a CHILD_POLICY
398    * constant
399    */
IIOMetadataFormatImpl(String rootName, int childPolicy)400   public IIOMetadataFormatImpl (String rootName, int childPolicy)
401   {
402     if (rootName == null)
403       throw new IllegalArgumentException ("null argument");
404 
405     if (childPolicy < IIOMetadataFormat.CHILD_POLICY_ALL
406 	|| childPolicy > IIOMetadataFormat.CHILD_POLICY_SOME
407 	|| childPolicy == IIOMetadataFormat.CHILD_POLICY_REPEAT)
408       throw new IllegalArgumentException ("wrong child policy");
409 
410     nodes.put (rootName, new IIOMetadataNode (rootName));
411     childPolicies.put (rootName, new Integer (childPolicy));
412     this.rootName = rootName;
413   }
414 
415   /**
416    * Construct a blank IIOMetadataFormatImpl with the given root name,
417    * a child policy of CHILD_POLICY_REPEAT and the given minimum and
418    * maximum limits on the number of root element children.
419    *
420    * @param rootName the root element name
421    * @param minChildren the minimum number of children that this node
422    * can have
423    * @param maxChildren the maximum number of children that this node
424    * can have
425    *
426    * @exception IllegalArgumentException if rootName is null
427    * @exception IllegalArgumentException if minChildren is less than
428    * zero or greater than maxChildren
429    */
IIOMetadataFormatImpl(String rootName, int minChildren, int maxChildren)430   public IIOMetadataFormatImpl (String rootName,
431 				int minChildren,
432 				int maxChildren)
433   {
434     if (rootName == null)
435       throw new IllegalArgumentException ("null argument");
436 
437     if (minChildren < 0 || maxChildren < minChildren)
438       throw new IllegalArgumentException ("invalid min or max children argument");
439 
440     nodes.put (rootName, new IIOMetadataNode (rootName));
441     childPolicies.put (rootName, new Integer (IIOMetadataFormat.CHILD_POLICY_REPEAT));
442     childRanges.put (rootName, new int [] { minChildren, maxChildren });
443     this.rootName = rootName;
444   }
445 
addAttribute(String elementName, String attrName, int dataType, boolean required, String defaultValue)446   protected void addAttribute (String elementName,
447                                String attrName,
448                                int dataType,
449                                boolean required,
450                                String defaultValue)
451   {
452     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
453     node.setAttributeNode (new IIOMetadataNodeAttr (node,
454 						    attrName,
455 						    dataType,
456 						    required,
457 						    defaultValue));
458   }
459 
addAttribute(String elementName, String attrName, int dataType, boolean required, String defaultValue, List enumeratedValues)460   protected void addAttribute (String elementName,
461                                String attrName,
462                                int dataType,
463                                boolean required,
464                                String defaultValue,
465                                List enumeratedValues)
466   {
467     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
468     node.setAttributeNode (new IIOMetadataNodeAttrEnumerated (node,
469 							      attrName,
470 							      dataType,
471 							      required,
472 							      defaultValue,
473 							      enumeratedValues));
474   }
475 
addAttribute(String elementName, String attrName, int dataType, boolean required, String defaultValue, String minValue, String maxValue, boolean minInclusive, boolean maxInclusive)476   protected void addAttribute (String elementName,
477                                String attrName,
478                                int dataType,
479                                boolean required,
480                                String defaultValue,
481                                String minValue,
482                                String maxValue,
483                                boolean minInclusive,
484                                boolean maxInclusive)
485   {
486     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
487     node.setAttributeNode (new IIOMetadataNodeAttrBounded (node,
488 							   attrName,
489 							   dataType,
490 							   required,
491 							   defaultValue,
492 							   minValue,
493 							   maxValue,
494 							   minInclusive,
495 							   maxInclusive));
496   }
497 
addAttribute(String elementName, String attrName, int dataType, boolean required, int listMinLength, int listMaxLength)498   protected void addAttribute (String elementName,
499                                String attrName,
500                                int dataType,
501                                boolean required,
502                                int listMinLength,
503                                int listMaxLength)
504   {
505     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
506     node.setAttributeNode (new IIOMetadataNodeAttrList (node,
507 							attrName,
508 							dataType,
509 							required,
510 							listMinLength,
511 							listMaxLength));
512   }
513 
addBooleanAttribute(String elementName, String attrName, boolean hasDefaultValue, boolean defaultValue)514   protected void addBooleanAttribute (String elementName,
515                                       String attrName,
516                                       boolean hasDefaultValue,
517                                       boolean defaultValue)
518   {
519     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
520 
521     List enumeratedValues = new ArrayList();
522     enumeratedValues.add ("TRUE");
523     enumeratedValues.add ("FALSE");
524 
525     node.setAttributeNode (new IIOMetadataNodeAttrEnumerated (node,
526 							      attrName,
527 							      IIOMetadataFormat.DATATYPE_BOOLEAN,
528 							      hasDefaultValue,
529 							      defaultValue ? "TRUE" : "FALSE",
530 							      enumeratedValues));
531   }
532 
addChildElement(String elementName, String parentName)533   protected void addChildElement (String elementName, String parentName)
534   {
535     IIOMetadataNode node = (IIOMetadataNode) nodes.get (parentName);
536 
537     node.appendChild (new IIOMetadataNode (elementName));
538     childPolicies.put (elementName, new Integer (IIOMetadataFormat.CHILD_POLICY_REPEAT));
539   }
540 
addElement(String elementName, String parentName, int childPolicy)541   protected void addElement (String elementName, String parentName, int childPolicy)
542   {
543     IIOMetadataNode node = (IIOMetadataNode) nodes.get (parentName);
544 
545     node.appendChild (new IIOMetadataNode (elementName));
546     childPolicies.put (elementName, new Integer (childPolicy));
547   }
548 
addElement(String elementName, String parentName, int minChildren, int maxChildren)549   protected void addElement (String elementName, String parentName,
550                              int minChildren, int maxChildren)
551   {
552     addChildElement (elementName, parentName);
553     childRanges.put (elementName, new int [] { minChildren, maxChildren });
554   }
555 
addNodeObject(IIOMetadataNode node, NodeObject o)556   private void addNodeObject (IIOMetadataNode node, NodeObject o)
557   {
558     node.setUserObject (o);
559   }
560 
getNodeObject(IIOMetadataNode node)561   private NodeObject getNodeObject (IIOMetadataNode node)
562   {
563     return (NodeObject) node.getUserObject ();
564   }
565 
removeNodeObject(IIOMetadataNode node)566   private void removeNodeObject (IIOMetadataNode node)
567   {
568     node.setUserObject (null);
569   }
570 
addObjectValue(String elementName, Class classType, boolean required, Object defaultValue)571   protected void addObjectValue (String elementName, Class classType,
572                                  boolean required, Object defaultValue)
573   {
574     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
575     addNodeObject (node, new NodeObject (node,
576                                          classType,
577                                          required,
578                                          defaultValue));
579   }
580 
addObjectValue(String elementName, Class classType, boolean required, Object defaultValue, List enumeratedValues)581   protected void addObjectValue (String elementName, Class classType,
582                                  boolean required, Object defaultValue,
583                                  List enumeratedValues)
584   {
585     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
586     addNodeObject (node, new NodeObjectEnumerated (node,
587                                                    classType,
588                                                    required,
589                                                    defaultValue,
590                                                    enumeratedValues));
591   }
592 
addObjectValue(String elementName, Class classType, Object defaultValue, Comparable minValue, Comparable maxValue, boolean minInclusive, boolean maxInclusive)593   protected void addObjectValue (String elementName, Class classType,
594                                  Object defaultValue,
595                                  Comparable minValue,
596                                  Comparable maxValue,
597                                  boolean minInclusive,
598                                  boolean maxInclusive)
599   {
600     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
601     addNodeObject (node, new NodeObjectBounded (node,
602                                                 classType,
603                                                 defaultValue,
604                                                 minValue,
605                                                 maxValue,
606                                                 minInclusive,
607                                                 maxInclusive));
608   }
609 
addObjectValue(String elementName, Class classType, int arrayMinLength, int arrayMaxLength)610   protected void addObjectValue (String elementName, Class classType,
611                                  int arrayMinLength, int arrayMaxLength)
612   {
613     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
614     addNodeObject (node, new NodeObjectArray (node,
615                                               classType,
616                                               arrayMinLength,
617                                               arrayMaxLength));
618   }
619 
getRootName()620   public String getRootName ()
621   {
622     return rootName;
623   }
624 
getResourceBaseName()625   protected String getResourceBaseName ()
626   {
627     return resourceBaseName;
628   }
629 
getStandardFormatInstance()630   public static IIOMetadataFormat getStandardFormatInstance ()
631   {
632     // FIXME: populate this with the standard metadata format
633     return new IIOMetadataFormatImpl (standardMetadataFormatName,
634                                       IIOMetadataFormat.CHILD_POLICY_ALL)
635       {
636         public boolean canNodeAppear (String elementName,
637                                       ImageTypeSpecifier specifier)
638         {
639           return true;
640         }
641       };
642   }
643 
644   public abstract boolean canNodeAppear (String elementName,
645                                          ImageTypeSpecifier specifier);
646 
647   protected void removeAttribute (String elementName,
648                                   String attrName)
649   {
650     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
651     node.removeAttribute (attrName);
652   }
653 
654   protected void removeElement (String elementName)
655   {
656     nodes.remove (elementName);
657   }
658 
659   protected void removeObjectValue (String elementName)
660   {
661     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
662     removeNodeObject (node);
663   }
664 
665   protected void setResourceBaseName (String resourceBaseName)
666   {
667     this.resourceBaseName = resourceBaseName;
668   }
669 
670   public int getAttributeDataType (String elementName, String attrName)
671   {
672     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
673     IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) node.getAttributeNode (attrName);
674     return attr.getDataType ();
675   }
676 
677   public String getAttributeDefaultValue (String elementName, String attrName)
678   {
679     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
680     IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) node.getAttributeNode (attrName);
681     return attr.getValue();
682   }
683 
684   public String getAttributeDescription (String elementName, String attrName, Locale locale)
685   {
686     return getDescription (elementName + "/" + attrName, locale);
687   }
688 
689   public String[] getAttributeEnumerations (String elementName, String attrName)
690   {
691     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
692     IIOMetadataNodeAttrEnumerated attr =
693       (IIOMetadataNodeAttrEnumerated) node.getAttributeNode (attrName);
694 
695     Object[] attrEnums = attr.getEnumerations();
696 
697     String[] attrNames = new String[attrEnums.length];
698 
699     for (int i = 0; i < attrEnums.length; i++)
700       {
701         attrNames[i] = (String) attrEnums[i];
702       }
703 
704     return attrNames;
705   }
706 
707   public int getAttributeListMaxLength (String elementName, String attrName)
708   {
709     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
710     IIOMetadataNodeAttrList attr =
711       (IIOMetadataNodeAttrList) node.getAttributeNode (attrName);
712     return attr.getListMaxLength();
713   }
714 
715   public int getAttributeListMinLength (String elementName, String attrName)
716   {
717     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
718     IIOMetadataNodeAttrList attr =
719       (IIOMetadataNodeAttrList) node.getAttributeNode (attrName);
720     return attr.getListMinLength();
721   }
722 
723   public String getAttributeMaxValue (String elementName, String attrName)
724   {
725     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
726     IIOMetadataNodeAttrBounded attr =
727       (IIOMetadataNodeAttrBounded) node.getAttributeNode (attrName);
728     return attr.getMaxValue();
729   }
730 
731   public String getAttributeMinValue (String elementName, String attrName)
732   {
733     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
734     IIOMetadataNodeAttrBounded attr =
735       (IIOMetadataNodeAttrBounded) node.getAttributeNode (attrName);
736     return attr.getMinValue();
737   }
738 
739   public String[] getAttributeNames (String elementName)
740   {
741     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
742 
743     NamedNodeMap attrNodes = node.getAttributes();
744 
745     String[] attrNames = new String[attrNodes.getLength()];
746 
747     for (int i = 0; i < attrNodes.getLength(); i++)
748       {
749         attrNames[i] = attrNodes.item (i).getLocalName();
750       }
751 
752     return attrNames;
753   }
754 
755   public int getAttributeValueType (String elementName, String attrName)
756   {
757     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
758     IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) node.getAttributeNode (attrName);
759     return attr.getDataType();
760   }
761 
762   public String[] getChildNames (String elementName)
763   {
764     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
765 
766     NodeList childNodes = node.getChildNodes();
767 
768     String[] childNames = new String[childNodes.getLength()];
769 
770     for (int i = 0; i < childNodes.getLength(); i++)
771       {
772         childNames[i] = childNodes.item (i).getLocalName();
773       }
774 
775     return childNames;
776   }
777 
778   public int getChildPolicy (String elementName)
779   {
780     return ((Integer) childPolicies.get (elementName)).intValue();
781   }
782 
783   private String getDescription (String resourceName, Locale locale)
784   {
785     if (resourceBaseName == null)
786       return null;
787 
788     Locale l = locale;
789 
790     if (l == null)
791       l = Locale.getDefault();
792 
793     ResourceBundle bundle = ResourceBundle.getBundle (resourceBaseName, locale);
794 
795     String desc = null;
796 
797     if (bundle == null)
798       {
799         try
800           {
801             desc = bundle.getString (resourceName);
802           }
803         catch (MissingResourceException e)
804           {
805             desc = null;
806           }
807       }
808 
809     return desc;
810   }
811 
812   public String getElementDescription (String elementName, Locale locale)
813   {
814     return getDescription (elementName, locale);
815   }
816 
817   public int getElementMaxChildren (String elementName)
818   {
819     return ((int[]) childRanges.get (elementName))[1];
820   }
821 
822   public int getElementMinChildren (String elementName)
823   {
824     return ((int[]) childRanges.get (elementName))[0];
825   }
826 
827   public int getObjectArrayMaxLength (String elementName)
828   {
829     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
830     return ((Integer) ((NodeObjectArray) getNodeObject (node)).getArrayMaxLength ()).intValue();
831   }
832 
833   public int getObjectArrayMinLength (String elementName)
834   {
835     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
836     return ((Integer) ((NodeObjectArray) getNodeObject (node)).getArrayMinLength ()).intValue();
837   }
838 
839   public Class getObjectClass (String elementName)
840   {
841     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
842     return getNodeObject (node).getClassType ();
843   }
844 
845   public Object getObjectDefaultValue (String elementName)
846   {
847     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
848     return getNodeObject (node).getDefaultValue ();
849   }
850 
851   public Object[] getObjectEnumerations (String elementName)
852   {
853     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
854     return ((NodeObjectEnumerated) getNodeObject (node)).getEnumerations ();
855   }
856 
857   public Comparable getObjectMaxValue (String elementName)
858   {
859     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
860     return ((NodeObjectBounded) getNodeObject (node)).getMaxValue ();
861   }
862 
863   public Comparable getObjectMinValue (String elementName)
864   {
865     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
866     return ((NodeObjectBounded) getNodeObject (node)).getMinValue ();
867   }
868 
869   public int getObjectValueType (String elementName)
870   {
871     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
872     NodeObject n = getNodeObject (node);
873 
874     if (n == null)
875       return IIOMetadataFormat.VALUE_NONE;
876     else
877       return n.getValueType ();
878   }
879 
880   public boolean isAttributeRequired (String elementName, String attrName)
881   {
882     IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
883     return ((IIOMetadataNodeAttr) node.getAttributeNode (attrName)).isRequired();
884   }
885 }
886