
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