001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.imageio.metadata;
019:
020: import javax.imageio.ImageTypeSpecifier;
021: import java.util.*;
022: import java.security.AccessController;
023: import java.security.PrivilegedAction;
024:
025: public abstract class IIOMetadataFormatImpl implements
026: IIOMetadataFormat {
027: @SuppressWarnings({"ConstantDeclaredInAbstractClass"})
028: public static final String standardMetadataFormatName = "javax_imageio_1.0";
029:
030: @SuppressWarnings({"StaticNonFinalField"})
031: private static IIOMetadataFormatImpl standardFormat;
032:
033: private String rootName;
034: private HashMap<String, Element> elementHash = new HashMap<String, Element>();
035:
036: private String resourceBaseName = getClass().getName()
037: + "Resources";
038:
039: public IIOMetadataFormatImpl(String rootName, int childPolicy) {
040: if (rootName == null) {
041: throw new IllegalArgumentException("rootName is null");
042: }
043: if (childPolicy < CHILD_POLICY_EMPTY
044: || childPolicy > CHILD_POLICY_MAX
045: || childPolicy == CHILD_POLICY_REPEAT) {
046: throw new IllegalArgumentException(
047: "childPolicy is not one of the predefined constants");
048: }
049:
050: this .rootName = rootName;
051: Element root = new Element();
052: root.name = rootName;
053: root.childPolicy = childPolicy;
054: elementHash.put(rootName, root);
055: }
056:
057: public IIOMetadataFormatImpl(String rootName, int minChildren,
058: int maxChildren) {
059: if (rootName == null) {
060: throw new IllegalArgumentException("rootName is null");
061: }
062: if (minChildren < 0) {
063: throw new IllegalArgumentException("minChildren < 0!");
064: }
065: if (minChildren > maxChildren) {
066: throw new IllegalArgumentException(
067: "minChildren > maxChildren!");
068: }
069:
070: this .rootName = rootName;
071: Element root = new Element();
072: root.name = rootName;
073: root.minChildren = minChildren;
074: root.maxChildren = maxChildren;
075: root.childPolicy = CHILD_POLICY_REPEAT;
076: elementHash.put(rootName, root);
077: }
078:
079: @SuppressWarnings({"AbstractMethodOverridesAbstractMethod"})
080: public abstract boolean canNodeAppear(String elementName,
081: ImageTypeSpecifier imageType);
082:
083: protected void addAttribute(String elementName, String attrName,
084: int dataType, boolean required, int listMinLength,
085: int listMaxLength) {
086: if (attrName == null) {
087: throw new IllegalArgumentException("attrName == null!");
088: }
089: if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
090: throw new IllegalArgumentException(
091: "Invalid value for dataType!");
092: }
093: if (listMinLength < 0 || listMinLength > listMaxLength) {
094: throw new IllegalArgumentException("Invalid list bounds!");
095: }
096:
097: Element element = findElement(elementName);
098: Attlist attr = new Attlist();
099: attr.name = attrName;
100: attr.dataType = dataType;
101: attr.required = required;
102: attr.listMinLength = listMinLength;
103: attr.listMaxLength = listMaxLength;
104: attr.valueType = VALUE_LIST;
105:
106: element.attributes.put(attrName, attr);
107: }
108:
109: protected void addAttribute(String elementName, String attrName,
110: int dataType, boolean required, String defaultValue) {
111: if (attrName == null) {
112: throw new IllegalArgumentException("attrName == null!");
113: }
114: if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
115: throw new IllegalArgumentException(
116: "Invalid value for dataType!");
117: }
118:
119: Element element = findElement(elementName);
120: Attlist attr = new Attlist();
121: attr.name = attrName;
122: attr.dataType = dataType;
123: attr.required = required;
124: attr.defaultValue = defaultValue;
125: attr.valueType = VALUE_ARBITRARY;
126:
127: element.attributes.put(attrName, attr);
128: }
129:
130: protected void addAttribute(String elementName, String attrName,
131: int dataType, boolean required, String defaultValue,
132: List<String> enumeratedValues) {
133: if (attrName == null) {
134: throw new IllegalArgumentException("attrName == null!");
135: }
136: if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
137: throw new IllegalArgumentException(
138: "Invalid value for dataType!");
139: }
140: if (enumeratedValues == null || enumeratedValues.isEmpty()) {
141: throw new IllegalArgumentException(
142: "enumeratedValues is empty or null");
143: }
144:
145: try {
146: for (String enumeratedValue : enumeratedValues) {
147: if (enumeratedValue == null) {
148: throw new IllegalArgumentException(
149: "enumeratedValues contains a null!");
150: }
151: }
152: } catch (ClassCastException e) {
153: throw new IllegalArgumentException(
154: "enumeratedValues contains a non-String value!");
155: }
156:
157: Element element = findElement(elementName);
158: Attlist attr = new Attlist();
159: attr.name = attrName;
160: attr.dataType = dataType;
161: attr.required = required;
162: attr.defaultValue = defaultValue;
163: attr.enumeratedValues = enumeratedValues;
164: attr.valueType = VALUE_ENUMERATION;
165:
166: element.attributes.put(attrName, attr);
167: }
168:
169: protected void addAttribute(String elementName, String attrName,
170: int dataType, boolean required, String defaultValue,
171: String minValue, String maxValue, boolean minInclusive,
172: boolean maxInclusive) {
173: if (attrName == null) {
174: throw new IllegalArgumentException("attrName == null!");
175: }
176: if (dataType < DATATYPE_STRING || dataType > DATATYPE_DOUBLE) {
177: throw new IllegalArgumentException(
178: "Invalid value for dataType!");
179: }
180:
181: Element element = findElement(elementName);
182: Attlist attr = new Attlist();
183: attr.name = attrName;
184: attr.dataType = dataType;
185: attr.required = required;
186: attr.defaultValue = defaultValue;
187: attr.minValue = minValue;
188: attr.maxValue = maxValue;
189: attr.minInclusive = minInclusive;
190: attr.maxInclusive = maxInclusive;
191:
192: attr.valueType = VALUE_RANGE;
193: attr.valueType |= minInclusive ? VALUE_RANGE_MIN_INCLUSIVE_MASK
194: : 0;
195: attr.valueType |= maxInclusive ? VALUE_RANGE_MAX_INCLUSIVE_MASK
196: : 0;
197:
198: element.attributes.put(attrName, attr);
199: }
200:
201: protected void addBooleanAttribute(String elementName,
202: String attrName, boolean hasDefaultValue,
203: boolean defaultValue) {
204: String defaultVal = hasDefaultValue ? (defaultValue ? "TRUE"
205: : "FALSE") : null;
206: ArrayList<String> values = new ArrayList<String>(2);
207: values.add("TRUE");
208: values.add("FALSE");
209:
210: addAttribute(elementName, attrName, DATATYPE_BOOLEAN, true,
211: defaultVal, values);
212: }
213:
214: protected void addChildElement(String elementName, String parentName) {
215: Element parent = findElement(parentName);
216: Element element = findElement(elementName);
217: parent.children.add(element.name);
218: }
219:
220: protected void addElement(String elementName, String parentName,
221: int childPolicy) {
222: if (childPolicy < CHILD_POLICY_EMPTY
223: || childPolicy > CHILD_POLICY_MAX
224: || childPolicy == CHILD_POLICY_REPEAT) {
225: throw new IllegalArgumentException(
226: "childPolicy is not one of the predefined constants");
227: }
228:
229: Element parent = findElement(parentName);
230: Element element = new Element();
231: element.name = elementName;
232: element.childPolicy = childPolicy;
233: elementHash.put(elementName, element);
234: parent.children.add(elementName);
235: }
236:
237: protected void addElement(String elementName, String parentName,
238: int minChildren, int maxChildren) {
239: if (minChildren < 0) {
240: throw new IllegalArgumentException("minChildren < 0!");
241: }
242: if (minChildren > maxChildren) {
243: throw new IllegalArgumentException(
244: "minChildren > maxChildren!");
245: }
246:
247: Element parent = findElement(parentName);
248: Element element = new Element();
249: element.name = elementName;
250: element.childPolicy = CHILD_POLICY_REPEAT;
251: element.minChildren = minChildren;
252: element.maxChildren = maxChildren;
253: elementHash.put(elementName, element);
254: parent.children.add(elementName);
255: }
256:
257: protected void addObjectValue(String elementName,
258: Class<?> classType, int arrayMinLength, int arrayMaxLength) {
259: Element element = findElement(elementName);
260:
261: ObjectValue objVal = new ObjectValue();
262: objVal.classType = classType;
263: objVal.arrayMaxLength = arrayMaxLength;
264: objVal.arrayMinLength = arrayMinLength;
265: objVal.valueType = VALUE_LIST;
266:
267: element.objectValue = objVal;
268: }
269:
270: protected <T> void addObjectValue(String elementName,
271: Class<T> classType, boolean required, T defaultValue) {
272: // note: reqired is an unused parameter
273: Element element = findElement(elementName);
274:
275: ObjectValue<T> objVal = new ObjectValue<T>();
276: objVal.classType = classType;
277: objVal.defaultValue = defaultValue;
278: objVal.valueType = VALUE_ARBITRARY;
279:
280: element.objectValue = objVal;
281: }
282:
283: protected <T> void addObjectValue(String elementName,
284: Class<T> classType, boolean required, T defaultValue,
285: List<? extends T> enumeratedValues) {
286: // note: reqired is an unused parameter
287: if (enumeratedValues == null || enumeratedValues.isEmpty()) {
288: throw new IllegalArgumentException(
289: "enumeratedValues is empty or null");
290: }
291:
292: try {
293: for (T enumeratedValue : enumeratedValues) {
294: if (enumeratedValue == null) {
295: throw new IllegalArgumentException(
296: "enumeratedValues contains a null!");
297: }
298: }
299: } catch (ClassCastException e) {
300: throw new IllegalArgumentException(
301: "enumeratedValues contains a value not of class classType!");
302: }
303:
304: Element element = findElement(elementName);
305:
306: ObjectValue<T> objVal = new ObjectValue<T>();
307: objVal.classType = classType;
308: objVal.defaultValue = defaultValue;
309: objVal.enumeratedValues = enumeratedValues;
310: objVal.valueType = VALUE_ENUMERATION;
311:
312: element.objectValue = objVal;
313: }
314:
315: protected <T extends Object & Comparable<? super T>> void addObjectValue(
316: String elementName, Class<T> classType, T defaultValue,
317: Comparable<? super T> minValue,
318: Comparable<? super T> maxValue, boolean minInclusive,
319: boolean maxInclusive) {
320: Element element = findElement(elementName);
321:
322: ObjectValue<T> objVal = new ObjectValue<T>();
323: objVal.classType = classType;
324: objVal.defaultValue = defaultValue;
325: objVal.minValue = minValue;
326: objVal.maxValue = maxValue;
327: objVal.minInclusive = minInclusive;
328: objVal.maxInclusive = maxInclusive;
329:
330: objVal.valueType = VALUE_RANGE;
331: objVal.valueType |= minInclusive ? VALUE_RANGE_MIN_INCLUSIVE_MASK
332: : 0;
333: objVal.valueType |= maxInclusive ? VALUE_RANGE_MAX_INCLUSIVE_MASK
334: : 0;
335:
336: element.objectValue = objVal;
337: }
338:
339: public int getAttributeDataType(String elementName, String attrName) {
340: Attlist attr = findAttribute(elementName, attrName);
341: return attr.dataType;
342: }
343:
344: public String getAttributeDefaultValue(String elementName,
345: String attrName) {
346: Attlist attr = findAttribute(elementName, attrName);
347: return attr.defaultValue;
348: }
349:
350: public String getAttributeDescription(String elementName,
351: String attrName, Locale locale) {
352: findAttribute(elementName, attrName);
353: return getResourceString(elementName + "/" + attrName, locale);
354: }
355:
356: public String[] getAttributeEnumerations(String elementName,
357: String attrName) {
358: Attlist attr = findAttribute(elementName, attrName);
359: if (attr.valueType != VALUE_ENUMERATION) {
360: throw new IllegalArgumentException(
361: "Attribute is not an enumeration!");
362: }
363:
364: return attr.enumeratedValues
365: .toArray(new String[attr.enumeratedValues.size()]);
366: }
367:
368: public int getAttributeListMaxLength(String elementName,
369: String attrName) {
370: Attlist attr = findAttribute(elementName, attrName);
371: if (attr.valueType != VALUE_LIST) {
372: throw new IllegalArgumentException(
373: "Attribute is not a list!");
374: }
375: return attr.listMaxLength;
376: }
377:
378: public int getAttributeListMinLength(String elementName,
379: String attrName) {
380: Attlist attr = findAttribute(elementName, attrName);
381: if (attr.valueType != VALUE_LIST) {
382: throw new IllegalArgumentException(
383: "Attribute is not a list!");
384: }
385: return attr.listMinLength;
386: }
387:
388: public String getAttributeMaxValue(String elementName,
389: String attrName) {
390: Attlist attr = findAttribute(elementName, attrName);
391: if ((attr.valueType & VALUE_RANGE) == 0) {
392: throw new IllegalArgumentException(
393: "Attribute is not a range!");
394: }
395: return attr.maxValue;
396: }
397:
398: public String getAttributeMinValue(String elementName,
399: String attrName) {
400: Attlist attr = findAttribute(elementName, attrName);
401: if ((attr.valueType & VALUE_RANGE) == 0) {
402: throw new IllegalArgumentException(
403: "Attribute is not a range!");
404: }
405: return attr.minValue;
406: }
407:
408: public String[] getAttributeNames(String elementName) {
409: Element element = findElement(elementName);
410: return element.attributes.keySet().toArray(
411: new String[element.attributes.size()]);
412: }
413:
414: public int getAttributeValueType(String elementName, String attrName) {
415: Attlist attr = findAttribute(elementName, attrName);
416: return attr.valueType;
417: }
418:
419: public String[] getChildNames(String elementName) {
420: Element element = findElement(elementName);
421: if (element.childPolicy == CHILD_POLICY_EMPTY) { // Element cannot have children
422: return null;
423: }
424: return element.children.toArray(new String[element.children
425: .size()]);
426: }
427:
428: public int getChildPolicy(String elementName) {
429: Element element = findElement(elementName);
430: return element.childPolicy;
431: }
432:
433: public String getElementDescription(String elementName,
434: Locale locale) {
435: findElement(elementName); // Check if there is such element
436: return getResourceString(elementName, locale);
437: }
438:
439: public int getElementMaxChildren(String elementName) {
440: Element element = findElement(elementName);
441: if (element.childPolicy != CHILD_POLICY_REPEAT) {
442: throw new IllegalArgumentException(
443: "Child policy is not CHILD_POLICY_REPEAT!");
444: }
445: return element.maxChildren;
446: }
447:
448: public int getElementMinChildren(String elementName) {
449: Element element = findElement(elementName);
450: if (element.childPolicy != CHILD_POLICY_REPEAT) {
451: throw new IllegalArgumentException(
452: "Child policy is not CHILD_POLICY_REPEAT!");
453: }
454: return element.minChildren;
455: }
456:
457: public int getObjectArrayMaxLength(String elementName) {
458: Element element = findElement(elementName);
459: ObjectValue v = element.objectValue;
460: if (v == null || v.valueType != VALUE_LIST) {
461: throw new IllegalArgumentException("Not a list!");
462: }
463: return v.arrayMaxLength;
464: }
465:
466: public int getObjectArrayMinLength(String elementName) {
467: Element element = findElement(elementName);
468: ObjectValue v = element.objectValue;
469: if (v == null || v.valueType != VALUE_LIST) {
470: throw new IllegalArgumentException("Not a list!");
471: }
472: return v.arrayMinLength;
473: }
474:
475: public Class<?> getObjectClass(String elementName) {
476: ObjectValue v = findObjectValue(elementName);
477: return v.classType;
478: }
479:
480: public Object getObjectDefaultValue(String elementName) {
481: ObjectValue v = findObjectValue(elementName);
482: return v.defaultValue;
483: }
484:
485: public Object[] getObjectEnumerations(String elementName) {
486: Element element = findElement(elementName);
487: ObjectValue v = element.objectValue;
488: if (v == null || v.valueType != VALUE_ENUMERATION) {
489: throw new IllegalArgumentException("Not an enumeration!");
490: }
491: return v.enumeratedValues.toArray();
492: }
493:
494: public Comparable<?> getObjectMaxValue(String elementName) {
495: Element element = findElement(elementName);
496: ObjectValue v = element.objectValue;
497: if (v == null || (v.valueType & VALUE_RANGE) == 0) {
498: throw new IllegalArgumentException("Not a range!");
499: }
500: return v.maxValue;
501: }
502:
503: public Comparable<?> getObjectMinValue(String elementName) {
504: Element element = findElement(elementName);
505: ObjectValue v = element.objectValue;
506: if (v == null || (v.valueType & VALUE_RANGE) == 0) {
507: throw new IllegalArgumentException("Not a range!");
508: }
509: return v.minValue;
510: }
511:
512: public int getObjectValueType(String elementName) {
513: Element element = findElement(elementName);
514: if (element.objectValue == null) {
515: return VALUE_NONE;
516: }
517: return element.objectValue.valueType;
518: }
519:
520: protected String getResourceBaseName() {
521: return resourceBaseName;
522: }
523:
524: public String getRootName() {
525: return rootName;
526: }
527:
528: public static IIOMetadataFormat getStandardFormatInstance() {
529: if (standardFormat == null) {
530: standardFormat = new IIOStandardMetadataFormat();
531: }
532:
533: return standardFormat;
534: }
535:
536: public boolean isAttributeRequired(String elementName,
537: String attrName) {
538: return findAttribute(elementName, attrName).required;
539: }
540:
541: protected void removeAttribute(String elementName, String attrName) {
542: Element element = findElement(elementName);
543: element.attributes.remove(attrName);
544: }
545:
546: protected void removeElement(String elementName) {
547: Element element;
548: if ((element = elementHash.get(elementName)) != null) {
549: elementHash.remove(elementName);
550: for (Element e : elementHash.values()) {
551: e.children.remove(element.name);
552: }
553: }
554: }
555:
556: protected void removeObjectValue(String elementName) {
557: Element element = findElement(elementName);
558: element.objectValue = null;
559: }
560:
561: protected void setResourceBaseName(String resourceBaseName) {
562: if (resourceBaseName == null) {
563: throw new IllegalArgumentException(
564: "resourceBaseName == null!");
565: }
566: this .resourceBaseName = resourceBaseName;
567: }
568:
569: @SuppressWarnings({"ClassWithoutConstructor"})
570: private class Element {
571: String name;
572:
573: ArrayList<String> children = new ArrayList<String>();
574: HashMap<String, Attlist> attributes = new HashMap<String, Attlist>();
575:
576: int minChildren;
577: int maxChildren;
578: int childPolicy;
579:
580: ObjectValue objectValue;
581: }
582:
583: @SuppressWarnings({"ClassWithoutConstructor"})
584: private class Attlist {
585: String name;
586:
587: int dataType;
588: boolean required;
589: int listMinLength;
590: int listMaxLength;
591: String defaultValue;
592: List<String> enumeratedValues;
593: String minValue;
594: String maxValue;
595: boolean minInclusive;
596: boolean maxInclusive;
597:
598: int valueType;
599: }
600:
601: @SuppressWarnings({"ClassWithoutConstructor"})
602: private class ObjectValue<T> {
603: Class<T> classType;
604: int arrayMinLength;
605: int arrayMaxLength;
606: T defaultValue;
607: List<? extends T> enumeratedValues;
608: Comparable<? super T> minValue;
609: Comparable<? super T> maxValue;
610: boolean minInclusive;
611: boolean maxInclusive;
612:
613: int valueType;
614: }
615:
616: private Element findElement(String name) {
617: Element element;
618: if ((element = elementHash.get(name)) == null) {
619: throw new IllegalArgumentException(
620: "element name is null or no such element: " + name);
621: }
622:
623: return element;
624: }
625:
626: private Attlist findAttribute(String elementName,
627: String attributeName) {
628: Element element = findElement(elementName);
629: Attlist attribute;
630: if ((attribute = element.attributes.get(attributeName)) == null) {
631: throw new IllegalArgumentException(
632: "attribute name is null or no such attribute: "
633: + attributeName);
634: }
635:
636: return attribute;
637: }
638:
639: private ObjectValue findObjectValue(String elementName) {
640: Element element = findElement(elementName);
641: ObjectValue v = element.objectValue;
642: if (v == null) {
643: throw new IllegalArgumentException(
644: "No object within element");
645: }
646: return v;
647: }
648:
649: private String getResourceString(String key, Locale locale) {
650: if (locale == null) {
651: locale = Locale.getDefault();
652: }
653:
654: // Get the context class loader and try to locate the bundle with it first
655: ClassLoader contextClassloader = AccessController
656: .doPrivileged(new PrivilegedAction<ClassLoader>() {
657: public ClassLoader run() {
658: return Thread.currentThread()
659: .getContextClassLoader();
660: }
661: });
662:
663: // Now try to get the resource bundle
664: ResourceBundle rb;
665: try {
666: rb = ResourceBundle.getBundle(resourceBaseName, locale,
667: contextClassloader);
668: } catch (MissingResourceException e) {
669: try {
670: rb = ResourceBundle.getBundle(resourceBaseName, locale);
671: } catch (MissingResourceException e1) {
672: return null;
673: }
674: }
675:
676: try {
677: return rb.getString(key);
678: } catch (MissingResourceException e) {
679: return null;
680: } catch (ClassCastException e) {
681: return null; // Not a string resource
682: }
683: }
684: }
|