import javax.xml.parsers.*; 
import org.w3c.dom.*; 

import java.awt.*;
import java.awt.event.*;

public class ch11_05 
{
    static String displayStrings[] = new String[1000];
    static int numberDisplayLines = 0;

    public static void displayDocument(String uri) 
    {
        try {

        DocumentBuilderFactory dbf =
            DocumentBuilderFactory.newInstance();

        DocumentBuilder db = null;
        try {
            db = dbf.newDocumentBuilder();
        } 
        catch (ParserConfigurationException pce) {}

        Document document = null;
            document = db.parse(uri);

            display(document, "");

        } catch (Exception e) {
            e.printStackTrace(System.err);
        }

    } 

    public static void display(Node node, String indent) 
    {
        if (node == null) {
            return;
        }

        int type = node.getNodeType();

        switch (type) {
            case Node.DOCUMENT_NODE: {
                displayStrings[numberDisplayLines] = indent;
                displayStrings[numberDisplayLines] += "<?xml version=\"1.0\" encoding=\""+
                  "UTF-8" + "\"?>";
                numberDisplayLines++;
                display(((Document)node).getDocumentElement(), "");
                break;
             }

             case Node.ELEMENT_NODE: {
                 displayStrings[numberDisplayLines] = indent;
                 displayStrings[numberDisplayLines] += "<";
                 displayStrings[numberDisplayLines] += node.getNodeName();

                 int length = (node.getAttributes() != null) ? node.getAttributes().getLength() : 0;
                 Attr attrs[] = new Attr[length];
                 for (int loopIndex = 0; loopIndex < length; loopIndex++) {
                     attrs[loopIndex] = (Attr)node.getAttributes().item(loopIndex);
                 }

                 for (int loopIndex = 0; loopIndex < attrs.length; loopIndex++) {
                     Attr attr = attrs[loopIndex];
                     displayStrings[numberDisplayLines] += " ";
                     displayStrings[numberDisplayLines] += attr.getNodeName();
                     displayStrings[numberDisplayLines] += "=\"";
                     displayStrings[numberDisplayLines] += attr.getNodeValue();
                     displayStrings[numberDisplayLines] += "\"";
                 }
                 displayStrings[numberDisplayLines] += ">";

                 numberDisplayLines++;

                 NodeList childNodes = node.getChildNodes();
                 if (childNodes != null) {
                     length = childNodes.getLength();
                     indent += "    ";
                     for (int loopIndex = 0; loopIndex < length; loopIndex++ ) {
                        display(childNodes.item(loopIndex), indent);
                     }
                 }
                 break;
             }

             case Node.CDATA_SECTION_NODE: {
                 displayStrings[numberDisplayLines] = indent;
                 displayStrings[numberDisplayLines] += "<![CDATA[";
                 displayStrings[numberDisplayLines] += node.getNodeValue();
                 displayStrings[numberDisplayLines] += "]]>";
                 numberDisplayLines++;
                 break;
             }

             case Node.TEXT_NODE: {
                 displayStrings[numberDisplayLines] = indent;
                 String newText = node.getNodeValue().trim();
                 if(newText.indexOf("\n") < 0 && newText.length() > 0) {
                     displayStrings[numberDisplayLines] += newText;
                     numberDisplayLines++;
                 }
                 break;
             }

             case Node.PROCESSING_INSTRUCTION_NODE: {
                 displayStrings[numberDisplayLines] = indent;

                 displayStrings[numberDisplayLines] += "<?";
                 displayStrings[numberDisplayLines] += node.getNodeName();
                 String text = node.getNodeValue();
                 if (text != null && text.length() > 0) {
                     displayStrings[numberDisplayLines] += text;
                 }
                 displayStrings[numberDisplayLines] += "?>";
                 numberDisplayLines++;
                 break;
            }    
        }

        if (type == Node.ELEMENT_NODE) {
            displayStrings[numberDisplayLines] = indent.substring(0, indent.length() - 4);
            displayStrings[numberDisplayLines] += "</";
            displayStrings[numberDisplayLines] += node.getNodeName();
            displayStrings[numberDisplayLines] += ">";
            numberDisplayLines++;
            indent+= "    ";
        }
    } 

    public static void main(String args[]) {

        displayDocument(args[0]);

        AppFrame f = new AppFrame(displayStrings, numberDisplayLines);

        f.setSize(300, 500);

        f.addWindowListener(new WindowAdapter() {public void
            windowClosing(WindowEvent e) {System.exit(0);}});

        f.show();
    } 
}

class AppFrame extends Frame
{
    String displayStrings[];
    int numberDisplayLines;

    public AppFrame(String[] strings, int number)
    {
        displayStrings = strings;
        numberDisplayLines = number;
    }

    public void paint(Graphics g)
    {
        Font font = new Font("Courier", Font.PLAIN, 12);
        g.setFont(font);

        FontMetrics fontmetrics = getFontMetrics(getFont());
        int y = fontmetrics.getHeight();

        for(int index = 0; index < numberDisplayLines; index++){
            y += fontmetrics.getHeight();
            g.drawString(displayStrings[index], 5, y);
        }
    }
}