What this is
This file is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2002 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.tax.io;
import java.lang.reflect.*;
import java.io.Writer;
import java.io.StringWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.PipedWriter;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.text.MessageFormat;
import org.netbeans.tax.TreeException;
import org.netbeans.tax.TreeDocumentRoot;
import org.netbeans.tax.TreeNode;
import org.netbeans.tax.TreeChild;
import org.netbeans.tax.TreeObjectList;
import org.netbeans.tax.TreeParentNode;
import org.netbeans.tax.TreeAttlistDecl;
import org.netbeans.tax.TreeAttlistDeclAttributeDef;
import org.netbeans.tax.TreeAttribute;
import org.netbeans.tax.TreeCDATASection;
import org.netbeans.tax.TreeCharacterReference;
import org.netbeans.tax.TreeCharacterData;
import org.netbeans.tax.TreeComment;
import org.netbeans.tax.TreeConditionalSection;
import org.netbeans.tax.TreeDocumentFragment;
import org.netbeans.tax.TreeDocument;
import org.netbeans.tax.TreeDocumentType;
import org.netbeans.tax.TreeDTD;
import org.netbeans.tax.TreeElementDecl;
import org.netbeans.tax.TreeElement;
import org.netbeans.tax.TreeEntityDecl;
import org.netbeans.tax.TreeGeneralEntityReference;
import org.netbeans.tax.TreeNotationDecl;
import org.netbeans.tax.TreeParameterEntityReference;
import org.netbeans.tax.TreeProcessingInstruction;
import org.netbeans.tax.TreeText;
import org.netbeans.tax.TreeUtilities;
import org.netbeans.tax.spec.AttlistDecl;
import org.netbeans.tax.spec.Attribute;
import org.netbeans.tax.spec.CDATASection;
import org.netbeans.tax.spec.CharacterReference;
import org.netbeans.tax.spec.Comment;
import org.netbeans.tax.spec.ConditionalSection;
import org.netbeans.tax.spec.DocumentFragment;
import org.netbeans.tax.spec.Document;
import org.netbeans.tax.spec.DocumentType;
import org.netbeans.tax.spec.DTD;
import org.netbeans.tax.spec.ElementDecl;
import org.netbeans.tax.spec.Element;
import org.netbeans.tax.spec.EntityDecl;
import org.netbeans.tax.spec.GeneralEntityReference;
import org.netbeans.tax.spec.NotationDecl;
import org.netbeans.tax.spec.ParameterEntityReference;
import org.netbeans.tax.spec.ProcessingInstruction;
import org.netbeans.tax.spec.Text;
/**
* We should avoid MessageFormat usage, it is probably the slowest method
* for constructing output.
*
* Fast implementation would write directly to steam/StringBuffer without
* construction so many auxiliary Strings.
*
* @author Libor Kramolis
* @version 0.1
*/
public class TreeStreamResult implements TreeOutputResult {
/** */
private TreeStreamWriter writer;
//
// init
//
/** Creates new TreeStreamResult. */
public TreeStreamResult (OutputStream outputStream) {
this.writer = new TreeStreamWriter (outputStream);
}
/** Creates new TreeStreamResult. */
public TreeStreamResult (StringWriter writer) {
this.writer = new TreeStreamWriter (writer);
}
public TreeStreamResult (PipedWriter writer) {
this.writer = new TreeStreamWriter (writer);
}
//
// itself
//
/**
*/
public final TreeWriter getWriter (TreeDocumentRoot document) {
writer.setDocument (document);
return writer;
}
//
// Writer
//
/**
*
*/
public final static class TreeStreamWriter
implements TreeWriter,
AttlistDecl.Writer,
Attribute.Writer,
CDATASection.Writer,
CharacterReference.Writer,
Comment.Writer,
ConditionalSection.Writer,
DocumentFragment.Writer,
Document.Writer,
DocumentType.Writer,
DTD.Writer,
ElementDecl.Writer,
Element.Writer,
EntityDecl.Writer,
GeneralEntityReference.Writer,
NotationDecl.Writer,
ParameterEntityReference.Writer,
ProcessingInstruction.Writer,
Text.Writer {
private static final char LESS_THAN = '<';
private static final char GREAT_THAN = '>';
private static final char AMPERSAND = '&';
private static final char SEMICOLON = ';';
private static final char APOSTROPHE = '\'';
private static final char QUOTE = '"';
private static final char PER_CENT = '%';
private static final char ASSIGN = '=';
private static final char BRACKET_LEFT = '[';
private static final char SPACE = ' ';
private static final String PI_START = ""; // NOI18N
private static final String COMMENT_START = ""; // NOI18N
private static final String ELEMENT_EMPTY_END = " />"; // NOI18N
private static final String ELEMENT_END_START = ""; // NOI18N
private static final String DOCTYPE_START = ""; // NOI18N
private static final String CHAR_REF_START = "&#"; // NOI18N
private static final String CHAR_REF_HEX_START = "&#x"; // NOI18N
private static final String ELEMENT_DECL_START = ".Writer
//
/**
*/
public void writeAttlistDecl (TreeAttlistDecl attlistDecl) throws TreeException {
StringBuffer sb = new StringBuffer ();
sb.append (ATTLIST_DECL_START).append (attlistDecl.getElementName ());
List attrdefs = attlistDecl.getAttributeDefs ();
Iterator it = attrdefs.iterator ();
while (it.hasNext ()) {
TreeAttlistDeclAttributeDef attrDef = (TreeAttlistDeclAttributeDef)it.next ();
sb.append ("\n\t").append (attrDef.getName ()).append (SPACE); // NOI18N
if (attrDef.getType () != attrDef.TYPE_ENUMERATED) {
sb.append (attrDef.getTypeName ()).append (SPACE);
}
if ((attrDef.getType () == TreeAttlistDeclAttributeDef.TYPE_ENUMERATED) ||
(attrDef.getType () == TreeAttlistDeclAttributeDef.TYPE_NOTATION)) {
sb.append (attrDef.getEnumeratedTypeString ()).append (SPACE);
}
if (attrDef.getDefaultType () != TreeAttlistDeclAttributeDef.DEFAULT_TYPE_NULL) {
sb.append (attrDef.getDefaultTypeName ()).append (SPACE);
}
if ((attrDef.getDefaultType () == TreeAttlistDeclAttributeDef.DEFAULT_TYPE_FIXED) ||
(attrDef.getDefaultType () == TreeAttlistDeclAttributeDef.DEFAULT_TYPE_NULL)) {
sb.append ("\"").append (attrDef.getDefaultValue ()).append ("\""); // NOI18N
}
}
sb.append (GREAT_THAN);
write (sb.toString ());
}
/**
* Write down the attribute if it was specified in document otherwise nothing.
*/
public void writeAttribute (TreeAttribute attribute) throws TreeException {
if (attribute.isSpecified () == false)
return;
write (createValueString (attribute.getQName (), attribute.getNonNormalizedValue ()));
}
/**
*/
public void writeCDATASection (TreeCDATASection cdataSection) throws TreeException {
String cdataData = cdataSection.getData ();
String cdataString = MessageFormat.format ("", new Object [] { cdataData }); // NOI18N
write (cdataString);
}
/**
*/
public void writeCharacterReference (TreeCharacterReference characterReference) throws TreeException {
String refName = characterReference.getName ();
String refString = MessageFormat.format ("&{0};", new Object [] { refName }); // NOI18N
write (refString);
}
/**
*/
public void writeComment (TreeComment comment) throws TreeException {
String comName = comment.getData ();
String comString = MessageFormat.format ("", new Object [] { comName }); // NOI18N
write (comString);
}
/**
*/
public void writeConditionalSection (TreeConditionalSection conditionalSection) throws TreeException {
if ( conditionalSection.isInclude () ) {
write (""); // NOI18N
}
/**
*/
public void writeDocumentFragment (TreeDocumentFragment documentFragment) throws TreeException {
StringBuffer sb = new StringBuffer ();
StringBuffer header = null;
if (documentFragment.getVersion () != null) {
if (header == null)
header = new StringBuffer ();
header.append (createValueString (XML_VERSION, documentFragment.getVersion ())).append (SPACE);
}
if (documentFragment.getEncoding () != null) {
if (header == null)
header = new StringBuffer ();
header.append (createValueString (XML_ENCODING, documentFragment.getEncoding ()));
}
if (header != null) {
sb.append (XML_HEADER).append (header).append (PI_END);
}
write (sb.toString () + "\n\n"); // NOI18N
indent -= indent_step;
writeObjectList (documentFragment);
}
/**
*/
public void writeDocument (TreeDocument document) throws TreeException {
StringBuffer sb = new StringBuffer ();
StringBuffer header = null;
if (document.getVersion () != null) {
if (header == null)
header = new StringBuffer ();
header.append (createValueString (XML_VERSION, document.getVersion ()));
}
if (document.getEncoding () != null) {
if (header == null)
header = new StringBuffer ();
header.append (SPACE).append (createValueString (XML_ENCODING, document.getEncoding ()));
}
if (document.getStandalone () != null) {
if (header == null)
header = new StringBuffer ();
header.append (SPACE).append (createValueString (XML_STANDALONE, document.getStandalone ()));
}
if (header != null) {
sb.append (XML_HEADER).append (header).append (PI_END);
}
write (sb.toString () + "\n\n"); // NOI18N
indent -= indent_step;
writeObjectList (document);
}
/**
*/
public void writeDocumentType (TreeDocumentType documentType) throws TreeException {
StringBuffer sb = new StringBuffer ();
sb.append (DOCTYPE_START).append (documentType.getElementName ());
if (documentType.getPublicId () != null) {
sb.append (SPACE).append (PUBLIC);
sb.append (createQuoteString (documentType.getPublicId ())).append (SPACE);
String systemId = documentType.getSystemId ();
sb.append (createQuoteString (systemId == null ? "" : systemId)); // NOI18N
} else if (documentType.getSystemId () != null) {
sb.append (SPACE).append (SYSTEM);
sb.append (createQuoteString (documentType.getSystemId ()));
}
write (sb.toString ());
if ( documentType.hasChildNodes () ) {
write (" ["); // NOI18N
//!!! use introspection to get internal DTD
try {
if (documentType == null) return;
Class klass = documentType.getClass ();
Field field = klass.getDeclaredField ("internalDTDText"); // NOI18N
field.setAccessible (true);
String internalDTDText = (String)field.get (documentType);
if ( internalDTDText != null ) {
write (internalDTDText);
} else {
// use tradition method instead (however it will resolve refs)
write ("\n"); // NOI18N
writeObjectList (documentType);
}
} catch (RuntimeException ex) {
throw ex;
} catch (Exception ex) {
// use tradition method instead (however it will resolve refs)
write ("\n"); // NOI18N
writeObjectList (documentType);
}
write ("]"); // NOI18N
}
write (GREAT_THAN); // NOI18N
}
/**
*/
public void writeDTD (TreeDTD dtd) throws TreeException {
StringBuffer sb = new StringBuffer ();
StringBuffer header = null;
if (dtd.getVersion () != null) {
if (header == null)
header = new StringBuffer ();
header.append (createValueString (XML_VERSION, dtd.getVersion ())).append (SPACE);
}
if (dtd.getEncoding () != null) {
if (header == null)
header = new StringBuffer ();
header.append (createValueString (XML_ENCODING, dtd.getEncoding ()));
}
if (header != null) {
sb.append (XML_HEADER).append (header).append (PI_END);
}
write (sb.toString () + "\n\n"); // NOI18N
indent -= indent_step;
writeObjectList (dtd);
}
/**
*/
public void writeElementDecl (TreeElementDecl elementDecl) throws TreeException {
StringBuffer sb = new StringBuffer ();
sb.append (ELEMENT_DECL_START).append (elementDecl.getName ()).append (SPACE);
sb.append (elementDecl.getContentType ().toString ());
sb.append (GREAT_THAN);
write (sb.toString ());
}
/**
*/
public void writeElement (TreeElement element) throws TreeException {
String elemName = element.getQName ();
write ("<" + elemName); // NOI18N
Iterator it = element.getAttributes ().iterator ();
while ( it.hasNext () ) {
TreeAttribute attr = (TreeAttribute)it.next ();
if (attr.isSpecified ()) {
write (SPACE);
writeAttribute (attr);
}
}
if (element.isEmpty ()) {
write ("/>"); // NOI18N
} else {
write (">"); // NOI18N
// content
writeObjectList (element);
// startIndent();
String endElemString = MessageFormat.format ("", new Object [] { elemName }); // NOI18N
write (endElemString);
}
}
/**
*/
public void writeEntityDecl (TreeEntityDecl entityDecl) throws TreeException {
String entParam = entityDecl.isParameter () ? "% " : ""; // NOI18N
String entName = entityDecl.getName ();
String entType = ""; // NOI18N
switch (entityDecl.getType ()) {
case TreeEntityDecl.TYPE_INTERNAL:
entType = "\"" + entityDecl.getInternalText () + "\""; // NOI18N
break;
case TreeEntityDecl.TYPE_EXTERNAL:
entType = createExternalIdString (entityDecl.getPublicId (), entityDecl.getSystemId ());
break;
case TreeEntityDecl.TYPE_UNPARSED:
entType = createExternalIdString (entityDecl.getPublicId (), entityDecl.getSystemId ()) +
" NDATA " + entityDecl.getNotationName (); // NOI18N
break;
}
String entString = MessageFormat.format ("", new Object [] { entParam, entName, entType }); // NOI18N
write (entString);
}
/**
*/
public void writeGeneralEntityReference (TreeGeneralEntityReference generalEntityReference) throws TreeException {
String refName = generalEntityReference.getName ();
String refString = MessageFormat.format
("&{0};", new Object [] { refName }); // NOI18N
write (refString);
}
/**
*/
public void writeNotationDecl (TreeNotationDecl notationDecl) throws TreeException {
String notName = notationDecl.getName ();
String notSysId = notationDecl.getSystemId ();
String notPubId = notationDecl.getPublicId ();
String notExtId = createExternalIdString (notPubId, notSysId);
String notString = MessageFormat.format
("", new Object [] { notName, notExtId }); // NOI18N
write (notString);
}
/**
*/
public void writeParameterEntityReference (TreeParameterEntityReference parameterEntityReference) throws TreeException {
String refName = parameterEntityReference.getName ();
String refString = MessageFormat.format
("%{0};", new Object [] { refName }); // NOI18N
write (refString);
}
/**
*/
public void writeProcessingInstruction (TreeProcessingInstruction processingInstruction) throws TreeException {
String piTarget = processingInstruction.getTarget ();
String piData = processingInstruction.getData ();
String piString = MessageFormat.format
("", new Object [] { piTarget, piData }); // NOI18N
write (piString);
}
/**
*/
public void writeText (TreeText text) throws TreeException {
String textString = text.getData ();
write (textString);
}
//
// itself
//
private void write (String string) throws TreeException {
try {
writer.write (string);
} catch (IOException exc) {
throw new TreeException (exc);
}
}
private void write (char ch) throws TreeException {
try {
writer.write (ch);
} catch (IOException exc) {
throw new TreeException (exc);
}
}
private void startIndent () throws TreeException {
StringBuffer sb = new StringBuffer ();
for (int i = 0; i < indent; i++) {
sb.append (' ');
}
try {
writer.write (sb.toString ());
} catch (IOException exc) {
throw new TreeException (exc);
}
}
private void endIndent () throws TreeException {
write ("\n"); // NOI18N
}
private void writeObjectList (TreeParentNode parentNode) throws TreeException {
indent += indent_step;
boolean notElementChild = ( parentNode instanceof TreeElement ) == false;
boolean documentChild = ( parentNode instanceof TreeDocument ) == true;
Iterator it = parentNode.getChildNodes ().iterator ();
while ( it.hasNext () ) {
TreeNode node = (TreeNode)it.next ();
// boolean isNotCharData = ( node instanceof TreeCharacterData ) == false;
if ( notElementChild ) {
// if ( isNotCharData ) {
startIndent ();
}
writeNode (node);
if ( notElementChild ) {
// if ( isNotCharData ) {
endIndent ();
}
if ( documentChild ) {
endIndent ();
}
}
indent -= indent_step;
}
/**
* Writes name value pair (attribute, encoding, standalone,...)
*/
private String createValueString (String name, String value) {
String valueString = MessageFormat.format
("{0}={1}", new Object [] { name, createQuoteString (value) }); // NOI18N
return valueString;
}
/**
* Autodetect quoting char giving highets priority to '"'.
*/
private String createQuoteString (String value) {
Character quote = new Character (QUOTE);
if ( value.indexOf (QUOTE) != -1 ) {
quote = new Character (APOSTROPHE);
}
return createQuoteString (value, quote);
}
/**
*/
private String createQuoteString (String value, Character quote) {
String valueString = MessageFormat.format
("{1}{0}{1}", new Object [] { value, quote }); // NOI18N
return valueString;
}
/**
*/
private String createExternalIdString (String publicId, String systemId) {
String externId;
if (publicId == null) {
externId = MessageFormat.format
("SYSTEM {0}", new Object [] { createQuoteString (systemId) }); // NOI18N
} else if (systemId == null) {
externId = MessageFormat.format
("PUBLIC {0}", new Object [] { createQuoteString (publicId) }); // NOI18N
} else {
externId = MessageFormat.format
("PUBLIC {0} {1}", new Object [] { createQuoteString (publicId), createQuoteString (systemId) }); // NOI18N
}
return externId;
}
} // end: class TreeStreamWriter
}
|