/*
* $Id: PrettyPrinter.java,v 1.10 2002/09/16 08:05:07 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.util;
import anvil.parser.DocumentHandler;
import anvil.parser.InputSource;
import anvil.parser.Locator;
import anvil.parser.Parser;
import anvil.parser.Tag;
import java.io.IOException;
import java.io.Writer;
import java.util.Stack;
import java.util.HashSet;
import java.util.StringTokenizer;
/**
* class PrettyPrinter
*
* @author: Jani Lehtim�ki
*/
public class PrettyPrinter implements DocumentHandler
{
private static final HashSet NO_CONTENT = new HashSet();
static {
NO_CONTENT.add("area");
NO_CONTENT.add("base");
NO_CONTENT.add("br");
NO_CONTENT.add("center");
NO_CONTENT.add("frame");
NO_CONTENT.add("hr");
NO_CONTENT.add("img");
NO_CONTENT.add("input");
NO_CONTENT.add("li");
NO_CONTENT.add("link");
NO_CONTENT.add("meta");
NO_CONTENT.add("option");
NO_CONTENT.add("p");
}
private Writer _writer;
private InputSource _source;
private Locator _locator = null;
private Stack _tags = new Stack();
private int _indent = 0;
public PrettyPrinter(InputSource source, Writer writer)
{
_source = source;
_writer = writer;
}
public void setDocumentLocator(Locator locator)
{
_locator = locator;
}
private void write(char ch)
{
try {
_writer.write(ch);
} catch (IOException e) {
}
}
private void write(String string)
{
try {
_writer.write(string);
} catch (IOException e) {
}
}
private void indent()
{
try {
_writer.write('\n');
for(int i=_indent * 2; i>0; i--) {
_writer.write(' ');
}
} catch (IOException e) {
}
}
public void startDocument()
{
}
public void endDocument()
{
try {
_writer.flush();
} catch (IOException e) {
}
}
public String compress(String cdata)
{
if (cdata.charAt(0) == '<') {
return cdata;
}
int n = cdata.length();
int i = 0;
char ch;
char pad = ' ';
StringBuffer buffer = new StringBuffer();
while( i < n ) {
ch = cdata.charAt(i);
if (Character.isWhitespace(ch)) {
pad = ' ';
while( (++i) < n ) {
if (ch == '\n') {
pad = '\n';
}
ch = cdata.charAt(i);
if (!Character.isWhitespace(ch)) {
break;
}
}
buffer.append(pad);
} else {
buffer.append(ch);
i++;
}
}
return buffer.toString();
}
public boolean allowIndent()
{
if (_tags.size()>0) {
Tag previousTag = (Tag)_tags.peek();
String name = previousTag.getName();
if (name.equalsIgnoreCase("td")) {
return false;
}
if (name.equalsIgnoreCase("textarea")) {
return false;
}
}
return true;
}
public void handleCharacters(String characters)
{
characters = compress(characters);
int length = characters.length();
if (length == 0) {
return;
}
if (characters.indexOf('\n')>-1) {
boolean doIndent = allowIndent();
StringTokenizer tok = new StringTokenizer(characters, "\n");
while(tok.hasMoreTokens()) {
if (doIndent) {
indent();
}
write(tok.nextToken());
doIndent = true;
}
} else {
write(characters);
}
}
public void handleComment(String characters)
{
if (allowIndent()) {
indent();
}
write("<!");
write(characters);
write('>');
}
public void handleTag(Tag tag)
{
if (tag.isEndTag()) {
String name = tag.getName().substring(1);
Tag at;
int i = _tags.size() - 1;
while(i>=0) {
at = (Tag)_tags.elementAt(i);
if (name.equalsIgnoreCase(at.getName())) {
break;
}
i--;
}
if (i>=0) {
while(_tags.size()>i) {
_tags.pop();
_indent--;
}
}
if (!(name.equalsIgnoreCase("a") ||
name.equalsIgnoreCase("td") ||
name.equalsIgnoreCase("textarea")))
{
indent();
}
write(tag.toString());
} else {
if (!tag.getName().equalsIgnoreCase("br") && allowIndent()) {
indent();
}
write(tag.toString());
boolean push = true;
if (tag.hasEndSlash()) {
push = false;
} else {
String name = tag.getName();
if (NO_CONTENT.contains(name.toLowerCase())) {
push = false;
}
}
if (push) {
_tags.push(tag);
_indent++;
}
}
}
public void handleProcessingInstruction(String data)
{
if (allowIndent()) {
indent();
}
write("<?");
write(data);
write("?>");
}
public void print() throws IOException
{
Parser parser = new Parser();
parser.parse(this, _source);
}
}