alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (HTMLWriter.java)

This example Java source code file (HTMLWriter.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

attributeset, badlocationexception, element, enumeration, htmldocument, htmlwriter, ioexception, mutableattributeset, net, network, object, optioncomboboxmodel, segment, simpleattributeset, string, text, util, vector

The HTMLWriter.java Java example source code

/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package javax.swing.text.html;

import javax.swing.text.*;
import java.io.Writer;
import java.util.Stack;
import java.util.Enumeration;
import java.util.Vector;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;
import java.net.URL;

/**
 * This is a writer for HTMLDocuments.
 *
 * @author  Sunita Mani
 */


public class HTMLWriter extends AbstractWriter {
    /*
     * Stores all elements for which end tags have to
     * be emitted.
     */
    private Stack<Element> blockElementStack = new Stack();
    private boolean inContent = false;
    private boolean inPre = false;
    /** When inPre is true, this will indicate the end offset of the pre
     * element. */
    private int preEndOffset;
    private boolean inTextArea = false;
    private boolean newlineOutputed = false;
    private boolean completeDoc;

    /*
     * Stores all embedded tags. Embedded tags are tags that are
     * stored as attributes in other tags. Generally they're
     * character level attributes.  Examples include
     * <b>, <i>, <font>, and <a>.
     */
    private Vector<HTML.Tag> tags = new Vector(10);

    /**
     * Values for the tags.
     */
    private Vector<Object> tagValues = new Vector(10);

    /**
     * Used when writing out content.
     */
    private Segment segment;

    /*
     * This is used in closeOutUnwantedEmbeddedTags.
     */
    private Vector<HTML.Tag> tagsToRemove = new Vector(10);

    /**
     * Set to true after the head has been output.
     */
    private boolean wroteHead;

    /**
     * Set to true when entities (such as <) should be replaced.
     */
    private boolean replaceEntities;

    /**
     * Temporary buffer.
     */
    private char[] tempChars;


    /**
     * Creates a new HTMLWriter.
     *
     * @param w   a Writer
     * @param doc  an HTMLDocument
     *
     */
    public HTMLWriter(Writer w, HTMLDocument doc) {
        this(w, doc, 0, doc.getLength());
    }

    /**
     * Creates a new HTMLWriter.
     *
     * @param w  a Writer
     * @param doc an HTMLDocument
     * @param pos the document location from which to fetch the content
     * @param len the amount to write out
     */
    public HTMLWriter(Writer w, HTMLDocument doc, int pos, int len) {
        super(w, doc, pos, len);
        completeDoc = (pos == 0 && len == doc.getLength());
        setLineLength(80);
    }

    /**
     * Iterates over the
     * Element tree and controls the writing out of
     * all the tags and its attributes.
     *
     * @exception IOException on any I/O error
     * @exception BadLocationException if pos represents an invalid
     *            location within the document.
     *
     */
    public void write() throws IOException, BadLocationException {
        ElementIterator it = getElementIterator();
        Element current = null;
        Element next;

        wroteHead = false;
        setCurrentLineLength(0);
        replaceEntities = false;
        setCanWrapLines(false);
        if (segment == null) {
            segment = new Segment();
        }
        inPre = false;
        boolean forcedBody = false;
        while ((next = it.next()) != null) {
            if (!inRange(next)) {
                if (completeDoc && next.getAttributes().getAttribute(
                        StyleConstants.NameAttribute) == HTML.Tag.BODY) {
                    forcedBody = true;
                }
                else {
                    continue;
                }
            }
            if (current != null) {

                /*
                  if next is child of current increment indent
                */

                if (indentNeedsIncrementing(current, next)) {
                    incrIndent();
                } else if (current.getParentElement() != next.getParentElement()) {
                    /*
                       next and current are not siblings
                       so emit end tags for items on the stack until the
                       item on top of the stack, is the parent of the
                       next.
                    */
                    Element top = blockElementStack.peek();
                    while (top != next.getParentElement()) {
                        /*
                           pop() will return top.
                        */
                        blockElementStack.pop();
                        if (!synthesizedElement(top)) {
                            AttributeSet attrs = top.getAttributes();
                            if (!matchNameAttribute(attrs, HTML.Tag.PRE) &&
                                !isFormElementWithContent(attrs)) {
                                decrIndent();
                            }
                            endTag(top);
                        }
                        top = blockElementStack.peek();
                    }
                } else if (current.getParentElement() == next.getParentElement()) {
                    /*
                       if next and current are siblings the indent level
                       is correct.  But, we need to make sure that if current is
                       on the stack, we pop it off, and put out its end tag.
                    */
                    Element top = blockElementStack.peek();
                    if (top == current) {
                        blockElementStack.pop();
                        endTag(top);
                    }
                }
            }
            if (!next.isLeaf() || isFormElementWithContent(next.getAttributes())) {
                blockElementStack.push(next);
                startTag(next);
            } else {
                emptyTag(next);
            }
            current = next;
        }
        /* Emit all remaining end tags */

        /* A null parameter ensures that all embedded tags
           currently in the tags vector have their
           corresponding end tags written out.
        */
        closeOutUnwantedEmbeddedTags(null);

        if (forcedBody) {
            blockElementStack.pop();
            endTag(current);
        }
        while (!blockElementStack.empty()) {
            current = blockElementStack.pop();
            if (!synthesizedElement(current)) {
                AttributeSet attrs = current.getAttributes();
                if (!matchNameAttribute(attrs, HTML.Tag.PRE) &&
                              !isFormElementWithContent(attrs)) {
                    decrIndent();
                }
                endTag(current);
            }
        }

        if (completeDoc) {
            writeAdditionalComments();
        }

        segment.array = null;
    }


    /**
     * Writes out the attribute set.  Ignores all
     * attributes with a key of type HTML.Tag,
     * attributes with a key of type StyleConstants,
     * and attributes with a key of type
     * HTML.Attribute.ENDTAG.
     *
     * @param attr   an AttributeSet
     * @exception IOException on any I/O error
     *
     */
    protected void writeAttributes(AttributeSet attr) throws IOException {
        // translate css attributes to html
        convAttr.removeAttributes(convAttr);
        convertToHTML32(attr, convAttr);

        Enumeration names = convAttr.getAttributeNames();
        while (names.hasMoreElements()) {
            Object name = names.nextElement();
            if (name instanceof HTML.Tag ||
                name instanceof StyleConstants ||
                name == HTML.Attribute.ENDTAG) {
                continue;
            }
            write(" " + name + "=\"" + convAttr.getAttribute(name) + "\"");
        }
    }

    /**
     * Writes out all empty elements (all tags that have no
     * corresponding end tag).
     *
     * @param elem   an Element
     * @exception IOException on any I/O error
     * @exception BadLocationException if pos represents an invalid
     *            location within the document.
     */
    protected void emptyTag(Element elem) throws BadLocationException, IOException {

        if (!inContent && !inPre) {
            indentSmart();
        }

        AttributeSet attr = elem.getAttributes();
        closeOutUnwantedEmbeddedTags(attr);
        writeEmbeddedTags(attr);

        if (matchNameAttribute(attr, HTML.Tag.CONTENT)) {
            inContent = true;
            text(elem);
        } else if (matchNameAttribute(attr, HTML.Tag.COMMENT)) {
            comment(elem);
        }  else {
            boolean isBlock = isBlockTag(elem.getAttributes());
            if (inContent && isBlock ) {
                writeLineSeparator();
                indentSmart();
            }

            Object nameTag = (attr != null) ? attr.getAttribute
                              (StyleConstants.NameAttribute) : null;
            Object endTag = (attr != null) ? attr.getAttribute
                              (HTML.Attribute.ENDTAG) : null;

            boolean outputEndTag = false;
            // If an instance of an UNKNOWN Tag, or an instance of a
            // tag that is only visible during editing
            //
            if (nameTag != null && endTag != null &&
                (endTag instanceof String) &&
                endTag.equals("true")) {
                outputEndTag = true;
            }

            if (completeDoc && matchNameAttribute(attr, HTML.Tag.HEAD)) {
                if (outputEndTag) {
                    // Write out any styles.
                    writeStyles(((HTMLDocument)getDocument()).getStyleSheet());
                }
                wroteHead = true;
            }

            write('<');
            if (outputEndTag) {
                write('/');
            }
            write(elem.getName());
            writeAttributes(attr);
            write('>');
            if (matchNameAttribute(attr, HTML.Tag.TITLE) && !outputEndTag) {
                Document doc = elem.getDocument();
                String title = (String)doc.getProperty(Document.TitleProperty);
                write(title);
            } else if (!inContent || isBlock) {
                writeLineSeparator();
                if (isBlock && inContent) {
                    indentSmart();
                }
            }
        }
    }

    /**
     * Determines if the HTML.Tag associated with the
     * element is a block tag.
     *
     * @param attr  an AttributeSet
     * @return  true if tag is block tag, false otherwise.
     */
    protected boolean isBlockTag(AttributeSet attr) {
        Object o = attr.getAttribute(StyleConstants.NameAttribute);
        if (o instanceof HTML.Tag) {
            HTML.Tag name = (HTML.Tag) o;
            return name.isBlock();
        }
        return false;
    }


    /**
     * Writes out a start tag for the element.
     * Ignores all synthesized elements.
     *
     * @param elem   an Element
     * @exception IOException on any I/O error
     */
    protected void startTag(Element elem) throws IOException, BadLocationException {

        if (synthesizedElement(elem)) {
            return;
        }

        // Determine the name, as an HTML.Tag.
        AttributeSet attr = elem.getAttributes();
        Object nameAttribute = attr.getAttribute(StyleConstants.NameAttribute);
        HTML.Tag name;
        if (nameAttribute instanceof HTML.Tag) {
            name = (HTML.Tag)nameAttribute;
        }
        else {
            name = null;
        }

        if (name == HTML.Tag.PRE) {
            inPre = true;
            preEndOffset = elem.getEndOffset();
        }

        // write out end tags for item on stack
        closeOutUnwantedEmbeddedTags(attr);

        if (inContent) {
            writeLineSeparator();
            inContent = false;
            newlineOutputed = false;
        }

        if (completeDoc && name == HTML.Tag.BODY && !wroteHead) {
            // If the head has not been output, output it and the styles.
            wroteHead = true;
            indentSmart();
            write("<head>");
            writeLineSeparator();
            incrIndent();
            writeStyles(((HTMLDocument)getDocument()).getStyleSheet());
            decrIndent();
            writeLineSeparator();
            indentSmart();
            write("</head>");
            writeLineSeparator();
        }

        indentSmart();
        write('<');
        write(elem.getName());
        writeAttributes(attr);
        write('>');
        if (name != HTML.Tag.PRE) {
            writeLineSeparator();
        }

        if (name == HTML.Tag.TEXTAREA) {
            textAreaContent(elem.getAttributes());
        } else if (name == HTML.Tag.SELECT) {
            selectContent(elem.getAttributes());
        } else if (completeDoc && name == HTML.Tag.BODY) {
            // Write out the maps, which is not stored as Elements in
            // the Document.
            writeMaps(((HTMLDocument)getDocument()).getMaps());
        }
        else if (name == HTML.Tag.HEAD) {
            HTMLDocument document = (HTMLDocument)getDocument();
            wroteHead = true;
            incrIndent();
            writeStyles(document.getStyleSheet());
            if (document.hasBaseTag()) {
                indentSmart();
                write("<base href=\"" + document.getBase() + "\">");
                writeLineSeparator();
            }
            decrIndent();
        }

    }


    /**
     * Writes out text that is contained in a TEXTAREA form
     * element.
     *
     * @param attr  an AttributeSet
     * @exception IOException on any I/O error
     * @exception BadLocationException if pos represents an invalid
     *            location within the document.
     */
    protected void textAreaContent(AttributeSet attr) throws BadLocationException, IOException {
        Document doc = (Document)attr.getAttribute(StyleConstants.ModelAttribute);
        if (doc != null && doc.getLength() > 0) {
            if (segment == null) {
                segment = new Segment();
            }
            doc.getText(0, doc.getLength(), segment);
            if (segment.count > 0) {
                inTextArea = true;
                incrIndent();
                indentSmart();
                setCanWrapLines(true);
                replaceEntities = true;
                write(segment.array, segment.offset, segment.count);
                replaceEntities = false;
                setCanWrapLines(false);
                writeLineSeparator();
                inTextArea = false;
                decrIndent();
            }
        }
    }


    /**
     * Writes out text.  If a range is specified when the constructor
     * is invoked, then only the appropriate range of text is written
     * out.
     *
     * @param elem   an Element
     * @exception IOException on any I/O error
     * @exception BadLocationException if pos represents an invalid
     *            location within the document.
     */
    protected void text(Element elem) throws BadLocationException, IOException {
        int start = Math.max(getStartOffset(), elem.getStartOffset());
        int end = Math.min(getEndOffset(), elem.getEndOffset());
        if (start < end) {
            if (segment == null) {
                segment = new Segment();
            }
            getDocument().getText(start, end - start, segment);
            newlineOutputed = false;
            if (segment.count > 0) {
                if (segment.array[segment.offset + segment.count - 1] == '\n'){
                    newlineOutputed = true;
                }
                if (inPre && end == preEndOffset) {
                    if (segment.count > 1) {
                        segment.count--;
                    }
                    else {
                        return;
                    }
                }
                replaceEntities = true;
                setCanWrapLines(!inPre);
                write(segment.array, segment.offset, segment.count);
                setCanWrapLines(false);
                replaceEntities = false;
            }
        }
    }

    /**
     * Writes out the content of the SELECT form element.
     *
     * @param attr the AttributeSet associated with the form element
     * @exception IOException on any I/O error
     */
    protected void selectContent(AttributeSet attr) throws IOException {
        Object model = attr.getAttribute(StyleConstants.ModelAttribute);
        incrIndent();
        if (model instanceof OptionListModel) {
            OptionListModel<Option> listModel = (OptionListModel
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.