Path: blob/master/test/jdk/javax/imageio/metadata/MetadataFormatPrinter.java
41149 views
/*1* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223//2425import java.io.PrintStream;26import java.util.ArrayList;27import java.util.Arrays;28import java.util.HashSet;29import java.util.Iterator;30import java.util.List;31import java.util.Set;32import java.util.StringTokenizer;33import javax.imageio.metadata.IIOMetadata;34import javax.imageio.metadata.IIOMetadataFormat;35import javax.imageio.metadata.IIOMetadataFormatImpl;36import javax.imageio.spi.IIORegistry;37import javax.imageio.spi.ImageReaderSpi;38import com.sun.imageio.plugins.png.PNGMetadata;3940public class MetadataFormatPrinter {4142private int indentLevel = 0;4344private int column = 0;4546private PrintStream out;4748private static final int maxColumn = 75;4950private static String[] dataTypeNames = {51"String", "Boolean", "Integer", "Float", "Double"52};5354// "Infinite" values55private static String maxInteger = Integer.toString(Integer.MAX_VALUE);5657public MetadataFormatPrinter(PrintStream out) {58this.out = out;59}6061private void println() {62out.println();63column = 0;64}6566private void println(String s) {67out.println(s);68column = 0;69}7071private void printWrapped(String in, int leftIndent) {72StringTokenizer t = new StringTokenizer(in);73while (t.hasMoreTokens()) {74String s = t.nextToken();75int length = s.length();76if (column + length > maxColumn) {77println();78indent();79for (int i = 0; i < leftIndent; i++) {80print(" ");81}82}83out.print(s);84out.print(" ");85column += length + 1;86}87}8889private void print(String s) {90int length = s.length();91if (column + length > maxColumn) {92println();93indent();94print(" ");95}96out.print(s);97column += length;98}99100private void print(IIOMetadataFormat format) {101String rootName = format.getRootName();102println("<!DOCTYPE \"" +103rootName +104"\" [");105++indentLevel;106print(format, rootName);107--indentLevel;108print("]>");109println();110println();111}112113private void indent() {114for (int i = 0; i < indentLevel; i++) {115out.print(" ");116column += 2;117}118}119120private void printElementInfo(IIOMetadataFormat format,121String elementName) {122println();123indent();124print("<!ELEMENT \"" +125elementName +126"\"");127128String[] childNames = format.getChildNames(elementName);129boolean hasChildren = true;130String separator = " "; // symbol to place between children131String terminator = ""; // symbol to follow last child132String repeater = ""; // "*" if repeating133134switch (format.getChildPolicy(elementName)) {135case IIOMetadataFormat.CHILD_POLICY_EMPTY:136hasChildren = false;137break;138case IIOMetadataFormat.CHILD_POLICY_ALL:139separator = ", ";140break;141case IIOMetadataFormat.CHILD_POLICY_SOME:142separator = "?, ";143terminator = "?";144break;145case IIOMetadataFormat.CHILD_POLICY_CHOICE:146separator = " | ";147break;148case IIOMetadataFormat.CHILD_POLICY_SEQUENCE:149separator = " | ";150repeater = "*";151break;152case IIOMetadataFormat.CHILD_POLICY_REPEAT:153repeater = "*";154break;155default:156break;157}158159if (hasChildren) {160print(" (");161for (int i = 0; i < childNames.length - 1; i++) {162print(childNames[i] + separator);163}164print(childNames[childNames.length - 1] + terminator);165print(")" + repeater + ">");166} else {167print(" EMPTY>");168}169println();170171String description = format.getElementDescription(elementName, null);172if (description != null) {173++indentLevel;174indent();175printWrapped("<!-- " + description + " -->", 5);176println();177--indentLevel;178}179if (format.getChildPolicy(elementName) ==180IIOMetadataFormat.CHILD_POLICY_REPEAT) {181int minChildren = format.getElementMinChildren(elementName);182if (minChildren != 0) {183indent();184println(" <!-- Min children: " +185minChildren +186" -->");187}188int maxChildren = format.getElementMaxChildren(elementName);189if (maxChildren != Integer.MAX_VALUE) {190indent();191println(" <!-- Max children: " +192maxChildren +193" -->");194}195}196}197198private void printAttributeInfo(IIOMetadataFormat format,199String elementName,200String attrName) {201indent();202print("<!ATTLIST \"" +203elementName +204"\" \"" +205attrName +206"\"");207208int attrValueType =209format.getAttributeValueType(elementName, attrName);210switch (attrValueType) {211case IIOMetadataFormat.VALUE_NONE:212throw new RuntimeException213("Encountered VALUE_NONE for an attribute!");214// break;215case IIOMetadataFormat.VALUE_ARBITRARY:216print(" #CDATA");217break;218case IIOMetadataFormat.VALUE_RANGE:219case IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE:220case IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE:221case IIOMetadataFormat.VALUE_RANGE_MIN_MAX_INCLUSIVE:222print(" #CDATA");223break;224case IIOMetadataFormat.VALUE_ENUMERATION:225print(" (");226String[] attrValues =227format.getAttributeEnumerations(elementName, attrName);228for (int j = 0; j < attrValues.length - 1; j++) {229print("\"" + attrValues[j] + "\" | ");230}231print("\"" + attrValues[attrValues.length - 1] + "\")");232break;233case IIOMetadataFormat.VALUE_LIST:234print(" #CDATA");235break;236default:237throw new RuntimeException238("Encountered unknown value type for an attribute!");239// break;240}241242String defaultValue =243format.getAttributeDefaultValue(elementName, attrName);244if (defaultValue != null) {245print(" ");246print("\"" + defaultValue + "\"");247} else {248if (format.isAttributeRequired(elementName, attrName)) {249print(" #REQUIRED");250} else {251print(" #IMPLIED");252}253}254println(">");255256String description = format.getAttributeDescription(elementName,257attrName,258null);259if (description != null) {260++indentLevel;261indent();262printWrapped("<!-- " + description + " -->", 5);263println();264--indentLevel;265}266267int dataType = format.getAttributeDataType(elementName, attrName);268269switch (attrValueType) {270case IIOMetadataFormat.VALUE_ARBITRARY:271indent();272println(" <!-- Data type: " + dataTypeNames[dataType] + " -->");273break;274275case IIOMetadataFormat.VALUE_RANGE:276case IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE:277case IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE:278case IIOMetadataFormat.VALUE_RANGE_MIN_MAX_INCLUSIVE:279indent();280println(" <!-- Data type: " + dataTypeNames[dataType] + " -->");281282boolean minInclusive =283(attrValueType &284IIOMetadataFormat.VALUE_RANGE_MIN_INCLUSIVE_MASK) != 0;285boolean maxInclusive =286(attrValueType &287IIOMetadataFormat.VALUE_RANGE_MAX_INCLUSIVE_MASK) != 0;288indent();289println(" <!-- Min value: " +290format.getAttributeMinValue(elementName, attrName) +291" " +292(minInclusive ? "(inclusive)" : "(exclusive)") +293" -->");294String maxValue =295format.getAttributeMaxValue(elementName, attrName);296// Hack: don't print "infinite" max values297if (dataType != IIOMetadataFormat.DATATYPE_INTEGER ||298!maxValue.equals(maxInteger)) {299indent();300println(" <!-- Max value: " +301maxValue +302" " +303(maxInclusive ? "(inclusive)" : "(exclusive)") +304" -->");305}306break;307308case IIOMetadataFormat.VALUE_LIST:309indent();310println(" <!-- Data type: List of " + dataTypeNames[dataType] + " -->");311312int minLength =313format.getAttributeListMinLength(elementName, attrName);314if (minLength != 0) {315indent();316println(" <!-- Min length: " +317minLength +318" -->");319}320int maxLength =321format.getAttributeListMaxLength(elementName, attrName);322if (maxLength != Integer.MAX_VALUE) {323indent();324println(" <!-- Max length: " +325maxLength +326" -->");327}328break;329}330}331332private void printObjectInfo(IIOMetadataFormat format,333String elementName) {334int objectType = format.getObjectValueType(elementName);335if (objectType == IIOMetadataFormat.VALUE_NONE) {336return;337}338339Class objectClass = format.getObjectClass(elementName);340if (objectClass != null) {341indent();342if (objectType == IIOMetadataFormat.VALUE_LIST) {343println(" <!-- User object: array of " +344objectClass.getName() +345" -->");346} else {347println(" <!-- User object: " +348objectClass.getName() +349" -->");350}351352Object defaultValue = format.getObjectDefaultValue(elementName);353if (defaultValue != null) {354indent();355println(" <!-- Default value: " +356defaultValue.toString() +357" -->");358}359360switch (objectType) {361case IIOMetadataFormat.VALUE_RANGE:362indent();363println(" <!-- Min value: " +364format.getObjectMinValue(elementName).toString() +365" -->");366indent();367println(" <!-- Max value: " +368format.getObjectMaxValue(elementName).toString() +369" -->");370break;371372case IIOMetadataFormat.VALUE_ENUMERATION:373Object[] enums = format.getObjectEnumerations(elementName);374for (int i = 0; i < enums.length; i++) {375indent();376println(" <!-- Enumerated value: " +377enums[i].toString() +378" -->");379}380break;381382case IIOMetadataFormat.VALUE_LIST:383int minLength = format.getObjectArrayMinLength(elementName);384if (minLength != 0) {385indent();386println(" <!-- Min length: " +387minLength +388" -->");389}390int maxLength = format.getObjectArrayMaxLength(elementName);391if (maxLength != Integer.MAX_VALUE) {392indent();393println(" <!-- Max length: " +394maxLength +395" -->");396}397break;398}399}400}401402// Set of elements that have been printed already403Set printedElements = new HashSet();404405// Set of elements that have been scheduled to be printed406Set scheduledElements = new HashSet();407408private void print(IIOMetadataFormat format,409String elementName) {410// Don't print elements more than once411if (printedElements.contains(elementName)) {412return;413}414printedElements.add(elementName);415416// Add the unscheduled children of this node to a list,417// and mark them as scheduled418List children = new ArrayList();419String[] childNames = format.getChildNames(elementName);420if (childNames != null) {421for (int i = 0; i < childNames.length; i++) {422String childName = childNames[i];423if (!scheduledElements.contains(childName)) {424children.add(childName);425scheduledElements.add(childName);426}427}428}429430printElementInfo(format, elementName);431printObjectInfo(format, elementName);432433++indentLevel;434String[] attrNames = format.getAttributeNames(elementName);435for (int i = 0; i < attrNames.length; i++) {436printAttributeInfo(format, elementName, attrNames[i]);437}438439// Recurse on child nodes440Iterator iter = children.iterator();441while (iter.hasNext()) {442print(format, (String)iter.next());443}444--indentLevel;445}446447public static void main(String[] args) {448IIOMetadataFormat format = null;449if (args.length == 0 || args[0].equals("javax_imageio_1.0")) {450format = IIOMetadataFormatImpl.getStandardFormatInstance();451} else {452IIORegistry registry = IIORegistry.getDefaultInstance();453Iterator iter = registry.getServiceProviders(ImageReaderSpi.class,454false);455while (iter.hasNext()) {456ImageReaderSpi spi = (ImageReaderSpi)iter.next();457if (args[0].equals458(spi.getNativeStreamMetadataFormatName())) {459System.out.print(spi.getDescription(null));460System.out.println(": native stream format");461format = spi.getStreamMetadataFormat(args[0]);462break;463}464465String[] extraStreamFormatNames =466spi.getExtraStreamMetadataFormatNames();467if (extraStreamFormatNames != null &&468Arrays.asList(extraStreamFormatNames).469contains(args[0])) {470System.out.print(spi.getDescription(null));471System.out.println(": extra stream format");472format = spi.getStreamMetadataFormat(args[0]);473break;474}475476if (args[0].equals477(spi.getNativeImageMetadataFormatName())) {478System.out.print(spi.getDescription(null));479System.out.println(": native image format");480format = spi.getImageMetadataFormat(args[0]);481break;482}483484String[] extraImageFormatNames =485spi.getExtraImageMetadataFormatNames();486if (extraImageFormatNames != null &&487Arrays.asList(extraImageFormatNames).contains(args[0])) {488System.out.print(spi.getDescription(null));489System.out.println(": extra image format");490format = spi.getImageMetadataFormat(args[0]);491break;492}493}494}495496if (format == null) {497System.err.println("Unknown format: " + args[0]);498System.exit(0);499}500501MetadataFormatPrinter printer = new MetadataFormatPrinter(System.out);502printer.print(format);503}504}505506507