All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enhydra.xml.dom.DOMInfoPrinter Maven / Gradle / Ivy

The newest version!
/*
 * Enhydra Java Application Server Project
 * 
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 
 * the License for the specific terms governing rights and limitations
 * under the License.
 * 
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * $Id: DOMInfoPrinter.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */

package org.enhydra.xml.dom;

import java.io.PrintWriter;

import org.enhydra.xml.xmlc.codegen.JavaLang;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Notation;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

/**
 * DOMTraversal handler for DOMInfo, using only generic DOM interfaces.
 */
public class DOMInfoPrinter implements DOMTraversal.Handler {
    /** Size to truncate text to */
    private static final int TEXT_TRUNCATE_SIZE = 12;

    /** Writer for output. */
    protected PrintWriter fOut;

    /** Print lines breaks as \n and \r */
    private boolean fSymbolicLineBreaks;

    /** Should text strings be truncated? */
    private boolean fTruncateText;

    /** Control attribute formatting. */
    protected boolean fVerboseAttributes;
    
    /** Should all attributes, or only specified ones be printed? */
    protected boolean fAllAttributes;
    
    /**
     * Flag to indicate that nothing should be printed, just nodes counted.
     * Use to implement terse attribute printing, nonly need be checked on
     * thinks that can be children of attributes.
     */
    protected boolean fAttrSkipPrint;

    /**
     * DOM traversal object.
     */
    private DOMTraversal fTraverser;

    /**
     * Indent level.
     */
    protected int level;

    /**
     * Constructor.
     */
    protected DOMInfoPrinter(int options,
                             DOMTraversal traverser,
                             PrintWriter out) {
        fOut = out;
        fSymbolicLineBreaks = ((options & DOMInfo.SYM_TEXT_LINEBREAKS) != 0);
        fTruncateText = ((options & DOMInfo.TRUNCATE_TEXT) != 0);
        fVerboseAttributes = ((options & DOMInfo.PRINT_ATTR_DETAILS) != 0);
        fAllAttributes = ((options & DOMInfo.ALL_ATTRS) != 0);
        fTraverser = traverser;
        traverser.setHandler(this);
    }

    /**
     * Print indentation.
     */
    protected void printIndent() {
        for (int i = 0; i < level + 1; i++) {
            fOut.print("    ");
        }
    }

    /**
     * Determine if a character should be printed as is.
     */
    private boolean isPrintable(char ch) {
        return ((ch <= 0x7f)
                && (Character.isWhitespace(ch) || !Character.isISOControl(ch)));
    }

    /**
     * Print a block of text, encoding non-ASCII or ISO control
     * charcters using the \u0000 convention.
     */
    private void printString(String text) {
        int len = text.length();
        for (int idx = 0; idx < len; idx++) {
            char ch = text.charAt(idx);
            if (fSymbolicLineBreaks && ((ch == '\n') || (ch == '\r'))) {
                fOut.write((ch == '\n') ? "\\n" : "\\r");
            } else if (isPrintable(ch)) {
                fOut.write(ch);
            } else {
                String hex = Integer.toHexString(ch);
                fOut.write("\\u");
                for (int cnt = hex.length(); cnt < 4; cnt++) {
                    fOut.write('0');
                }
                fOut.write(hex);
            }
        }
    }

    /*
     * Print a label and value if the value is not null or empty.
     */
    private void printLabelValue(String label,
                                 String value) {
        if ((value != null) && (value.length() > 0)) {
            fOut.print(" ");
            fOut.print(label);
            fOut.print("=");
            printString(value);
        }
    }

    /**
     * Print a name, with a space in front of it, if not null.
     */
    private void printName(String name) {
        if (name != null) {
            fOut.print(" ");
            fOut.print(name);
        }
    }

    /**
     * Print node name (override to add additional information).
     */
    protected void printNodeName(Node node) {
        fOut.print(JavaLang.simpleClassName(node.getClass().getName()));
    }

    /**
     * Print the basic information displayed about every node.
     */
    private void printNodeInfo(Node node) {
        // Print node class name without package.
        printIndent();
        printNodeName(node);
        fOut.print(':');
        String namespaceURI = node.getNamespaceURI();
        if ((namespaceURI != null) && (namespaceURI.length() > 0)) {
            printLabelValue("NS", namespaceURI);
            fOut.print(":");
        }
    }

    /**
     * Process children.
     */
    private void processChildren(Node node) {
        level++;
        fTraverser.processChildren(node);
        level--;
    }

    /**
     * Determine if an element has attributes that are to be printed.
     */ 
    protected boolean hasPrintAttributes(Element element) {
        NamedNodeMap attrs = element.getAttributes();
        if (attrs == null) {
            return false;
        }
        if (fAllAttributes) {
            return attrs.getLength() > 0;
        }
        // Check for specified attributes.
        for (int i = 0; i < attrs.getLength(); i++) {
            if (((Attr)attrs.item(i)).getSpecified()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Handler called for Document nodes.
     */
    public void handleDocument(Document document) {
        printNodeInfo(document);
        fOut.println();

        level++;
        fTraverser.processDocumentType(document);
        level--;
        processChildren(document);
    }

    /**
     * Handler called for DocumentType nodes.
     */
    public void handleDocumentType(DocumentType documentType) {
        printNodeInfo(documentType);
        printLabelValue("name", documentType.getNodeName());
        fOut.println();

        String internalSubset = documentType.getInternalSubset();
        if ((internalSubset != null) && (internalSubset.length() > 0)) {
            printIndent();
            printLabelValue("internalSubset", internalSubset);
            fOut.println();
        }

        level++;
        fTraverser.processDocumentTypeContents(documentType);
        // It is non-standard to have children of a document type,
        // however Xerces uses this for grammar.
        processChildren(documentType);
        level--;
    }

    /**
     * Handler called for DocumentFragment nodes.
     */
    public void handleDocumentFragment(DocumentFragment documentFragment) {
        printNodeInfo(documentFragment);
        printLabelValue("name", documentFragment.getNodeName());
        fOut.println();

        processChildren(documentFragment);
    }

    /**
     * Print an attribute in a terse manner.
     */
    private void printTerseAttrInfo(Node attr) {
        printName(attr.getNodeName());
        fOut.print("=\"");
        printString(attr.getNodeValue());
        fOut.print("\"");
    }

    /**
     * Print an attribute in a verbose manner.
     */
    private void printVerboseAttrInfo(Node attr) {
        printNodeInfo(attr);
        printName(attr.getNodeName());
        if (!((Attr)attr).getSpecified()) {
            fOut.print(" (unspecified)");
        }
        fOut.println();
    }

    /**
     * Handler called for Attr nodes.
     */
    public void handleAttr(Attr attr) {
        if (fVerboseAttributes) {
            printVerboseAttrInfo(attr);
        } else {
            printTerseAttrInfo(attr);
        }

        fAttrSkipPrint = !fVerboseAttributes;
        processChildren(attr);
        fAttrSkipPrint = false;
    }

    /**
     * Handler called for Entity nodes.
     */
    public void handleEntity(Entity entity) {
        printNodeInfo(entity);
        printLabelValue("name", entity.getNodeName());
        printLabelValue("notationName", entity.getNotationName());
        printLabelValue("systemId", entity.getPublicId());
        printLabelValue("publicId", entity.getPublicId());
        fOut.println();

        processChildren(entity);
    }

    /**
     * Handler called for EntityReference nodes.
     */
    public void handleEntityReference(EntityReference entityRef) {
        if (!fAttrSkipPrint) {
            printNodeInfo(entityRef);
            printLabelValue("name", entityRef.getNodeName());
            fOut.println();
        }
        processChildren(entityRef);
    }

    /**
     * Process an element's attributes.
     */
    private void processAttributes(Element element) {
        if (fVerboseAttributes) {
            fOut.println();
            if (hasPrintAttributes(element)) {
                level++;
                printIndent();
                fOut.println("Attributes:");
                level++;
                fTraverser.processAttributes(element);
                level -= 2;
            }
        } else {
            if (hasPrintAttributes(element)) {
                fOut.print(":");
                fTraverser.processAttributes(element);
            }
            fOut.println();
        }
    }

    /**
     * Handler called for Element nodes.
     */
    public void handleElement(Element element) {
        printNodeInfo(element);
        printName(element.getNodeName());

        processAttributes(element);
        processChildren(element);
    }

    /**
     * Handler called for Notation nodes.
     */
    public void handleNotation(Notation notation) {
        if (!fAttrSkipPrint) {
            printNodeInfo(notation);
            printLabelValue("systemId", notation.getSystemId());
            printLabelValue("publicId", notation.getPublicId());
        }
    }

    /**
     * Handler called for ProcessingInstruction nodes.
     */
    public void handleProcessingInstruction(ProcessingInstruction pi) {
        if (!fAttrSkipPrint) {
            printNodeInfo(pi);
            printLabelValue("target", pi.getTarget());
            printLabelValue("data", pi.getData());
            fOut.println();
        }
    }

    /**
     * Print information about any of the CharacterData nodes.
     */
    private void printCharacterDataInfo(CharacterData charData) {
        if (!fAttrSkipPrint) {
            printNodeInfo(charData);
            fOut.print(" ");
            String data = charData.getData();
            if (fTruncateText && (data.length() > TEXT_TRUNCATE_SIZE)) {
                data = data.substring(0, TEXT_TRUNCATE_SIZE);
            }
            printString(data);
            fOut.println();
        }
    }

    /**
     * Handler called for CDATASection nodes.
     */
    public void handleCDATASection(CDATASection cdata) {
        printCharacterDataInfo(cdata);
    }

    /**
     * Handler called for Comment nodes.
     */
    public void handleComment(Comment comment) {
        printCharacterDataInfo(comment);
    }

    /**
     * Handler called for Text nodes.
     */
    public void handleText(Text text) {
        printCharacterDataInfo(text);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy