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

org.enhydra.xml.dom.DOMStats 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: DOMStats.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */

package org.enhydra.xml.dom;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.TreeMap;

import org.enhydra.xml.lazydom.LazyNode;
import org.enhydra.xml.xmlc.codegen.JavaLang;
import org.w3c.dom.Node;

/*
 * NB: This has special handling for LazyDOM nodes.  It would have been better
 * from an OOD perspective to derive a LazyDOMStats class.
 */

/**
 * Collect and print statistics on a DOM.
 */
public class DOMStats {
    /**
     * Option flag to print simple class names instead of fully qualified
     * names.
     */
    public static final int SIMPLE_CLASS_NAMES = 0x01;

    /**
     * Field width used for node types.
     */
    private static final int NODE_TYPE_WIDTH = 22;

    /**
     * Field width used for counts.
     */
    private static final int COUNT_WIDTH = 10;

    /**
     * Max Node type number.
     */
    private static final short MAX_NODE_TYPE = Node.NOTATION_NODE;

    /**
     * Indentation padding.
     */
    private static final String INDENT2 = "  ";
    private static final String INDENT4 = "    ";

    /**
     * Statitics collected on a node.
     */
    private class NodeStats {
        public int fNodeCount;     // New nodes for lazy DOM..
        public int fTemplateCount;
        public int fExpandedCount;

        /** Sum a NodeStats with this object. */
        public void sum(NodeStats stats) {
            fNodeCount += stats.fNodeCount;
            fTemplateCount += stats.fTemplateCount;
            fExpandedCount += stats.fExpandedCount;
        }
    }

    /**
     * Class used to collect a count Nodes by class
     */
    private class NodeClassCount {
        public final String fClass;
        public NodeStats fStats = new NodeStats();

        /** Constructor */
        public NodeClassCount(String nodeClass) {
            fClass = nodeClass;
        }
    }

    /*
     * Is this a LazyDOM?
     */
    private final boolean fIsLazyDOM;

    /**
     * Options sets.
     */
    private final int fOptions;

    /**
     * Table of counts, indexed by node class name.
     */
    private final TreeMap fNodeClassCounts = new TreeMap();

    /**
     * Maximum length of a node class name.
     */
    private int fMaxNodeClassName;

    /**
     * Count of nodes, indexed by type.
     */
    private NodeStats[] fTypeStats = new NodeStats[MAX_NODE_TYPE+1];

    /**
     * Constructor, collect stats.
     */
    private DOMStats(Node root,
                     int options) {
        fOptions = options;
        fIsLazyDOM = (DOMOps.getActualNode(root) instanceof LazyNode);
        for (int i = 0; i < fTypeStats.length; i++) {
            fTypeStats[i] = new NodeStats();
        }
        collectStats(root);
    }

    /**
     * Get the class name to print based on the options.
     */
    private String getPrintClassName(String className) {
        if ((fOptions & SIMPLE_CLASS_NAMES) != 0) {
            return JavaLang.simpleClassName(className);
        } else {
            return className;
        }
    }

    /**
     * Get a node class stats.
     */
    private NodeStats getNodeClassStats(Node node) {
        String nodeClass = node.getClass().getName();
        NodeClassCount counts = (NodeClassCount)fNodeClassCounts.get(nodeClass);
        if (counts == null) {
            counts = new NodeClassCount(nodeClass);
            fNodeClassCounts.put(nodeClass, counts);
            int nameLen = getPrintClassName(nodeClass).length();
            if (nameLen > fMaxNodeClassName) {
                fMaxNodeClassName = nameLen;
            }
        }
        return counts.fStats;
    }

    /**
     * Count a node by type.
     */
    private void countNode(Node node) {
        NodeStats classStats = getNodeClassStats(node);
        boolean isLazyNode = (node instanceof LazyNode);
        if (isLazyNode && ((LazyNode)node).isTemplateNode()) {
            fTypeStats[node.getNodeType()].fTemplateCount++;
            classStats.fTemplateCount++;
        } else if (isLazyNode && (((LazyNode)node).getNodeId() >= 0)) {
            fTypeStats[node.getNodeType()].fExpandedCount++;
            classStats.fExpandedCount++;
        } else {
            fTypeStats[node.getNodeType()].fNodeCount++;
            classStats.fNodeCount++;
        }
    }

    /**
     * Collect statistics.
     */
    private void collectStats(Node root) {
        SimpleDOMTraversal.Handler handler
            = new SimpleDOMTraversal.Handler() {
                    public void handleNode(Node node) {
                        countNode(node);
                    }
                };
        SimpleDOMTraversal traverser = SimpleDOMTraversal.getTraverser(handler, root);
        traverser.traverse(root);
    }

    //FIXME: need to collect these somewhere..
    /**
     * Right pad a string.
     */
    private String padRight(String src,
                            int len) {
        StringBuffer buf = new StringBuffer(len);
        int curLen = src.length();
        buf.append(src);
        while (curLen < len) {
            buf.append(' ');
            curLen++;
        }
        return buf.toString();
    }

    /**
     * Left pad a string.
     */
    private String padLeft(String src,
                           int len) {
        StringBuffer buf = new StringBuffer(len);
        int curLen = src.length();
        while (curLen < len) {
            buf.append(' ');
            curLen++;
        }
        buf.append(src);
        return buf.toString();
    }

    /**
     * Output a label plus a NodeStats.
     */
    private void printNodeStats(PrintWriter out,
                                String label,
                                int labelWidth,
                                NodeStats stats) {
        out.print(INDENT4);
        out.print(padRight(label, labelWidth));
        if (fIsLazyDOM) {
            out.print(padLeft(Integer.toString(stats.fTemplateCount), COUNT_WIDTH));
            out.print(padLeft(Integer.toString(stats.fExpandedCount), COUNT_WIDTH));
        }
        out.print(padLeft(Integer.toString(stats.fNodeCount), COUNT_WIDTH));
        out.println();
    }

    /**
     * Print nodes by type.
     */
    private void printByType(PrintWriter out) {
        out.print(INDENT2);
        out.print(padRight("Node Type", NODE_TYPE_WIDTH));
        out.print(INDENT2);
        if (fIsLazyDOM) {
            out.print(padLeft("Template", COUNT_WIDTH));
            out.print(padLeft("Expanded", COUNT_WIDTH));
            out.print(padLeft("New", COUNT_WIDTH));
        } else {
            out.print(padLeft("Nodes", COUNT_WIDTH));
        }
        out.println();
        NodeStats sum = new NodeStats();
        for (short type = 1; type <= MAX_NODE_TYPE; type++) {
            printNodeStats(out, DOMInfo.nodeTypeToName(type), NODE_TYPE_WIDTH,
                           fTypeStats[type]);
            sum.sum(fTypeStats[type]);
        }
        printNodeStats(out, "Total", NODE_TYPE_WIDTH, sum);
    }

    /**
     * Print nodes by class.
     */
    private void printByClass(PrintWriter out) {
        int labelWidth = fMaxNodeClassName + 2;
        out.print(INDENT2);
        out.print(padRight("Node Class", labelWidth));
        out.print(INDENT2);
        if (fIsLazyDOM) {
            out.print(padLeft("Template", COUNT_WIDTH));
            out.print(padLeft("Expanded", COUNT_WIDTH));
            out.print(padLeft("New", COUNT_WIDTH));
        } else {
            out.print(padLeft("Nodes", COUNT_WIDTH));
        }
        out.println();
        Iterator values = fNodeClassCounts.values().iterator();
        NodeStats sum = new NodeStats();
        while (values.hasNext()) {
            NodeClassCount count = (NodeClassCount)values.next();
            printNodeStats(out, getPrintClassName(count.fClass),
                           labelWidth, count.fStats);
            sum.sum(count.fStats);
        }
        printNodeStats(out, "Total", labelWidth, sum);
    }

    /**
     * Output statistics.
     */
    private void outputStats(String msg,
                             PrintWriter out) {
        if (out == null) {
            out = new PrintWriter(System.err, true);
        }
        if ((msg != null) && (msg.length() > 0)) {
            out.println(msg + ":");
        }
        printByType(out);
        printByClass(out);
        out.flush();
    }

    /**
     * Collect and print statistics about a DOM tree or subtree.
     * @param msg A message to print at the start.  If null or empty,
     *  don't print a message.
     * @param root Top of the tree.
     * @param options Option flags controlling printing.
     * @param out Output writer.  If null, stderr will be used.
     */
    public static void printStats(String msg,
                                  Node root,
                                  int options,
                                  PrintWriter out) {
        new DOMStats(root, options).outputStats(msg, out);
    }

    /**
     * Collect and print statistics about a DOM tree or subtree.
     * @param msg A message to print at the start.  If null or empty,
     *  don't print a message.
     * @param root Top of the tree.
     * @param options Option flags controlling printing.
     * @param out Output writer.  If null, stderr will be used.
     */
    public static void printStats(String msg,
                                  Node root,
                                  int options,
                                  OutputStream out) {
        PrintWriter writer = new PrintWriter((out != null) ? out : System.err, true);
        printStats(msg, root, options, writer);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy