jdk/test/javax/imageio/metadata/MetadataFormatPrinter.java
changeset 13769 ba52da5186ad
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/metadata/MetadataFormatPrinter.java	Mon Sep 17 13:44:07 2012 +0400
@@ -0,0 +1,505 @@
+/*
+ * 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);
+    }
+}