3789983e89
Reviewed-by: darcy, ihse
506 lines
17 KiB
Java
506 lines
17 KiB
Java
/*
|
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
//
|
|
|
|
import java.io.PrintStream;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.StringTokenizer;
|
|
import javax.imageio.metadata.IIOMetadata;
|
|
import javax.imageio.metadata.IIOMetadataFormat;
|
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
import javax.imageio.spi.IIORegistry;
|
|
import javax.imageio.spi.ImageReaderSpi;
|
|
import com.sun.imageio.plugins.png.PNGMetadata;
|
|
|
|
public class MetadataFormatPrinter {
|
|
|
|
private int indentLevel = 0;
|
|
|
|
private int column = 0;
|
|
|
|
private PrintStream out;
|
|
|
|
private static final int maxColumn = 75;
|
|
|
|
private static String[] dataTypeNames = {
|
|
"String", "Boolean", "Integer", "Float", "Double"
|
|
};
|
|
|
|
// "Infinite" values
|
|
private static String maxInteger = Integer.toString(Integer.MAX_VALUE);
|
|
|
|
public MetadataFormatPrinter(PrintStream out) {
|
|
this.out = out;
|
|
}
|
|
|
|
private void println() {
|
|
out.println();
|
|
column = 0;
|
|
}
|
|
|
|
private void println(String s) {
|
|
out.println(s);
|
|
column = 0;
|
|
}
|
|
|
|
private void printWrapped(String in, int leftIndent) {
|
|
StringTokenizer t = new StringTokenizer(in);
|
|
while (t.hasMoreTokens()) {
|
|
String s = t.nextToken();
|
|
int length = s.length();
|
|
if (column + length > maxColumn) {
|
|
println();
|
|
indent();
|
|
for (int i = 0; i < leftIndent; i++) {
|
|
print(" ");
|
|
}
|
|
}
|
|
out.print(s);
|
|
out.print(" ");
|
|
column += length + 1;
|
|
}
|
|
}
|
|
|
|
private void print(String s) {
|
|
int length = s.length();
|
|
if (column + length > maxColumn) {
|
|
println();
|
|
indent();
|
|
print(" ");
|
|
}
|
|
out.print(s);
|
|
column += length;
|
|
}
|
|
|
|
private void print(IIOMetadataFormat format) {
|
|
String rootName = format.getRootName();
|
|
println("<!DOCTYPE \"" +
|
|
rootName +
|
|
"\" [");
|
|
++indentLevel;
|
|
print(format, rootName);
|
|
--indentLevel;
|
|
print("]>");
|
|
println();
|
|
println();
|
|
}
|
|
|
|
private void indent() {
|
|
for (int i = 0; i < indentLevel; i++) {
|
|
out.print(" ");
|
|
column += 2;
|
|
}
|
|
}
|
|
|
|
private void printElementInfo(IIOMetadataFormat format,
|
|
String elementName) {
|
|
println();
|
|
indent();
|
|
print("<!ELEMENT \"" +
|
|
elementName +
|
|
"\"");
|
|
|
|
String[] childNames = format.getChildNames(elementName);
|
|
boolean hasChildren = true;
|
|
String separator = " "; // symbol to place between children
|
|
String terminator = ""; // symbol to follow last child
|
|
String repeater = ""; // "*" if repeating
|
|
|
|
switch (format.getChildPolicy(elementName)) {
|
|
case IIOMetadataFormat.CHILD_POLICY_EMPTY:
|
|
hasChildren = false;
|
|
break;
|
|
case IIOMetadataFormat.CHILD_POLICY_ALL:
|
|
separator = ", ";
|
|
break;
|
|
case IIOMetadataFormat.CHILD_POLICY_SOME:
|
|
separator = "?, ";
|
|
terminator = "?";
|
|
break;
|
|
case IIOMetadataFormat.CHILD_POLICY_CHOICE:
|
|
separator = " | ";
|
|
break;
|
|
case IIOMetadataFormat.CHILD_POLICY_SEQUENCE:
|
|
separator = " | ";
|
|
repeater = "*";
|
|
break;
|
|
case IIOMetadataFormat.CHILD_POLICY_REPEAT:
|
|
repeater = "*";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (hasChildren) {
|
|
print(" (");
|
|
for (int i = 0; i < childNames.length - 1; i++) {
|
|
print(childNames[i] + separator);
|
|
}
|
|
print(childNames[childNames.length - 1] + terminator);
|
|
print(")" + repeater + ">");
|
|
} else {
|
|
print(" EMPTY>");
|
|
}
|
|
println();
|
|
|
|
String description = format.getElementDescription(elementName, null);
|
|
if (description != null) {
|
|
++indentLevel;
|
|
indent();
|
|
printWrapped("<!-- " + description + " -->", 5);
|
|
println();
|
|
--indentLevel;
|
|
}
|
|
if (format.getChildPolicy(elementName) ==
|
|
IIOMetadataFormat.CHILD_POLICY_REPEAT) {
|
|
int minChildren = format.getElementMinChildren(elementName);
|
|
if (minChildren != 0) {
|
|
indent();
|
|
println(" <!-- Min children: " +
|
|
minChildren +
|
|
" -->");
|
|
}
|
|
int maxChildren = format.getElementMaxChildren(elementName);
|
|
if (maxChildren != Integer.MAX_VALUE) {
|
|
indent();
|
|
println(" <!-- Max children: " +
|
|
maxChildren +
|
|
" -->");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void printAttributeInfo(IIOMetadataFormat format,
|
|
String elementName,
|
|
String attrName) {
|
|
indent();
|
|
print("<!ATTLIST \"" +
|
|
elementName +
|
|
"\" \"" +
|
|
attrName +
|
|
"\"");
|
|
|
|
int attrValueType =
|
|
format.getAttributeValueType(elementName, attrName);
|
|
switch (attrValueType) {
|
|
case IIOMetadataFormat.VALUE_NONE:
|
|
throw new RuntimeException
|
|
("Encountered VALUE_NONE for an attribute!");
|
|
// break;
|
|
case IIOMetadataFormat.VALUE_ARBITRARY:
|
|
print(" #CDATA");
|
|
break;
|
|
case IIOMetadataFormat.VALUE_RANGE:
|
|
case IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE:
|
|
case IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE:
|
|
case IIOMetadataFormat.VALUE_RANGE_MIN_MAX_INCLUSIVE:
|
|
print(" #CDATA");
|
|
break;
|
|
case IIOMetadataFormat.VALUE_ENUMERATION:
|
|
print(" (");
|
|
String[] attrValues =
|
|
format.getAttributeEnumerations(elementName, attrName);
|
|
for (int j = 0; j < attrValues.length - 1; j++) {
|
|
print("\"" + attrValues[j] + "\" | ");
|
|
}
|
|
print("\"" + attrValues[attrValues.length - 1] + "\")");
|
|
break;
|
|
case IIOMetadataFormat.VALUE_LIST:
|
|
print(" #CDATA");
|
|
break;
|
|
default:
|
|
throw new RuntimeException
|
|
("Encountered unknown value type for an attribute!");
|
|
// break;
|
|
}
|
|
|
|
String defaultValue =
|
|
format.getAttributeDefaultValue(elementName, attrName);
|
|
if (defaultValue != null) {
|
|
print(" ");
|
|
print("\"" + defaultValue + "\"");
|
|
} else {
|
|
if (format.isAttributeRequired(elementName, attrName)) {
|
|
print(" #REQUIRED");
|
|
} else {
|
|
print(" #IMPLIED");
|
|
}
|
|
}
|
|
println(">");
|
|
|
|
String description = format.getAttributeDescription(elementName,
|
|
attrName,
|
|
null);
|
|
if (description != null) {
|
|
++indentLevel;
|
|
indent();
|
|
printWrapped("<!-- " + description + " -->", 5);
|
|
println();
|
|
--indentLevel;
|
|
}
|
|
|
|
int dataType = format.getAttributeDataType(elementName, attrName);
|
|
|
|
switch (attrValueType) {
|
|
case IIOMetadataFormat.VALUE_ARBITRARY:
|
|
indent();
|
|
println(" <!-- Data type: " + dataTypeNames[dataType] + " -->");
|
|
break;
|
|
|
|
case IIOMetadataFormat.VALUE_RANGE:
|
|
case IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE:
|
|
case IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE:
|
|
case IIOMetadataFormat.VALUE_RANGE_MIN_MAX_INCLUSIVE:
|
|
indent();
|
|
println(" <!-- Data type: " + dataTypeNames[dataType] + " -->");
|
|
|
|
boolean minInclusive =
|
|
(attrValueType &
|
|
IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE_MASK) != 0;
|
|
boolean maxInclusive =
|
|
(attrValueType &
|
|
IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE_MASK) != 0;
|
|
indent();
|
|
println(" <!-- Min value: " +
|
|
format.getAttributeMinValue(elementName, attrName) +
|
|
" " +
|
|
(minInclusive ? "(inclusive)" : "(exclusive)") +
|
|
" -->");
|
|
String maxValue =
|
|
format.getAttributeMaxValue(elementName, attrName);
|
|
// Hack: don't print "infinite" max values
|
|
if (dataType != IIOMetadataFormat.DATATYPE_INTEGER ||
|
|
!maxValue.equals(maxInteger)) {
|
|
indent();
|
|
println(" <!-- Max value: " +
|
|
maxValue +
|
|
" " +
|
|
(maxInclusive ? "(inclusive)" : "(exclusive)") +
|
|
" -->");
|
|
}
|
|
break;
|
|
|
|
case IIOMetadataFormat.VALUE_LIST:
|
|
indent();
|
|
println(" <!-- Data type: List of " + dataTypeNames[dataType] + " -->");
|
|
|
|
int minLength =
|
|
format.getAttributeListMinLength(elementName, attrName);
|
|
if (minLength != 0) {
|
|
indent();
|
|
println(" <!-- Min length: " +
|
|
minLength +
|
|
" -->");
|
|
}
|
|
int maxLength =
|
|
format.getAttributeListMaxLength(elementName, attrName);
|
|
if (maxLength != Integer.MAX_VALUE) {
|
|
indent();
|
|
println(" <!-- Max length: " +
|
|
maxLength +
|
|
" -->");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void printObjectInfo(IIOMetadataFormat format,
|
|
String elementName) {
|
|
int objectType = format.getObjectValueType(elementName);
|
|
if (objectType == IIOMetadataFormat.VALUE_NONE) {
|
|
return;
|
|
}
|
|
|
|
Class objectClass = format.getObjectClass(elementName);
|
|
if (objectClass != null) {
|
|
indent();
|
|
if (objectType == IIOMetadataFormat.VALUE_LIST) {
|
|
println(" <!-- User object: array of " +
|
|
objectClass.getName() +
|
|
" -->");
|
|
} else {
|
|
println(" <!-- User object: " +
|
|
objectClass.getName() +
|
|
" -->");
|
|
}
|
|
|
|
Object defaultValue = format.getObjectDefaultValue(elementName);
|
|
if (defaultValue != null) {
|
|
indent();
|
|
println(" <!-- Default value: " +
|
|
defaultValue.toString() +
|
|
" -->");
|
|
}
|
|
|
|
switch (objectType) {
|
|
case IIOMetadataFormat.VALUE_RANGE:
|
|
indent();
|
|
println(" <!-- Min value: " +
|
|
format.getObjectMinValue(elementName).toString() +
|
|
" -->");
|
|
indent();
|
|
println(" <!-- Max value: " +
|
|
format.getObjectMaxValue(elementName).toString() +
|
|
" -->");
|
|
break;
|
|
|
|
case IIOMetadataFormat.VALUE_ENUMERATION:
|
|
Object[] enums = format.getObjectEnumerations(elementName);
|
|
for (int i = 0; i < enums.length; i++) {
|
|
indent();
|
|
println(" <!-- Enumerated value: " +
|
|
enums[i].toString() +
|
|
" -->");
|
|
}
|
|
break;
|
|
|
|
case IIOMetadataFormat.VALUE_LIST:
|
|
int minLength = format.getObjectArrayMinLength(elementName);
|
|
if (minLength != 0) {
|
|
indent();
|
|
println(" <!-- Min length: " +
|
|
minLength +
|
|
" -->");
|
|
}
|
|
int maxLength = format.getObjectArrayMaxLength(elementName);
|
|
if (maxLength != Integer.MAX_VALUE) {
|
|
indent();
|
|
println(" <!-- Max length: " +
|
|
maxLength +
|
|
" -->");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set of elements that have been printed already
|
|
Set printedElements = new HashSet();
|
|
|
|
// Set of elements that have been scheduled to be printed
|
|
Set scheduledElements = new HashSet();
|
|
|
|
private void print(IIOMetadataFormat format,
|
|
String elementName) {
|
|
// Don't print elements more than once
|
|
if (printedElements.contains(elementName)) {
|
|
return;
|
|
}
|
|
printedElements.add(elementName);
|
|
|
|
// Add the unscheduled children of this node to a list,
|
|
// and mark them as scheduled
|
|
List children = new ArrayList();
|
|
String[] childNames = format.getChildNames(elementName);
|
|
if (childNames != null) {
|
|
for (int i = 0; i < childNames.length; i++) {
|
|
String childName = childNames[i];
|
|
if (!scheduledElements.contains(childName)) {
|
|
children.add(childName);
|
|
scheduledElements.add(childName);
|
|
}
|
|
}
|
|
}
|
|
|
|
printElementInfo(format, elementName);
|
|
printObjectInfo(format, elementName);
|
|
|
|
++indentLevel;
|
|
String[] attrNames = format.getAttributeNames(elementName);
|
|
for (int i = 0; i < attrNames.length; i++) {
|
|
printAttributeInfo(format, elementName, attrNames[i]);
|
|
}
|
|
|
|
// Recurse on child nodes
|
|
Iterator iter = children.iterator();
|
|
while (iter.hasNext()) {
|
|
print(format, (String)iter.next());
|
|
}
|
|
--indentLevel;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
IIOMetadataFormat format = null;
|
|
if (args.length == 0 || args[0].equals("javax_imageio_1.0")) {
|
|
format = IIOMetadataFormatImpl.getStandardFormatInstance();
|
|
} else {
|
|
IIORegistry registry = IIORegistry.getDefaultInstance();
|
|
Iterator iter = registry.getServiceProviders(ImageReaderSpi.class,
|
|
false);
|
|
while (iter.hasNext()) {
|
|
ImageReaderSpi spi = (ImageReaderSpi)iter.next();
|
|
if (args[0].equals
|
|
(spi.getNativeStreamMetadataFormatName())) {
|
|
System.out.print(spi.getDescription(null));
|
|
System.out.println(": native stream format");
|
|
format = spi.getStreamMetadataFormat(args[0]);
|
|
break;
|
|
}
|
|
|
|
String[] extraStreamFormatNames =
|
|
spi.getExtraStreamMetadataFormatNames();
|
|
if (extraStreamFormatNames != null &&
|
|
Arrays.asList(extraStreamFormatNames).
|
|
contains(args[0])) {
|
|
System.out.print(spi.getDescription(null));
|
|
System.out.println(": extra stream format");
|
|
format = spi.getStreamMetadataFormat(args[0]);
|
|
break;
|
|
}
|
|
|
|
if (args[0].equals
|
|
(spi.getNativeImageMetadataFormatName())) {
|
|
System.out.print(spi.getDescription(null));
|
|
System.out.println(": native image format");
|
|
format = spi.getImageMetadataFormat(args[0]);
|
|
break;
|
|
}
|
|
|
|
String[] extraImageFormatNames =
|
|
spi.getExtraImageMetadataFormatNames();
|
|
if (extraImageFormatNames != null &&
|
|
Arrays.asList(extraImageFormatNames).contains(args[0])) {
|
|
System.out.print(spi.getDescription(null));
|
|
System.out.println(": extra image format");
|
|
format = spi.getImageMetadataFormat(args[0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (format == null) {
|
|
System.err.println("Unknown format: " + args[0]);
|
|
System.exit(0);
|
|
}
|
|
|
|
MetadataFormatPrinter printer = new MetadataFormatPrinter(System.out);
|
|
printer.print(format);
|
|
}
|
|
}
|