Hi Mark,
Just finished javax.swing.text.html.HTMLWriter, can you commit it for me?
Thanks! ;)
                                                                  David Fu.
/* HTMLWriter.java -- 
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package javax.swing.text.html;

import java.io.IOException;
import java.io.Writer;

import java.util.Enumeration;
import java.util.HashSet;

import javax.swing.ComboBoxModel;

import javax.swing.text.AbstractWriter;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;

import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.Option;

/**
 * HTMLWriter,
 * A Writer for HTMLDocuments.
 *
 * @author David Fu (fchoong at netbeans.jp)
 */

public class HTMLWriter extends AbstractWriter
{
    private Writer outWriter = null;
    private HTMLDocument html_doc = null;
    
    private HashSet storeContentAttr = null;
    
    private String new_line_str = "" + NEWLINE;
    
    private char[] html_entity_char_arr         = {'<',    '>',    '&',     '"'};
    private String[] html_entity_escape_str_arr = {"&lt;", "&gt;", "&amp;", "&quot;"};
    
    public HTMLWriter(Writer writer, HTMLDocument doc)
    {
        super(writer, doc);
        outWriter = writer;
        html_doc = doc;
        storeContentAttr = new HashSet();
        
    } // public HTMLWriter(Writer writer, HTMLDocument doc)
    
    public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)
    {
        super(writer, doc, pos, len);
        outWriter = writer;
        html_doc = doc;
        storeContentAttr = new HashSet();
        
    } // public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)
    
    /** Call this method to start outputing HTML.
     */
    public void write() throws IOException, BadLocationException
    {
        Element rootElem = html_doc.getDefaultRootElement();
        
        traverse(rootElem);
        
        // NOTE: Close out remaining embeded tags.
        Object[] tag_arr = storeContentAttr.toArray();
        
        for(int i = 0; i < tag_arr.length; i++)
        {
            writeRaw("</" + tag_arr[i].toString() + ">");
        } // for(int i = 0; i < tag_arr.length; i++)
        
    } // public void write() throws IOException, BadLocationException
    
    private void traverse(Element paramElem) throws IOException, BadLocationException
    {
        Element currElem = paramElem;
        
        AttributeSet attrSet = currElem.getAttributes();
            
        closeOutUnwantedEmbeddedTags(attrSet);
        
        if(synthesizedElement(paramElem))
        {
            if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
            {
                writeEmbeddedTags(attrSet);
                text(currElem);
            } // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
            else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
            {
                comment(currElem);
            } // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
            else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
            {
                int child_elem_count = currElem.getElementCount();
                
                if(child_elem_count > 0)
                {
                    for(int i = 0; i < child_elem_count; i++)
                    {
                        Element childElem = paramElem.getElement(i);
            
                        traverse(childElem);
            
                    } // for(int i = 0; i < child_elem_count; i++)
                } // if(child_elem_count > 0)
            } // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
        } // if(synthesizedElement(paramElem))
        else
        {
            if(matchNameAttribute(attrSet, HTML.Tag.TITLE))
            {
                boolean fg_is_end_tag = false;
                Enumeration attrNameEnum = attrSet.getAttributeNames();
        
                while(attrNameEnum.hasMoreElements())
                {
                    Object key = attrNameEnum.nextElement();
                    Object value = attrSet.getAttribute(key);
            
                    if(key == HTML.Attribute.ENDTAG && value.equals("true"))
                        fg_is_end_tag = true;
                } // while(attrNameEnum.hasMoreElements())
                
                if(fg_is_end_tag)
                    writeRaw("</title>");
                else
                {
                    indent();
                    writeRaw("<title>");
                    
                    String title_str = (String) html_doc.getProperty(html_doc.TitleProperty);
                    
                    if(title_str != null)
                        writeContent(title_str);
                    
                } // else
            } // if(matchNameAttribute(attrSet, HTML.Tag.TITLE))
            else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
            {
                selectContent(attrSet);
            } // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
            else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
            {
                textAreaContent(attrSet);
            } // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
            else
            {
                HTML.Tag htmlTag = (HTML.Tag) attrSet.getAttribute(StyleConstants.NameAttribute);
                
                int child_elem_count = currElem.getElementCount();
                
                if(child_elem_count > 0)
                {
                    startTag(currElem);
                    
                    for(int i = 0; i < child_elem_count; i++)
                    {
                        Element childElem = paramElem.getElement(i);
            
                        traverse(childElem);
            
                    } // for(int i = 0; i < child_elem_count; i++)
                    
                    endTag(currElem);
                    
                } // if(child_elem_count > 0)
                else
                {
                    emptyTag(currElem);
                } // else 
            } // else
        } // else
        
    } // private void traverse(Element paramElem) throws IOException, BadLocationException
    
    /** Writes all the attributes in the attrSet, except for attrbutes with keys of HTML.Tag, StyleConstants or HTML.Attribute.ENDTAG.
     */
    protected void writeAttributes(AttributeSet attrSet) throws IOException
    {
        Enumeration attrNameEnum = attrSet.getAttributeNames();
        
        while(attrNameEnum.hasMoreElements())
        {
            Object key = attrNameEnum.nextElement();
            Object value = attrSet.getAttribute(key);
            
            // NOTE: HTML.Attribute.ENDTAG is an instance, not a class.
            if(!((key instanceof HTML.Tag) || (key instanceof StyleConstants) || (key == HTML.Attribute.ENDTAG)))
            {
                if(key == HTML.Attribute.SELECTED)
                    writeRaw(" selected");
                else if(key == HTML.Attribute.CHECKED)
                    writeRaw(" checked");
                else
                    writeRaw(" " + key + "=\"" + value + "\"");
            } // if(!((key instanceof HTML.Tag) || (key instanceof StyleConstants) || (key == HTML.Attribute.ENDTAG)))
        } // while(attrNameEnum.hasMoreElements())
        
    } // protected void writeAttributes(AttributeSet attrSet) throws IOException
    
    /** Writes out an empty tag.
     */
    protected void emptyTag(Element paramElem) throws IOException, BadLocationException
    {
        String elem_name = paramElem.getName();
        AttributeSet attrSet = paramElem.getAttributes();
        
        writeRaw("<" + elem_name);
        
        writeAttributes(attrSet);
            
        writeRaw(">");
        
        if(isBlockTag(attrSet))
        {
            writeRaw("</" + elem_name + ">");
        } // if(isBlockTag(attrSet))
        
    } // protected void emptyTag(Element paramElem) throws IOException, BadLocationException
    
    /** Determines if it is a block tag or not.
     */
    protected boolean isBlockTag(AttributeSet attrSet)
    {
        return ((HTML.Tag) attrSet.getAttribute(StyleConstants.NameAttribute)).isBlock();
    } // protected boolean isBlockTag(AttributeSet attrSet)
    
    /** Writes out a start tag. Synthesized elements are skipped.
     */
    protected void startTag(Element paramElem) throws IOException, BadLocationException
    {
        String elem_name = paramElem.getName();
        AttributeSet attrSet = paramElem.getAttributes();
        
        indent();
        writeRaw("<" + elem_name);
        writeAttributes(attrSet);
        writeRaw(">");
        writeLineSeparator();
        incrIndent();
        
    } // protected void startTag(Element paramElem) throws IOException, BadLocationException
    
    /** Writes out the contents of a textarea.
     */
    protected void textAreaContent(AttributeSet attrSet) throws IOException, BadLocationException
    {
        writeLineSeparator();
        indent();
        writeRaw("<textarea");
        writeAttributes(attrSet);
        writeRaw(">");
        writeLineSeparator();
        
        Document tempDocument = (Document) attrSet.getAttribute(StyleConstants.ModelAttribute);
        
        writeRaw(tempDocument.getText(0, tempDocument.getLength()));
        indent();
        writeRaw("</textarea>");
        
    } // protected void textAreaContent(AttributeSet attrSet) throws IOException, BadLocationException
    
    /** Writes out text, within the appropriate range if it is specified.
     */
    protected void text(Element paramElem) throws IOException, BadLocationException
    {
        int offset =  paramElem.getStartOffset();
        int len =  paramElem.getEndOffset() -  paramElem.getStartOffset();
        String txt_value = html_doc.getText(offset, len);
        
        writeContent(txt_value);
        
    } // protected void text(Element paramElem) throws IOException, BadLocationException
    
    /** Writes out the contents of a select element.
     */
    protected void selectContent(AttributeSet attrSet) throws IOException
    {
        writeLineSeparator();
        indent();
        writeRaw("<select");
        writeAttributes(attrSet);
        writeRaw(">");
        incrIndent();
        writeLineSeparator();
        
        ComboBoxModel comboBoxModel = (ComboBoxModel) attrSet.getAttribute(StyleConstants.ModelAttribute);
        
        for(int i = 0; i < comboBoxModel.getSize(); i++)
        {
            writeOption((Option) comboBoxModel.getElementAt(i));
        } // for(int i = 0; i < comboBoxModel.getSize(); i++)
        
        decrIndent();
        indent();
        writeRaw("</select>");
        
    } // protected void selectContent(AttributeSet attrSet) throws IOException
    
    /** Writes out the contents of an option element.
     */
    protected void writeOption(Option option) throws IOException
    {
        indent();
        writeRaw("<option");
        writeAttributes(option.getAttributes());
        writeRaw(">");
        
        writeContent(option.getLabel());
        
        writeRaw("</option>");
        writeLineSeparator();
        
    } // protected void writeOption(Option option) throws IOException
    
    /** Writes out an end tag.
     */
    protected void endTag(Element paramElem) throws IOException
    {
        String elem_name = paramElem.getName();
        
        decrIndent();
        
        indent();
        writeRaw("</" + elem_name + ">");
        
        writeLineSeparator();
        
    } // protected void endTag(Element paramElem) throws IOException
    
    /** Writes out the comment.
     */
    protected void comment(Element paramElem) throws IOException, BadLocationException
    {
        AttributeSet attrSet = paramElem.getAttributes();
        
        String comment_str = (String) attrSet.getAttribute(HTML.Attribute.COMMENT);
        
        writeRaw("<!--" + comment_str + "-->");
        
    } // protected void comment(Element paramElem) throws IOException, BadLocationException
    
    /** Determines if element is a synthesized Element or not.
     */
    protected boolean synthesizedElement(Element element)
    {
        AttributeSet attrSet = element.getAttributes();
        Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);
        
        if(tagType.equals(HTML.Tag.CONTENT) || tagType.equals(HTML.Tag.COMMENT) || tagType.equals(HTML.Tag.IMPLIED))
            return true;
        else
            return false;
        
    } // protected boolean synthesizedElement(Element element)
    
    /** Determines if StyleConstants.NameAttribute matches tag or not.
     */
    protected boolean matchNameAttribute(AttributeSet attrSet, HTML.Tag tag)
    {
        Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);
        
        if(tagType.equals(tag))
            return true;
        else
            return false;
        
    } // protected boolean matchNameAttribute(AttributeSet attrSet, HTML.Tag tag)
    
    /** Writes out an embedded tag.
     */
    protected void writeEmbeddedTags(AttributeSet attrSet) throws IOException
    {
        Enumeration attrNameEnum = attrSet.getAttributeNames();
        
        while(attrNameEnum.hasMoreElements())
        {
            Object key = attrNameEnum.nextElement();
            Object value = attrSet.getAttribute(key);
            
            if(key instanceof HTML.Tag)
            {
                if(!storeContentAttr.contains(key))
                {
                    writeRaw("<" + key);
                    writeAttributes((AttributeSet) value);
                    writeRaw(">");
                    storeContentAttr.add(key);
                } // if(!storeContentAttr.contains(key))
            } // if(key instanceof HTML.Tag)
        } // while(attrNameEnum.hasMoreElements())
        
    } // protected void writeEmbeddedTags(AttributeSet attrSet) throws IOException
    
    /** Closes out an unwanted embedded tag.
     */
    protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet) throws IOException
    {
        Object[] tag_arr = storeContentAttr.toArray();
        
        for(int i = 0; i < tag_arr.length; i++)
        {
            HTML.Tag key = (HTML.Tag) tag_arr[i];
            
            if(!attrSet.isDefined(key))
            {
                writeRaw("</" + key.toString() + ">");
                storeContentAttr.remove(key);
            } // if(!attrSet.isDefined(key))
        } // for(int i = 0; i < tag_arr.length; i++)
        
    } // protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet) throws IOException
    
    /** Writes out a line separator.
     */
    protected void writeLineSeparator() throws IOException
    {
        writeRaw(new_line_str);
    } // protected void writeLineSeparator() throws IOException
    
    /** Write to the writer. Character entites such as &lt;, &gt; are escaped appropriately.
     */
    protected void output(char[] chars, int off, int len) throws IOException
    {
        StringBuffer strBuffer = new StringBuffer();
        
        for(int i = 0; i < chars.length; i++)
        {
            if(isCharHtmlEntity(chars[i]))
                strBuffer.append(escapeCharHtmlEntity(chars[i]));
            else
                strBuffer.append(chars[i]);
        } // for(int i = 0; i < chars.length; i++)
        
        writeRaw(strBuffer.toString());
        
    } // protected void output(char[] chars, int off, int len) throws IOException
    
    private void writeRaw(String param_str) throws IOException
    {
        super.output(param_str.toCharArray(), 0, param_str.length());
    } // private void writeRaw(char[] chars, int off, int len) throws IOException
    
    private void writeContent(String param_str) throws IOException
    {
        char[] str_char_arr = param_str.toCharArray();
        
        if(hasHtmlEntity(param_str))
            output(str_char_arr, 0, str_char_arr.length);
        else
            super.output(str_char_arr, 0, str_char_arr.length);
        
    } // private void writeContent(String param_str) throws IOException
    
    // Use this for debugging.
    private void writeAllAttributes(AttributeSet attrSet) throws IOException
    {
        Enumeration attrNameEnum = attrSet.getAttributeNames();
        
        while(attrNameEnum.hasMoreElements())
        {
            Object key = attrNameEnum.nextElement();
            Object value = attrSet.getAttribute(key);
            
            writeRaw(" " + key + "=\"" + value + "\"");
            writeRaw(" " + key.getClass().toString() + "=\"" + value.getClass().toString() + "\"");
        } // while(attrNameEnum.hasMoreElements())
        
    } // private void writeAllAttributes(AttributeSet attrSet) throws IOException
    
    private boolean hasHtmlEntity(String param_str)
    {
        boolean ret_bool = false;
        
        for(int i = 0; i < html_entity_char_arr.length; i++)
        {
            if(param_str.indexOf(html_entity_char_arr[i]) != -1)
            {
                ret_bool = true;
                break;
            } // if(param_str.indexOf(html_entity_char_arr[i]) != -1)
        } // for(int i = 0; i < html_entity_char_arr.length; i++)
        
        return ret_bool;
    } // private boolean hasHtmlEntity(String param_str)
    
    private boolean isCharHtmlEntity(char param_char)
    {
        boolean ret_bool = false;
        
        for(int i = 0; i < html_entity_char_arr.length; i++)
        {
            if(param_char == html_entity_char_arr[i])
            {
                ret_bool = true;
                break;
            } // if(param_char == html_entity_char_arr[i])
        } // for(int i = 0; i < html_entity_char_arr.length; i++)
        
        return ret_bool;
    } // private boolean hasHtmlEntity(String param_str)
    
    private String escapeCharHtmlEntity(char param_char)
    {
        String ret_str = null;
        
        for(int i = 0; i < html_entity_char_arr.length; i++)
        {
            if(param_char == html_entity_char_arr[i])
            {
                ret_str = html_entity_escape_str_arr[i];
                break;
            } // if(param_char == html_entity_char_arr[i])
        } // for(int i = 0; i < html_entity_char_arr.length; i++)
        
        return ret_str;
    } // private String escapeCharHtmlEntity(char param_char)
    
} // public class HTMLWriter extends AbstractWriter

Reply via email to