blob: 5338739c26c867d8f465c1c38fcbf198c418436d [file] [log] [blame]
/*
* 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);
}
}