History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/imageio/metadata/IIOMetadataFormatImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/imageio/metadata/IIOMetadataFormatImpl.java+1270−0
@@ -0,0 +1,1270 @@
1+/*
2+ * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.imageio.metadata;
27+
28+import java.util.ArrayList;
29+import java.util.Collection;
30+import java.util.HashMap;
31+import java.util.Iterator;
32+import java.util.List;
33+import java.util.Locale;
34+import java.util.Map;
35+import java.util.MissingResourceException;
36+import java.util.ResourceBundle;
37+import javax.imageio.ImageTypeSpecifier;
38+import com.sun.imageio.plugins.common.StandardMetadataFormat;
39+
40+/**
41+ * A concrete class providing a reusable implementation of the
42+ * <code>IIOMetadataFormat</code> interface. In addition, a static
43+ * instance representing the standard, plug-in neutral
44+ * <code>javax_imageio_1.0</code> format is provided by the
45+ * <code>getStandardFormatInstance</code> method.
46+ *
47+ * <p> In order to supply localized descriptions of elements and
48+ * attributes, a <code>ResourceBundle</code> with a base name of
49+ * <code>this.getClass().getName() + "Resources"</code> should be
50+ * supplied via the usual mechanism used by
51+ * <code>ResourceBundle.getBundle</code>. Briefly, the subclasser
52+ * supplies one or more additional classes according to a naming
53+ * convention (by default, the fully-qualified name of the subclass
54+ * extending <code>IIMetadataFormatImpl</code>, plus the string
55+ * "Resources", plus the country, language, and variant codes
56+ * separated by underscores). At run time, calls to
57+ * <code>getElementDescription</code> or
58+ * <code>getAttributeDescription</code> will attempt to load such
59+ * classes dynamically according to the supplied locale, and will use
60+ * either the element name, or the element name followed by a '/'
61+ * character followed by the attribute name as a key. This key will
62+ * be supplied to the <code>ResourceBundle</code>'s
63+ * <code>getString</code> method, and the resulting localized
64+ * description of the node or attribute is returned.
65+ *
66+ * <p> The subclass may supply a different base name for the resource
67+ * bundles using the <code>setResourceBaseName</code> method.
68+ *
69+ * <p> A subclass may choose its own localization mechanism, if so
70+ * desired, by overriding the supplied implementations of
71+ * <code>getElementDescription</code> and
72+ * <code>getAttributeDescription</code>.
73+ *
74+ * @see ResourceBundle#getBundle(String,Locale)
75+ *
76+ */
77+public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat {
78+
79+ /**
80+ * A <code>String</code> constant containing the standard format
81+ * name, <code>"javax_imageio_1.0"</code>.
82+ */
83+ public static final String standardMetadataFormatName =
84+ "javax_imageio_1.0";
85+
86+ private static IIOMetadataFormat standardFormat = null;
87+
88+ private String resourceBaseName = this.getClass().getName() + "Resources";
89+
90+ private String rootName;
91+
92+ // Element name (String) -> Element
93+ private HashMap elementMap = new HashMap();
94+
95+ class Element {
96+ String elementName;
97+
98+ int childPolicy;
99+ int minChildren = 0;
100+ int maxChildren = 0;
101+
102+ // Child names (Strings)
103+ List childList = new ArrayList();
104+
105+ // Parent names (Strings)
106+ List parentList = new ArrayList();
107+
108+ // List of attribute names in the order they were added
109+ List attrList = new ArrayList();
110+ // Attr name (String) -> Attribute
111+ Map attrMap = new HashMap();
112+
113+ ObjectValue objectValue;
114+ }
115+
116+ class Attribute {
117+ String attrName;
118+
119+ int valueType = VALUE_ARBITRARY;
120+ int dataType;
121+ boolean required;
122+ String defaultValue = null;
123+
124+ // enumeration
125+ List enumeratedValues;
126+
127+ // range
128+ String minValue;
129+ String maxValue;
130+
131+ // list
132+ int listMinLength;
133+ int listMaxLength;
134+ }
135+
136+ class ObjectValue {
137+ int valueType = VALUE_NONE;
138+ Class classType = null;
139+ Object defaultValue = null;
140+
141+ // Meaningful only if valueType == VALUE_ENUMERATION
142+ List enumeratedValues = null;
143+
144+ // Meaningful only if valueType == VALUE_RANGE
145+ Comparable minValue = null;
146+ Comparable maxValue = null;
147+
148+ // Meaningful only if valueType == VALUE_LIST
149+ int arrayMinLength = 0;
150+ int arrayMaxLength = 0;
151+ }
152+
153+ /**
154+ * Constructs a blank <code>IIOMetadataFormatImpl</code> instance,
155+ * with a given root element name and child policy (other than
156+ * <code>CHILD_POLICY_REPEAT</code>). Additional elements, and
157+ * their attributes and <code>Object</code> reference information
158+ * may be added using the various <code>add</code> methods.
159+ *
160+ * @param rootName the name of the root element.
161+ * @param childPolicy one of the <code>CHILD_POLICY_*</code> constants,
162+ * other than <code>CHILD_POLICY_REPEAT</code>.
163+ *
164+ * @exception IllegalArgumentException if <code>rootName</code> is
165+ * <code>null</code>.
166+ * @exception IllegalArgumentException if <code>childPolicy</code> is
167+ * not one of the predefined constants.
168+ */
169+ public IIOMetadataFormatImpl(String rootName,
170+ int childPolicy) {
171+ if (rootName == null) {
172+ throw new IllegalArgumentException("rootName == null!");
173+ }
174+ if (childPolicy < CHILD_POLICY_EMPTY ||
175+ childPolicy > CHILD_POLICY_MAX ||
176+ childPolicy == CHILD_POLICY_REPEAT) {
177+ throw new IllegalArgumentException("Invalid value for childPolicy!");
178+ }
179+
180+ this.rootName = rootName;
181+
182+ Element root = new Element();
183+ root.elementName = rootName;
184+ root.childPolicy = childPolicy;
185+
186+ elementMap.put(rootName, root);
187+ }
188+
189+ /**
190+ * Constructs a blank <code>IIOMetadataFormatImpl</code> instance,
191+ * with a given root element name and a child policy of
192+ * <code>CHILD_POLICY_REPEAT</code>. Additional elements, and
193+ * their attributes and <code>Object</code> reference information
194+ * may be added using the various <code>add</code> methods.
195+ *
196+ * @param rootName the name of the root element.
197+ * @param minChildren the minimum number of children of the node.
198+ * @param maxChildren the maximum number of children of the node.
199+ *
200+ * @exception IllegalArgumentException if <code>rootName</code> is
201+ * <code>null</code>.
202+ * @exception IllegalArgumentException if <code>minChildren</code>
203+ * is negative or larger than <code>maxChildren</code>.
204+ */
205+ public IIOMetadataFormatImpl(String rootName,
206+ int minChildren,
207+ int maxChildren) {
208+ if (rootName == null) {
209+ throw new IllegalArgumentException("rootName == null!");
210+ }
211+ if (minChildren < 0) {
212+ throw new IllegalArgumentException("minChildren < 0!");
213+ }
214+ if (minChildren > maxChildren) {
215+ throw new IllegalArgumentException("minChildren > maxChildren!");
216+ }
217+
218+ Element root = new Element();
219+ root.elementName = rootName;
220+ root.childPolicy = CHILD_POLICY_REPEAT;
221+ root.minChildren = minChildren;
222+ root.maxChildren = maxChildren;
223+
224+ this.rootName = rootName;
225+ elementMap.put(rootName, root);
226+ }
227+
228+ /**
229+ * Sets a new base name for locating <code>ResourceBundle</code>s
230+ * containing descriptions of elements and attributes for this
231+ * format.
232+ *
233+ * <p> Prior to the first time this method is called, the base
234+ * name will be equal to <code>this.getClass().getName() +
235+ * "Resources"</code>.
236+ *
237+ * @param resourceBaseName a <code>String</code> containg the new
238+ * base name.
239+ *
240+ * @exception IllegalArgumentException if
241+ * <code>resourceBaseName</code> is <code>null</code>.
242+ *
243+ * @see #getResourceBaseName
244+ */
245+ protected void setResourceBaseName(String resourceBaseName) {
246+ if (resourceBaseName == null) {
247+ throw new IllegalArgumentException("resourceBaseName == null!");
248+ }
249+ this.resourceBaseName = resourceBaseName;
250+ }
251+
252+ /**
253+ * Returns the currently set base name for locating
254+ * <code>ResourceBundle</code>s.
255+ *
256+ * @return a <code>String</code> containing the base name.
257+ *
258+ * @see #setResourceBaseName
259+ */
260+ protected String getResourceBaseName() {
261+ return resourceBaseName;
262+ }
263+
264+ /**
265+ * Utility method for locating an element.
266+ *
267+ * @param mustAppear if <code>true</code>, throw an
268+ * <code>IllegalArgumentException</code> if no such node exists;
269+ * if <code>false</code>, just return null.
270+ */
271+ private Element getElement(String elementName, boolean mustAppear) {
272+ if (mustAppear && (elementName == null)) {
273+ throw new IllegalArgumentException("element name is null!");
274+ }
275+ Element element = (Element)elementMap.get(elementName);
276+ if (mustAppear && (element == null)) {
277+ throw new IllegalArgumentException("No such element: " +
278+ elementName);
279+ }
280+ return element;
281+ }
282+
283+ private Element getElement(String elementName) {
284+ return getElement(elementName, true);
285+ }
286+
287+ // Utility method for locating an attribute
288+ private Attribute getAttribute(String elementName, String attrName) {
289+ Element element = getElement(elementName);
290+ Attribute attr = (Attribute)element.attrMap.get(attrName);
291+ if (attr == null) {
292+ throw new IllegalArgumentException("No such attribute \"" +
293+ attrName + "\"!");
294+ }
295+ return attr;
296+ }
297+
298+ // Setup
299+
300+ /**
301+ * Adds a new element type to this metadata document format with a
302+ * child policy other than <code>CHILD_POLICY_REPEAT</code>.
303+ *
304+ * @param elementName the name of the new element.
305+ * @param parentName the name of the element that will be the
306+ * parent of the new element.
307+ * @param childPolicy one of the <code>CHILD_POLICY_*</code>
308+ * constants, other than <code>CHILD_POLICY_REPEAT</code>,
309+ * indicating the child policy of the new element.
310+ *
311+ * @exception IllegalArgumentException if <code>parentName</code>
312+ * is <code>null</code>, or is not a legal element name for this
313+ * format.
314+ * @exception IllegalArgumentException if <code>childPolicy</code>
315+ * is not one of the predefined constants.
316+ */
317+ protected void addElement(String elementName,
318+ String parentName,
319+ int childPolicy) {
320+ Element parent = getElement(parentName);
321+ if (childPolicy < CHILD_POLICY_EMPTY ||
322+ childPolicy > CHILD_POLICY_MAX ||
323+ childPolicy == CHILD_POLICY_REPEAT) {
324+ throw new IllegalArgumentException
325+ ("Invalid value for childPolicy!");
326+ }
327+
328+ Element element = new Element();
329+ element.elementName = elementName;
330+ element.childPolicy = childPolicy;
331+
332+ parent.childList.add(elementName);
333+ element.parentList.add(parentName);
334+
335+ elementMap.put(elementName, element);
336+ }
337+
338+ /**
339+ * Adds a new element type to this metadata document format with a
340+ * child policy of <code>CHILD_POLICY_REPEAT</code>.
341+ *
342+ * @param elementName the name of the new element.
343+ * @param parentName the name of the element that will be the
344+ * parent of the new element.
345+ * @param minChildren the minimum number of children of the node.
346+ * @param maxChildren the maximum number of children of the node.
347+ *
348+ * @exception IllegalArgumentException if <code>parentName</code>
349+ * is <code>null</code>, or is not a legal element name for this
350+ * format.
351+ * @exception IllegalArgumentException if <code>minChildren</code>
352+ * is negative or larger than <code>maxChildren</code>.
353+ */
354+ protected void addElement(String elementName,
355+ String parentName,
356+ int minChildren,
357+ int maxChildren) {
358+ Element parent = getElement(parentName);
359+ if (minChildren < 0) {
360+ throw new IllegalArgumentException("minChildren < 0!");
361+ }
362+ if (minChildren > maxChildren) {
363+ throw new IllegalArgumentException("minChildren > maxChildren!");
364+ }
365+
366+ Element element = new Element();
367+ element.elementName = elementName;
368+ element.childPolicy = CHILD_POLICY_REPEAT;
369+ element.minChildren = minChildren;
370+ element.maxChildren = maxChildren;
371+
372+ parent.childList.add(elementName);
373+ element.parentList.add(parentName);
374+
375+ elementMap.put(elementName, element);
376+ }
377+
378+ /**
379+ * Adds an existing element to the list of legal children for a
380+ * given parent node type.
381+ *
382+ * @param parentName the name of the element that will be the
383+ * new parent of the element.
384+ * @param elementName the name of the element to be addded as a
385+ * child.
386+ *
387+ * @exception IllegalArgumentException if <code>elementName</code>
388+ * is <code>null</code>, or is not a legal element name for this
389+ * format.
390+ * @exception IllegalArgumentException if <code>parentName</code>
391+ * is <code>null</code>, or is not a legal element name for this
392+ * format.
393+ */
394+ protected void addChildElement(String elementName, String parentName) {
395+ Element parent = getElement(parentName);
396+ Element element = getElement(elementName);
397+ parent.childList.add(elementName);
398+ element.parentList.add(parentName);
399+ }
400+
401+ /**
402+ * Removes an element from the format. If no element with the
403+ * given name was present, nothing happens and no exception is
404+ * thrown.
405+ *
406+ * @param elementName the name of the element to be removed.
407+ */
408+ protected void removeElement(String elementName) {
409+ Element element = getElement(elementName, false);
410+ if (element != null) {
411+ Iterator iter = element.parentList.iterator();
412+ while (iter.hasNext()) {
413+ String parentName = (String)iter.next();
414+ Element parent = getElement(parentName, false);
415+ if (parent != null) {
416+ parent.childList.remove(elementName);
417+ }
418+ }
419+ elementMap.remove(elementName);
420+ }
421+ }
422+
423+ /**
424+ * Adds a new attribute to a previously defined element that may
425+ * be set to an arbitrary value.
426+ *
427+ * @param elementName the name of the element.
428+ * @param attrName the name of the attribute being added.
429+ * @param dataType the data type (string format) of the attribute,
430+ * one of the <code>DATATYPE_*</code> constants.
431+ * @param required <code>true</code> if the attribute must be present.
432+ * @param defaultValue the default value for the attribute, or
433+ * <code>null</code>.
434+ *
435+ * @exception IllegalArgumentException if <code>elementName</code>
436+ * is <code>null</code>, or is not a legal element name for this
437+ * format.
438+ * @exception IllegalArgumentException if <code>attrName</code> is
439+ * <code>null</code>.
440+ * @exception IllegalArgumentException if <code>dataType</code> is
441+ * not one of the predefined constants.
442+ */
443+ protected void addAttribute(String elementName,
444+ String attrName,
445+ int dataType,
446+ boolean required,
447+ String defaultValue) {
448+ Element element = getElement(elementName);
449+ if (attrName == null) {
450+ throw new IllegalArgumentException("attrName == null!");
451+ }
452+ if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
453+ throw new IllegalArgumentException("Invalid value for dataType!");
454+ }
455+
456+ Attribute attr = new Attribute();
457+ attr.attrName = attrName;
458+ attr.valueType = VALUE_ARBITRARY;
459+ attr.dataType = dataType;
460+ attr.required = required;
461+ attr.defaultValue = defaultValue;
462+
463+ element.attrList.add(attrName);
464+ element.attrMap.put(attrName, attr);
465+ }
466+
467+ /**
468+ * Adds a new attribute to a previously defined element that will
469+ * be defined by a set of enumerated values.
470+ *
471+ * @param elementName the name of the element.
472+ * @param attrName the name of the attribute being added.
473+ * @param dataType the data type (string format) of the attribute,
474+ * one of the <code>DATATYPE_*</code> constants.
475+ * @param required <code>true</code> if the attribute must be present.
476+ * @param defaultValue the default value for the attribute, or
477+ * <code>null</code>.
478+ * @param enumeratedValues a <code>List</code> of
479+ * <code>String</code>s containing the legal values for the
480+ * attribute.
481+ *
482+ * @exception IllegalArgumentException if <code>elementName</code>
483+ * is <code>null</code>, or is not a legal element name for this
484+ * format.
485+ * @exception IllegalArgumentException if <code>attrName</code> is
486+ * <code>null</code>.
487+ * @exception IllegalArgumentException if <code>dataType</code> is
488+ * not one of the predefined constants.
489+ * @exception IllegalArgumentException if
490+ * <code>enumeratedValues</code> is <code>null</code>.
491+ * @exception IllegalArgumentException if
492+ * <code>enumeratedValues</code> does not contain at least one
493+ * entry.
494+ * @exception IllegalArgumentException if
495+ * <code>enumeratedValues</code> contains an element that is not a
496+ * <code>String</code> or is <code>null</code>.
497+ */
498+ protected void addAttribute(String elementName,
499+ String attrName,
500+ int dataType,
501+ boolean required,
502+ String defaultValue,
503+ List<String> enumeratedValues) {
504+ Element element = getElement(elementName);
505+ if (attrName == null) {
506+ throw new IllegalArgumentException("attrName == null!");
507+ }
508+ if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
509+ throw new IllegalArgumentException("Invalid value for dataType!");
510+ }
511+ if (enumeratedValues == null) {
512+ throw new IllegalArgumentException("enumeratedValues == null!");
513+ }
514+ if (enumeratedValues.size() == 0) {
515+ throw new IllegalArgumentException("enumeratedValues is empty!");
516+ }
517+ Iterator iter = enumeratedValues.iterator();
518+ while (iter.hasNext()) {
519+ Object o = iter.next();
520+ if (o == null) {
521+ throw new IllegalArgumentException
522+ ("enumeratedValues contains a null!");
523+ }
524+ if (!(o instanceof String)) {
525+ throw new IllegalArgumentException
526+ ("enumeratedValues contains a non-String value!");
527+ }
528+ }
529+
530+ Attribute attr = new Attribute();
531+ attr.attrName = attrName;
532+ attr.valueType = VALUE_ENUMERATION;
533+ attr.dataType = dataType;
534+ attr.required = required;
535+ attr.defaultValue = defaultValue;
536+ attr.enumeratedValues = enumeratedValues;
537+
538+ element.attrList.add(attrName);
539+ element.attrMap.put(attrName, attr);
540+ }
541+
542+ /**
543+ * Adds a new attribute to a previously defined element that will
544+ * be defined by a range of values.
545+ *
546+ * @param elementName the name of the element.
547+ * @param attrName the name of the attribute being added.
548+ * @param dataType the data type (string format) of the attribute,
549+ * one of the <code>DATATYPE_*</code> constants.
550+ * @param required <code>true</code> if the attribute must be present.
551+ * @param defaultValue the default value for the attribute, or
552+ * <code>null</code>.
553+ * @param minValue the smallest (inclusive or exclusive depending
554+ * on the value of <code>minInclusive</code>) legal value for the
555+ * attribute, as a <code>String</code>.
556+ * @param maxValue the largest (inclusive or exclusive depending
557+ * on the value of <code>minInclusive</code>) legal value for the
558+ * attribute, as a <code>String</code>.
559+ * @param minInclusive <code>true</code> if <code>minValue</code>
560+ * is inclusive.
561+ * @param maxInclusive <code>true</code> if <code>maxValue</code>
562+ * is inclusive.
563+ *
564+ * @exception IllegalArgumentException if <code>elementName</code>
565+ * is <code>null</code>, or is not a legal element name for this
566+ * format.
567+ * @exception IllegalArgumentException if <code>attrName</code> is
568+ * <code>null</code>.
569+ * @exception IllegalArgumentException if <code>dataType</code> is
570+ * not one of the predefined constants.
571+ */
572+ protected void addAttribute(String elementName,
573+ String attrName,
574+ int dataType,
575+ boolean required,
576+ String defaultValue,
577+ String minValue,
578+ String maxValue,
579+ boolean minInclusive,
580+ boolean maxInclusive) {
581+ Element element = getElement(elementName);
582+ if (attrName == null) {
583+ throw new IllegalArgumentException("attrName == null!");
584+ }
585+ if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
586+ throw new IllegalArgumentException("Invalid value for dataType!");
587+ }
588+
589+ Attribute attr = new Attribute();
590+ attr.attrName = attrName;
591+ attr.valueType = VALUE_RANGE;
592+ if (minInclusive) {
593+ attr.valueType |= VALUE_RANGE_MIN_INCLUSIVE_MASK;
594+ }
595+ if (maxInclusive) {
596+ attr.valueType |= VALUE_RANGE_MAX_INCLUSIVE_MASK;
597+ }
598+ attr.dataType = dataType;
599+ attr.required = required;
600+ attr.defaultValue = defaultValue;
601+ attr.minValue = minValue;
602+ attr.maxValue = maxValue;
603+
604+ element.attrList.add(attrName);
605+ element.attrMap.put(attrName, attr);
606+ }
607+
608+ /**
609+ * Adds a new attribute to a previously defined element that will
610+ * be defined by a list of values.
611+ *
612+ * @param elementName the name of the element.
613+ * @param attrName the name of the attribute being added.
614+ * @param dataType the data type (string format) of the attribute,
615+ * one of the <code>DATATYPE_*</code> constants.
616+ * @param required <code>true</code> if the attribute must be present.
617+ * @param listMinLength the smallest legal number of list items.
618+ * @param listMaxLength the largest legal number of list items.
619+ *
620+ * @exception IllegalArgumentException if <code>elementName</code>
621+ * is <code>null</code>, or is not a legal element name for this
622+ * format.
623+ * @exception IllegalArgumentException if <code>attrName</code> is
624+ * <code>null</code>.
625+ * @exception IllegalArgumentException if <code>dataType</code> is
626+ * not one of the predefined constants.
627+ * @exception IllegalArgumentException if
628+ * <code>listMinLength</code> is negative or larger than
629+ * <code>listMaxLength</code>.
630+ */
631+ protected void addAttribute(String elementName,
632+ String attrName,
633+ int dataType,
634+ boolean required,
635+ int listMinLength,
636+ int listMaxLength) {
637+ Element element = getElement(elementName);
638+ if (attrName == null) {
639+ throw new IllegalArgumentException("attrName == null!");
640+ }
641+ if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
642+ throw new IllegalArgumentException("Invalid value for dataType!");
643+ }
644+ if (listMinLength < 0 || listMinLength > listMaxLength) {
645+ throw new IllegalArgumentException("Invalid list bounds!");
646+ }
647+
648+ Attribute attr = new Attribute();
649+ attr.attrName = attrName;
650+ attr.valueType = VALUE_LIST;
651+ attr.dataType = dataType;
652+ attr.required = required;
653+ attr.listMinLength = listMinLength;
654+ attr.listMaxLength = listMaxLength;
655+
656+ element.attrList.add(attrName);
657+ element.attrMap.put(attrName, attr);
658+ }
659+
660+ /**
661+ * Adds a new attribute to a previously defined element that will
662+ * be defined by the enumerated values <code>TRUE</code> and
663+ * <code>FALSE</code>, with a datatype of
664+ * <code>DATATYPE_BOOLEAN</code>.
665+ *
666+ * @param elementName the name of the element.
667+ * @param attrName the name of the attribute being added.
668+ * @param hasDefaultValue <code>true</code> if a default value
669+ * should be present.
670+ * @param defaultValue the default value for the attribute as a
671+ * <code>boolean</code>, ignored if <code>hasDefaultValue</code>
672+ * is <code>false</code>.
673+ *
674+ * @exception IllegalArgumentException if <code>elementName</code>
675+ * is <code>null</code>, or is not a legal element name for this
676+ * format.
677+ * @exception IllegalArgumentException if <code>attrName</code> is
678+ * <code>null</code>.
679+ */
680+ protected void addBooleanAttribute(String elementName,
681+ String attrName,
682+ boolean hasDefaultValue,
683+ boolean defaultValue) {
684+ List values = new ArrayList();
685+ values.add("TRUE");
686+ values.add("FALSE");
687+
688+ String dval = null;
689+ if (hasDefaultValue) {
690+ dval = defaultValue ? "TRUE" : "FALSE";
691+ }
692+ addAttribute(elementName,
693+ attrName,
694+ DATATYPE_BOOLEAN,
695+ true,
696+ dval,
697+ values);
698+ }
699+
700+ /**
701+ * Removes an attribute from a previously defined element. If no
702+ * attribute with the given name was present in the given element,
703+ * nothing happens and no exception is thrown.
704+ *
705+ * @param elementName the name of the element.
706+ * @param attrName the name of the attribute being removed.
707+ *
708+ * @exception IllegalArgumentException if <code>elementName</code>
709+ * is <code>null</code>, or is not a legal element name for this format.
710+ */
711+ protected void removeAttribute(String elementName, String attrName) {
712+ Element element = getElement(elementName);
713+ element.attrList.remove(attrName);
714+ element.attrMap.remove(attrName);
715+ }
716+
717+ /**
718+ * Allows an <code>Object</code> reference of a given class type
719+ * to be stored in nodes implementing the named element. The
720+ * value of the <code>Object</code> is unconstrained other than by
721+ * its class type.
722+ *
723+ * <p> If an <code>Object</code> reference was previously allowed,
724+ * the previous settings are overwritten.
725+ *
726+ * @param elementName the name of the element.
727+ * @param classType a <code>Class</code> variable indicating the
728+ * legal class type for the object value.
729+ * @param required <code>true</code> if an object value must be present.
730+ * @param defaultValue the default value for the
731+ * <code>Object</code> reference, or <code>null</code>.
732+ *
733+ * @exception IllegalArgumentException if <code>elementName</code>
734+ * is <code>null</code>, or is not a legal element name for this format.
735+ */
736+ protected <T> void addObjectValue(String elementName,
737+ Class<T> classType,
738+ boolean required,
739+ T defaultValue)
740+ {
741+ Element element = getElement(elementName);
742+ ObjectValue obj = new ObjectValue();
743+ obj.valueType = VALUE_ARBITRARY;
744+ obj.classType = classType;
745+ obj.defaultValue = defaultValue;
746+
747+ element.objectValue = obj;
748+ }
749+
750+ /**
751+ * Allows an <code>Object</code> reference of a given class type
752+ * to be stored in nodes implementing the named element. The
753+ * value of the <code>Object</code> must be one of the values
754+ * given by <code>enumeratedValues</code>.
755+ *
756+ * <p> If an <code>Object</code> reference was previously allowed,
757+ * the previous settings are overwritten.
758+ *
759+ * @param elementName the name of the element.
760+ * @param classType a <code>Class</code> variable indicating the
761+ * legal class type for the object value.
762+ * @param required <code>true</code> if an object value must be present.
763+ * @param defaultValue the default value for the
764+ * <code>Object</code> reference, or <code>null</code>.
765+ * @param enumeratedValues a <code>List</code> of
766+ * <code>Object</code>s containing the legal values for the
767+ * object reference.
768+ *
769+ * @exception IllegalArgumentException if <code>elementName</code>
770+ * is <code>null</code>, or is not a legal element name for this format.
771+ * @exception IllegalArgumentException if
772+ * <code>enumeratedValues</code> is <code>null</code>.
773+ * @exception IllegalArgumentException if
774+ * <code>enumeratedValues</code> does not contain at least one
775+ * entry.
776+ * @exception IllegalArgumentException if
777+ * <code>enumeratedValues</code> contains an element that is not
778+ * an instance of the class type denoted by <code>classType</code>
779+ * or is <code>null</code>.
780+ */
781+ protected <T> void addObjectValue(String elementName,
782+ Class<T> classType,
783+ boolean required,
784+ T defaultValue,
785+ List<? extends T> enumeratedValues)
786+ {
787+ Element element = getElement(elementName);
788+ if (enumeratedValues == null) {
789+ throw new IllegalArgumentException("enumeratedValues == null!");
790+ }
791+ if (enumeratedValues.size() == 0) {
792+ throw new IllegalArgumentException("enumeratedValues is empty!");
793+ }
794+ Iterator iter = enumeratedValues.iterator();
795+ while (iter.hasNext()) {
796+ Object o = iter.next();
797+ if (o == null) {
798+ throw new IllegalArgumentException("enumeratedValues contains a null!");
799+ }
800+ if (!classType.isInstance(o)) {
801+ throw new IllegalArgumentException("enumeratedValues contains a value not of class classType!");
802+ }
803+ }
804+
805+ ObjectValue obj = new ObjectValue();
806+ obj.valueType = VALUE_ENUMERATION;
807+ obj.classType = classType;
808+ obj.defaultValue = defaultValue;
809+ obj.enumeratedValues = enumeratedValues;
810+
811+ element.objectValue = obj;
812+ }
813+
814+ /**
815+ * Allows an <code>Object</code> reference of a given class type
816+ * to be stored in nodes implementing the named element. The
817+ * value of the <code>Object</code> must be within the range given
818+ * by <code>minValue</code> and <code>maxValue</code>.
819+ * Furthermore, the class type must implement the
820+ * <code>Comparable</code> interface.
821+ *
822+ * <p> If an <code>Object</code> reference was previously allowed,
823+ * the previous settings are overwritten.
824+ *
825+ * @param elementName the name of the element.
826+ * @param classType a <code>Class</code> variable indicating the
827+ * legal class type for the object value.
828+ * @param defaultValue the default value for the
829+ * @param minValue the smallest (inclusive or exclusive depending
830+ * on the value of <code>minInclusive</code>) legal value for the
831+ * object value, as a <code>String</code>.
832+ * @param maxValue the largest (inclusive or exclusive depending
833+ * on the value of <code>minInclusive</code>) legal value for the
834+ * object value, as a <code>String</code>.
835+ * @param minInclusive <code>true</code> if <code>minValue</code>
836+ * is inclusive.
837+ * @param maxInclusive <code>true</code> if <code>maxValue</code>
838+ * is inclusive.
839+ *
840+ * @exception IllegalArgumentException if <code>elementName</code>
841+ * is <code>null</code>, or is not a legal element name for this
842+ * format.
843+ */
844+ protected <T extends Object & Comparable<? super T>> void
845+ addObjectValue(String elementName,
846+ Class<T> classType,
847+ T defaultValue,
848+ Comparable<? super T> minValue,
849+ Comparable<? super T> maxValue,
850+ boolean minInclusive,
851+ boolean maxInclusive)
852+ {
853+ Element element = getElement(elementName);
854+ ObjectValue obj = new ObjectValue();
855+ obj.valueType = VALUE_RANGE;
856+ if (minInclusive) {
857+ obj.valueType |= VALUE_RANGE_MIN_INCLUSIVE_MASK;
858+ }
859+ if (maxInclusive) {
860+ obj.valueType |= VALUE_RANGE_MAX_INCLUSIVE_MASK;
861+ }
862+ obj.classType = classType;
863+ obj.defaultValue = defaultValue;
864+ obj.minValue = minValue;
865+ obj.maxValue = maxValue;
866+
867+ element.objectValue = obj;
868+ }
869+
870+ /**
871+ * Allows an <code>Object</code> reference of a given class type
872+ * to be stored in nodes implementing the named element. The
873+ * value of the <code>Object</code> must an array of objects of
874+ * class type given by <code>classType</code>, with at least
875+ * <code>arrayMinLength</code> and at most
876+ * <code>arrayMaxLength</code> elements.
877+ *
878+ * <p> If an <code>Object</code> reference was previously allowed,
879+ * the previous settings are overwritten.
880+ *
881+ * @param elementName the name of the element.
882+ * @param classType a <code>Class</code> variable indicating the
883+ * legal class type for the object value.
884+ * @param arrayMinLength the smallest legal length for the array.
885+ * @param arrayMaxLength the largest legal length for the array.
886+ *
887+ * @exception IllegalArgumentException if <code>elementName</code> is
888+ * not a legal element name for this format.
889+ */
890+ protected void addObjectValue(String elementName,
891+ Class<?> classType,
892+ int arrayMinLength,
893+ int arrayMaxLength) {
894+ Element element = getElement(elementName);
895+ ObjectValue obj = new ObjectValue();
896+ obj.valueType = VALUE_LIST;
897+ obj.classType = classType;
898+ obj.arrayMinLength = arrayMinLength;
899+ obj.arrayMaxLength = arrayMaxLength;
900+
901+ element.objectValue = obj;
902+ }
903+
904+ /**
905+ * Disallows an <code>Object</code> reference from being stored in
906+ * nodes implementing the named element.
907+ *
908+ * @param elementName the name of the element.
909+ *
910+ * @exception IllegalArgumentException if <code>elementName</code> is
911+ * not a legal element name for this format.
912+ */
913+ protected void removeObjectValue(String elementName) {
914+ Element element = getElement(elementName);
915+ element.objectValue = null;
916+ }
917+
918+ // Utility method
919+
920+ // Methods from IIOMetadataFormat
921+
922+ // Root
923+
924+ public String getRootName() {
925+ return rootName;
926+ }
927+
928+ // Multiplicity
929+
930+ public abstract boolean canNodeAppear(String elementName,
931+ ImageTypeSpecifier imageType);
932+
933+ public int getElementMinChildren(String elementName) {
934+ Element element = getElement(elementName);
935+ if (element.childPolicy != CHILD_POLICY_REPEAT) {
936+ throw new IllegalArgumentException("Child policy not CHILD_POLICY_REPEAT!");
937+ }
938+ return element.minChildren;
939+ }
940+
941+ public int getElementMaxChildren(String elementName) {
942+ Element element = getElement(elementName);
943+ if (element.childPolicy != CHILD_POLICY_REPEAT) {
944+ throw new IllegalArgumentException("Child policy not CHILD_POLICY_REPEAT!");
945+ }
946+ return element.maxChildren;
947+ }
948+
949+ private String getResource(String key, Locale locale) {
950+ if (locale == null) {
951+ locale = Locale.getDefault();
952+ }
953+
954+ /**
955+ * If an applet supplies an implementation of IIOMetadataFormat and
956+ * resource bundles, then the resource bundle will need to be
957+ * accessed via the applet class loader. So first try the context
958+ * class loader to locate the resource bundle.
959+ * If that throws MissingResourceException, then try the
960+ * system class loader.
961+ */
962+ ClassLoader loader = (ClassLoader)
963+ java.security.AccessController.doPrivileged(
964+ new java.security.PrivilegedAction() {
965+ public Object run() {
966+ return Thread.currentThread().getContextClassLoader();
967+ }
968+ });
969+
970+ ResourceBundle bundle = null;
971+ try {
972+ bundle = ResourceBundle.getBundle(resourceBaseName,
973+ locale, loader);
974+ } catch (MissingResourceException mre) {
975+ try {
976+ bundle = ResourceBundle.getBundle(resourceBaseName, locale);
977+ } catch (MissingResourceException mre1) {
978+ return null;
979+ }
980+ }
981+
982+ try {
983+ return bundle.getString(key);
984+ } catch (MissingResourceException e) {
985+ return null;
986+ }
987+ }
988+
989+ /**
990+ * Returns a <code>String</code> containing a description of the
991+ * named element, or <code>null</code>. The desciption will be
992+ * localized for the supplied <code>Locale</code> if possible.
993+ *
994+ * <p> The default implementation will first locate a
995+ * <code>ResourceBundle</code> using the current resource base
996+ * name set by <code>setResourceBaseName</code> and the supplied
997+ * <code>Locale</code>, using the fallback mechanism described in
998+ * the comments for <code>ResourceBundle.getBundle</code>. If a
999+ * <code>ResourceBundle</code> is found, the element name will be
1000+ * used as a key to its <code>getString</code> method, and the
1001+ * result returned. If no <code>ResourceBundle</code> is found,
1002+ * or no such key is present, <code>null</code> will be returned.
1003+ *
1004+ * <p> If <code>locale</code> is <code>null</code>, the current
1005+ * default <code>Locale</code> returned by <code>Locale.getLocale</code>
1006+ * will be used.
1007+ *
1008+ * @param elementName the name of the element.
1009+ * @param locale the <code>Locale</code> for which localization
1010+ * will be attempted.
1011+ *
1012+ * @return the element description.
1013+ *
1014+ * @exception IllegalArgumentException if <code>elementName</code>
1015+ * is <code>null</code>, or is not a legal element name for this format.
1016+ *
1017+ * @see #setResourceBaseName
1018+ */
1019+ public String getElementDescription(String elementName,
1020+ Locale locale) {
1021+ Element element = getElement(elementName);
1022+ return getResource(elementName, locale);
1023+ }
1024+
1025+ // Children
1026+
1027+ public int getChildPolicy(String elementName) {
1028+ Element element = getElement(elementName);
1029+ return element.childPolicy;
1030+ }
1031+
1032+ public String[] getChildNames(String elementName) {
1033+ Element element = getElement(elementName);
1034+ if (element.childPolicy == CHILD_POLICY_EMPTY) {
1035+ return null;
1036+ }
1037+ return (String[])element.childList.toArray(new String[0]);
1038+ }
1039+
1040+ // Attributes
1041+
1042+ public String[] getAttributeNames(String elementName) {
1043+ Element element = getElement(elementName);
1044+ List names = element.attrList;
1045+
1046+ String[] result = new String[names.size()];
1047+ return (String[])names.toArray(result);
1048+ }
1049+
1050+ public int getAttributeValueType(String elementName, String attrName) {
1051+ Attribute attr = getAttribute(elementName, attrName);
1052+ return attr.valueType;
1053+ }
1054+
1055+ public int getAttributeDataType(String elementName, String attrName) {
1056+ Attribute attr = getAttribute(elementName, attrName);
1057+ return attr.dataType;
1058+ }
1059+
1060+ public boolean isAttributeRequired(String elementName, String attrName) {
1061+ Attribute attr = getAttribute(elementName, attrName);
1062+ return attr.required;
1063+ }
1064+
1065+ public String getAttributeDefaultValue(String elementName,
1066+ String attrName) {
1067+ Attribute attr = getAttribute(elementName, attrName);
1068+ return attr.defaultValue;
1069+ }
1070+
1071+ public String[] getAttributeEnumerations(String elementName,
1072+ String attrName) {
1073+ Attribute attr = getAttribute(elementName, attrName);
1074+ if (attr.valueType != VALUE_ENUMERATION) {
1075+ throw new IllegalArgumentException
1076+ ("Attribute not an enumeration!");
1077+ }
1078+
1079+ List values = attr.enumeratedValues;
1080+ Iterator iter = values.iterator();
1081+ String[] result = new String[values.size()];
1082+ return (String[])values.toArray(result);
1083+ }
1084+
1085+ public String getAttributeMinValue(String elementName, String attrName) {
1086+ Attribute attr = getAttribute(elementName, attrName);
1087+ if (attr.valueType != VALUE_RANGE &&
1088+ attr.valueType != VALUE_RANGE_MIN_INCLUSIVE &&
1089+ attr.valueType != VALUE_RANGE_MAX_INCLUSIVE &&
1090+ attr.valueType != VALUE_RANGE_MIN_MAX_INCLUSIVE) {
1091+ throw new IllegalArgumentException("Attribute not a range!");
1092+ }
1093+
1094+ return attr.minValue;
1095+ }
1096+
1097+ public String getAttributeMaxValue(String elementName, String attrName) {
1098+ Attribute attr = getAttribute(elementName, attrName);
1099+ if (attr.valueType != VALUE_RANGE &&
1100+ attr.valueType != VALUE_RANGE_MIN_INCLUSIVE &&
1101+ attr.valueType != VALUE_RANGE_MAX_INCLUSIVE &&
1102+ attr.valueType != VALUE_RANGE_MIN_MAX_INCLUSIVE) {
1103+ throw new IllegalArgumentException("Attribute not a range!");
1104+ }
1105+
1106+ return attr.maxValue;
1107+ }
1108+
1109+ public int getAttributeListMinLength(String elementName, String attrName) {
1110+ Attribute attr = getAttribute(elementName, attrName);
1111+ if (attr.valueType != VALUE_LIST) {
1112+ throw new IllegalArgumentException("Attribute not a list!");
1113+ }
1114+
1115+ return attr.listMinLength;
1116+ }
1117+
1118+ public int getAttributeListMaxLength(String elementName, String attrName) {
1119+ Attribute attr = getAttribute(elementName, attrName);
1120+ if (attr.valueType != VALUE_LIST) {
1121+ throw new IllegalArgumentException("Attribute not a list!");
1122+ }
1123+
1124+ return attr.listMaxLength;
1125+ }
1126+
1127+ /**
1128+ * Returns a <code>String</code> containing a description of the
1129+ * named attribute, or <code>null</code>. The desciption will be
1130+ * localized for the supplied <code>Locale</code> if possible.
1131+ *
1132+ * <p> The default implementation will first locate a
1133+ * <code>ResourceBundle</code> using the current resource base
1134+ * name set by <code>setResourceBaseName</code> and the supplied
1135+ * <code>Locale</code>, using the fallback mechanism described in
1136+ * the comments for <code>ResourceBundle.getBundle</code>. If a
1137+ * <code>ResourceBundle</code> is found, the element name followed
1138+ * by a "/" character followed by the attribute name
1139+ * (<code>elementName + "/" + attrName</code>) will be used as a
1140+ * key to its <code>getString</code> method, and the result
1141+ * returned. If no <code>ResourceBundle</code> is found, or no
1142+ * such key is present, <code>null</code> will be returned.
1143+ *
1144+ * <p> If <code>locale</code> is <code>null</code>, the current
1145+ * default <code>Locale</code> returned by <code>Locale.getLocale</code>
1146+ * will be used.
1147+ *
1148+ * @param elementName the name of the element.
1149+ * @param attrName the name of the attribute.
1150+ * @param locale the <code>Locale</code> for which localization
1151+ * will be attempted, or <code>null</code>.
1152+ *
1153+ * @return the attribute description.
1154+ *
1155+ * @exception IllegalArgumentException if <code>elementName</code>
1156+ * is <code>null</code>, or is not a legal element name for this format.
1157+ * @exception IllegalArgumentException if <code>attrName</code> is
1158+ * <code>null</code> or is not a legal attribute name for this
1159+ * element.
1160+ *
1161+ * @see #setResourceBaseName
1162+ */
1163+ public String getAttributeDescription(String elementName,
1164+ String attrName,
1165+ Locale locale) {
1166+ Element element = getElement(elementName);
1167+ if (attrName == null) {
1168+ throw new IllegalArgumentException("attrName == null!");
1169+ }
1170+ Attribute attr = (Attribute)element.attrMap.get(attrName);
1171+ if (attr == null) {
1172+ throw new IllegalArgumentException("No such attribute!");
1173+ }
1174+
1175+ String key = elementName + "/" + attrName;
1176+ return getResource(key, locale);
1177+ }
1178+
1179+ private ObjectValue getObjectValue(String elementName) {
1180+ Element element = getElement(elementName);
1181+ ObjectValue objv = (ObjectValue)element.objectValue;
1182+ if (objv == null) {
1183+ throw new IllegalArgumentException("No object within element " +
1184+ elementName + "!");
1185+ }
1186+ return objv;
1187+ }
1188+
1189+ public int getObjectValueType(String elementName) {
1190+ Element element = getElement(elementName);
1191+ ObjectValue objv = (ObjectValue)element.objectValue;
1192+ if (objv == null) {
1193+ return VALUE_NONE;
1194+ }
1195+ return objv.valueType;
1196+ }
1197+
1198+ public Class<?> getObjectClass(String elementName) {
1199+ ObjectValue objv = getObjectValue(elementName);
1200+ return objv.classType;
1201+ }
1202+
1203+ public Object getObjectDefaultValue(String elementName) {
1204+ ObjectValue objv = getObjectValue(elementName);
1205+ return objv.defaultValue;
1206+ }
1207+
1208+ public Object[] getObjectEnumerations(String elementName) {
1209+ ObjectValue objv = getObjectValue(elementName);
1210+ if (objv.valueType != VALUE_ENUMERATION) {
1211+ throw new IllegalArgumentException("Not an enumeration!");
1212+ }
1213+ List vlist = objv.enumeratedValues;
1214+ Object[] values = new Object[vlist.size()];
1215+ return vlist.toArray(values);
1216+ }
1217+
1218+ public Comparable<?> getObjectMinValue(String elementName) {
1219+ ObjectValue objv = getObjectValue(elementName);
1220+ if ((objv.valueType & VALUE_RANGE) != VALUE_RANGE) {
1221+ throw new IllegalArgumentException("Not a range!");
1222+ }
1223+ return objv.minValue;
1224+ }
1225+
1226+ public Comparable<?> getObjectMaxValue(String elementName) {
1227+ ObjectValue objv = getObjectValue(elementName);
1228+ if ((objv.valueType & VALUE_RANGE) != VALUE_RANGE) {
1229+ throw new IllegalArgumentException("Not a range!");
1230+ }
1231+ return objv.maxValue;
1232+ }
1233+
1234+ public int getObjectArrayMinLength(String elementName) {
1235+ ObjectValue objv = getObjectValue(elementName);
1236+ if (objv.valueType != VALUE_LIST) {
1237+ throw new IllegalArgumentException("Not a list!");
1238+ }
1239+ return objv.arrayMinLength;
1240+ }
1241+
1242+ public int getObjectArrayMaxLength(String elementName) {
1243+ ObjectValue objv = getObjectValue(elementName);
1244+ if (objv.valueType != VALUE_LIST) {
1245+ throw new IllegalArgumentException("Not a list!");
1246+ }
1247+ return objv.arrayMaxLength;
1248+ }
1249+
1250+ // Standard format descriptor
1251+
1252+ private synchronized static void createStandardFormat() {
1253+ if (standardFormat == null) {
1254+ standardFormat = new StandardMetadataFormat();
1255+ }
1256+ }
1257+
1258+ /**
1259+ * Returns an <code>IIOMetadataFormat</code> object describing the
1260+ * standard, plug-in neutral <code>javax.imageio_1.0</code>
1261+ * metadata document format described in the comment of the
1262+ * <code>javax.imageio.metadata</code> package.
1263+ *
1264+ * @return a predefined <code>IIOMetadataFormat</code> instance.
1265+ */
1266+ public static IIOMetadataFormat getStandardFormatInstance() {
1267+ createStandardFormat();
1268+ return standardFormat;
1269+ }
1270+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t