Source Code Cross Referenced for MinimalHTMLWriter.java in  » 6.0-JDK-Core » swing » javax » swing » text » html » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing.text.html 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1998-1999 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package javax.swing.text.html;
027
028        import java.io.Writer;
029        import java.io.IOException;
030        import java.util.*;
031        import java.awt.Color;
032        import javax.swing.text.*;
033
034        /**
035         * MinimalHTMLWriter is a fallback writer used by the
036         * HTMLEditorKit to write out HTML for a document that
037         * is a not produced by the EditorKit.
038         *
039         * The format for the document is:
040         * <pre>
041         * &lt;html&gt;
042         *   &lt;head&gt;
043         *     &lt;style&gt;
044         *        &lt;!-- list of named styles
045         *         p.normal {
046         *            font-family: SansSerif;
047         *	      margin-height: 0;
048         *	      font-size: 14
049         *	   }
050         *        --&gt;
051         *      &lt;/style&gt;
052         *   &lt;/head&gt;
053         *   &lt;body&gt;
054         *    &lt;p style=normal&gt;
055         *        <b>Bold, italic, and underline attributes
056         *        of the run are emitted as HTML tags.
057         *        The remaining attributes are emitted as
058         *        part of the style attribute of a &lt;span&gt; tag.
059         *        The syntax is similar to inline styles.</b>
060         *    &lt;/p&gt;
061         *   &lt;/body&gt;
062         * &lt;/html&gt;
063         * </pre>
064         *
065         * @author Sunita Mani
066         * @version 1.21, 05/05/07
067         */
068
069        public class MinimalHTMLWriter extends AbstractWriter {
070
071            /**
072             * These static finals are used to
073             * tweak and query the fontMask about which
074             * of these tags need to be generated or
075             * terminated.
076             */
077            private static final int BOLD = 0x01;
078            private static final int ITALIC = 0x02;
079            private static final int UNDERLINE = 0x04;
080
081            // Used to map StyleConstants to CSS.
082            private static final CSS css = new CSS();
083
084            private int fontMask = 0;
085
086            int startOffset = 0;
087            int endOffset = 0;
088
089            /**
090             * Stores the attributes of the previous run.
091             * Used to compare with the current run's
092             * attributeset.  If identical, then a
093             * &lt;span&gt; tag is not emitted.
094             */
095            private AttributeSet fontAttributes;
096
097            /**
098             * Maps from style name as held by the Document, to the archived
099             * style name (style name written out). These may differ.
100             */
101            private Hashtable styleNameMapping;
102
103            /**
104             * Creates a new MinimalHTMLWriter.
105             *
106             * @param w  Writer
107             * @param doc StyledDocument
108             *
109             */
110            public MinimalHTMLWriter(Writer w, StyledDocument doc) {
111                super (w, doc);
112            }
113
114            /**
115             * Creates a new MinimalHTMLWriter.
116             *
117             * @param w  Writer
118             * @param doc StyledDocument
119             * @param pos The location in the document to fetch the
120             *   content.
121             * @param len The amount to write out.
122             *
123             */
124            public MinimalHTMLWriter(Writer w, StyledDocument doc, int pos,
125                    int len) {
126                super (w, doc, pos, len);
127            }
128
129            /**
130             * Generates HTML output
131             * from a StyledDocument.
132             *
133             * @exception IOException on any I/O error
134             * @exception BadLocationException if pos represents an invalid
135             *            location within the document.
136             *
137             */
138            public void write() throws IOException, BadLocationException {
139                styleNameMapping = new Hashtable();
140                writeStartTag("<html>");
141                writeHeader();
142                writeBody();
143                writeEndTag("</html>");
144            }
145
146            /**
147             * Writes out all the attributes for the
148             * following types:
149             *  StyleConstants.ParagraphConstants,
150             *  StyleConstants.CharacterConstants,
151             *  StyleConstants.FontConstants,
152             *  StyleConstants.ColorConstants.
153             * The attribute name and value are separated by a colon.
154             * Each pair is separated by a semicolon.
155             *
156             * @exception IOException on any I/O error
157             */
158            protected void writeAttributes(AttributeSet attr)
159                    throws IOException {
160                Enumeration attributeNames = attr.getAttributeNames();
161                while (attributeNames.hasMoreElements()) {
162                    Object name = attributeNames.nextElement();
163                    if ((name instanceof  StyleConstants.ParagraphConstants)
164                            || (name instanceof  StyleConstants.CharacterConstants)
165                            || (name instanceof  StyleConstants.FontConstants)
166                            || (name instanceof  StyleConstants.ColorConstants)) {
167                        indent();
168                        write(name.toString());
169                        write(':');
170                        write(css.styleConstantsValueToCSSValue(
171                                (StyleConstants) name, attr.getAttribute(name))
172                                .toString());
173                        write(';');
174                        write(NEWLINE);
175                    }
176                }
177            }
178
179            /**
180             * Writes out text.
181             *
182             * @exception IOException on any I/O error
183             */
184            protected void text(Element elem) throws IOException,
185                    BadLocationException {
186                String contentStr = getText(elem);
187                if ((contentStr.length() > 0)
188                        && (contentStr.charAt(contentStr.length() - 1) == NEWLINE)) {
189                    contentStr = contentStr.substring(0,
190                            contentStr.length() - 1);
191                }
192                if (contentStr.length() > 0) {
193                    write(contentStr);
194                }
195            }
196
197            /**
198             * Writes out a start tag appropriately
199             * indented.  Also increments the indent level.
200             *
201             * @exception IOException on any I/O error
202             */
203            protected void writeStartTag(String tag) throws IOException {
204                indent();
205                write(tag);
206                write(NEWLINE);
207                incrIndent();
208            }
209
210            /**
211             * Writes out an end tag appropriately
212             * indented.  Also decrements the indent level.
213             *
214             * @exception IOException on any I/O error
215             */
216            protected void writeEndTag(String endTag) throws IOException {
217                decrIndent();
218                indent();
219                write(endTag);
220                write(NEWLINE);
221            }
222
223            /**
224             * Writes out the &lt;head&gt; and &lt;style&gt;
225             * tags, and then invokes writeStyles() to write
226             * out all the named styles as the content of the
227             * &lt;style&gt; tag.  The content is surrounded by
228             * valid HTML comment markers to ensure that the
229             * document is viewable in applications/browsers
230             * that do not support the tag.
231             *
232             * @exception IOException on any I/O error
233             */
234            protected void writeHeader() throws IOException {
235                writeStartTag("<head>");
236                writeStartTag("<style>");
237                writeStartTag("<!--");
238                writeStyles();
239                writeEndTag("-->");
240                writeEndTag("</style>");
241                writeEndTag("</head>");
242            }
243
244            /**
245             * Writes out all the named styles as the
246             * content of the &lt;style&gt; tag.
247             *
248             * @exception IOException on any I/O error
249             */
250            protected void writeStyles() throws IOException {
251                /*
252                 *  Access to DefaultStyledDocument done to workaround
253                 *  a missing API in styled document to access the
254                 *  stylenames.
255                 */
256                DefaultStyledDocument styledDoc = ((DefaultStyledDocument) getDocument());
257                Enumeration styleNames = styledDoc.getStyleNames();
258
259                while (styleNames.hasMoreElements()) {
260                    Style s = styledDoc.getStyle((String) styleNames
261                            .nextElement());
262
263                    /** PENDING: Once the name attribute is removed
264                    from the list we check check for 0. **/
265                    if (s.getAttributeCount() == 1
266                            && s.isDefined(StyleConstants.NameAttribute)) {
267                        continue;
268                    }
269                    indent();
270                    write("p." + addStyleName(s.getName()));
271                    write(" {\n");
272                    incrIndent();
273                    writeAttributes(s);
274                    decrIndent();
275                    indent();
276                    write("}\n");
277                }
278            }
279
280            /**
281             * Iterates over the elements in the document
282             * and processes elements based on whether they are
283             * branch elements or leaf elements.  This method specially handles
284             * leaf elements that are text.
285             *
286             * @exception IOException on any I/O error
287             */
288            protected void writeBody() throws IOException, BadLocationException {
289                ElementIterator it = getElementIterator();
290
291                /*
292                  This will be a section element for a styled document.
293                  We represent this element in HTML as the body tags.
294                  Therefore we ignore it.
295                 */
296                it.current();
297
298                Element next = null;
299
300                writeStartTag("<body>");
301
302                boolean inContent = false;
303
304                while ((next = it.next()) != null) {
305                    if (!inRange(next)) {
306                        continue;
307                    }
308                    if (next instanceof  AbstractDocument.BranchElement) {
309                        if (inContent) {
310                            writeEndParagraph();
311                            inContent = false;
312                            fontMask = 0;
313                        }
314                        writeStartParagraph(next);
315                    } else if (isText(next)) {
316                        writeContent(next, !inContent);
317                        inContent = true;
318                    } else {
319                        writeLeaf(next);
320                        inContent = true;
321                    }
322                }
323                if (inContent) {
324                    writeEndParagraph();
325                }
326                writeEndTag("</body>");
327            }
328
329            /**
330             * Emits an end tag for a &lt;p&gt;
331             * tag.  Before writing out the tag, this method ensures
332             * that all other tags that have been opened are
333             * appropriately closed off.
334             *
335             * @exception IOException on any I/O error
336             */
337            protected void writeEndParagraph() throws IOException {
338                writeEndMask(fontMask);
339                if (inFontTag()) {
340                    endSpanTag();
341                } else {
342                    write(NEWLINE);
343                }
344                writeEndTag("</p>");
345            }
346
347            /**
348             * Emits the start tag for a paragraph. If
349             * the paragraph has a named style associated with it,
350             * then this method also generates a class attribute for the
351             * &lt;p&gt; tag and sets its value to be the name of the
352             * style.
353             *
354             * @exception IOException on any I/O error
355             */
356            protected void writeStartParagraph(Element elem) throws IOException {
357                AttributeSet attr = elem.getAttributes();
358                Object resolveAttr = attr
359                        .getAttribute(StyleConstants.ResolveAttribute);
360                if (resolveAttr instanceof  StyleContext.NamedStyle) {
361                    writeStartTag("<p class="
362                            + mapStyleName(((StyleContext.NamedStyle) resolveAttr)
363                                    .getName()) + ">");
364                } else {
365                    writeStartTag("<p>");
366                }
367            }
368
369            /**
370             * Responsible for writing out other non-text leaf
371             * elements.
372             *
373             * @exception IOException on any I/O error
374             */
375            protected void writeLeaf(Element elem) throws IOException {
376                indent();
377                if (elem.getName() == StyleConstants.IconElementName) {
378                    writeImage(elem);
379                } else if (elem.getName() == StyleConstants.ComponentElementName) {
380                    writeComponent(elem);
381                }
382            }
383
384            /**
385             * Responsible for handling Icon Elements;
386             * deliberately unimplemented.  How to implement this method is 
387             * an issue of policy.  For example, if you're generating
388             * an &lt;img&gt; tag, how should you 
389             * represent the src attribute (the location of the image)?
390             * In certain cases it could be a URL, in others it could
391             * be read from a stream.
392             *
393             * @param elem element of type StyleConstants.IconElementName
394             */
395            protected void writeImage(Element elem) throws IOException {
396            }
397
398            /**
399             * Responsible for handling Component Elements;  
400             * deliberately unimplemented.
401             * How this method is implemented is a matter of policy.
402             */
403            protected void writeComponent(Element elem) throws IOException {
404            }
405
406            /**
407             * Returns true if the element is a text element.
408             *
409             */
410            protected boolean isText(Element elem) {
411                return (elem.getName() == AbstractDocument.ContentElementName);
412            }
413
414            /**
415             * Writes out the attribute set
416             * in an HTML-compliant manner.
417             *
418             * @exception IOException on any I/O error
419             * @exception BadLocationException if pos represents an invalid
420             *            location within the document.
421             */
422            protected void writeContent(Element elem, boolean needsIndenting)
423                    throws IOException, BadLocationException {
424
425                AttributeSet attr = elem.getAttributes();
426                writeNonHTMLAttributes(attr);
427                if (needsIndenting) {
428                    indent();
429                }
430                writeHTMLTags(attr);
431                text(elem);
432            }
433
434            /**
435             * Generates
436             * bold &lt;b&gt;, italic &lt;i&gt;, and &lt;u&gt; tags for the
437             * text based on its attribute settings.
438             *
439             * @exception IOException on any I/O error
440             */
441
442            protected void writeHTMLTags(AttributeSet attr) throws IOException {
443
444                int oldMask = fontMask;
445                setFontMask(attr);
446
447                int endMask = 0;
448                int startMask = 0;
449                if ((oldMask & BOLD) != 0) {
450                    if ((fontMask & BOLD) == 0) {
451                        endMask |= BOLD;
452                    }
453                } else if ((fontMask & BOLD) != 0) {
454                    startMask |= BOLD;
455                }
456
457                if ((oldMask & ITALIC) != 0) {
458                    if ((fontMask & ITALIC) == 0) {
459                        endMask |= ITALIC;
460                    }
461                } else if ((fontMask & ITALIC) != 0) {
462                    startMask |= ITALIC;
463                }
464
465                if ((oldMask & UNDERLINE) != 0) {
466                    if ((fontMask & UNDERLINE) == 0) {
467                        endMask |= UNDERLINE;
468                    }
469                } else if ((fontMask & UNDERLINE) != 0) {
470                    startMask |= UNDERLINE;
471                }
472                writeEndMask(endMask);
473                writeStartMask(startMask);
474            }
475
476            /**
477             * Tweaks the appropriate bits of fontMask
478             * to reflect whether the text is to be displayed in
479             * bold, italic, and/or with an underline.
480             *
481             */
482            private void setFontMask(AttributeSet attr) {
483                if (StyleConstants.isBold(attr)) {
484                    fontMask |= BOLD;
485                }
486
487                if (StyleConstants.isItalic(attr)) {
488                    fontMask |= ITALIC;
489                }
490
491                if (StyleConstants.isUnderline(attr)) {
492                    fontMask |= UNDERLINE;
493                }
494            }
495
496            /**
497             * Writes out start tags &lt;u&gt;, &lt;i&gt;, and &lt;b&gt; based on
498             * the mask settings.
499             *
500             * @exception IOException on any I/O error
501             */
502            private void writeStartMask(int mask) throws IOException {
503                if (mask != 0) {
504                    if ((mask & UNDERLINE) != 0) {
505                        write("<u>");
506                    }
507                    if ((mask & ITALIC) != 0) {
508                        write("<i>");
509                    }
510                    if ((mask & BOLD) != 0) {
511                        write("<b>");
512                    }
513                }
514            }
515
516            /**
517             * Writes out end tags for &lt;u&gt;, &lt;i&gt;, and &lt;b&gt; based on
518             * the mask settings.
519             *
520             * @exception IOException on any I/O error
521             */
522            private void writeEndMask(int mask) throws IOException {
523                if (mask != 0) {
524                    if ((mask & BOLD) != 0) {
525                        write("</b>");
526                    }
527                    if ((mask & ITALIC) != 0) {
528                        write("</i>");
529                    }
530                    if ((mask & UNDERLINE) != 0) {
531                        write("</u>");
532                    }
533                }
534            }
535
536            /**
537             * Writes out the remaining
538             * character-level attributes (attributes other than bold,
539             * italic, and underline) in an HTML-compliant way.  Given that
540             * attributes such as font family and font size have no direct
541             * mapping to HTML tags, a &lt;span&gt; tag is generated and its
542             * style attribute is set to contain the list of remaining
543             * attributes just like inline styles.
544             *
545             * @exception IOException on any I/O error
546             */
547            protected void writeNonHTMLAttributes(AttributeSet attr)
548                    throws IOException {
549
550                String style = "";
551                String separator = "; ";
552
553                if (inFontTag() && fontAttributes.isEqual(attr)) {
554                    return;
555                }
556
557                boolean first = true;
558                Color color = (Color) attr
559                        .getAttribute(StyleConstants.Foreground);
560                if (color != null) {
561                    style += "color: "
562                            + css.styleConstantsValueToCSSValue(
563                                    (StyleConstants) StyleConstants.Foreground,
564                                    color);
565                    first = false;
566                }
567                Integer size = (Integer) attr
568                        .getAttribute(StyleConstants.FontSize);
569                if (size != null) {
570                    if (!first) {
571                        style += separator;
572                    }
573                    style += "font-size: " + size.intValue() + "pt";
574                    first = false;
575                }
576
577                String family = (String) attr
578                        .getAttribute(StyleConstants.FontFamily);
579                if (family != null) {
580                    if (!first) {
581                        style += separator;
582                    }
583                    style += "font-family: " + family;
584                    first = false;
585                }
586
587                if (style.length() > 0) {
588                    if (fontMask != 0) {
589                        writeEndMask(fontMask);
590                        fontMask = 0;
591                    }
592                    startSpanTag(style);
593                    fontAttributes = attr;
594                } else if (fontAttributes != null) {
595                    writeEndMask(fontMask);
596                    fontMask = 0;
597                    endSpanTag();
598                }
599            }
600
601            /**
602             * Returns true if we are currently in a &lt;font&gt; tag.
603             */
604            protected boolean inFontTag() {
605                return (fontAttributes != null);
606            }
607
608            /**
609             * This is no longer used, instead &lt;span&gt; will be written out.
610             * <p>
611             * Writes out an end tag for the &lt;font&gt; tag.
612             *
613             * @exception IOException on any I/O error
614             */
615            protected void endFontTag() throws IOException {
616                write(NEWLINE);
617                writeEndTag("</font>");
618                fontAttributes = null;
619            }
620
621            /**
622             * This is no longer used, instead &lt;span&gt; will be written out.
623             * <p>
624             * Writes out a start tag for the &lt;font&gt; tag.
625             * Because font tags cannot be nested, 
626             * this method closes out
627             * any enclosing font tag before writing out a
628             * new start tag.
629             *
630             * @exception IOException on any I/O error
631             */
632            protected void startFontTag(String style) throws IOException {
633                boolean callIndent = false;
634                if (inFontTag()) {
635                    endFontTag();
636                    callIndent = true;
637                }
638                writeStartTag("<font style=\"" + style + "\">");
639                if (callIndent) {
640                    indent();
641                }
642            }
643
644            /**
645             * Writes out a start tag for the &lt;font&gt; tag.
646             * Because font tags cannot be nested, 
647             * this method closes out
648             * any enclosing font tag before writing out a
649             * new start tag.
650             *
651             * @exception IOException on any I/O error
652             */
653            private void startSpanTag(String style) throws IOException {
654                boolean callIndent = false;
655                if (inFontTag()) {
656                    endSpanTag();
657                    callIndent = true;
658                }
659                writeStartTag("<span style=\"" + style + "\">");
660                if (callIndent) {
661                    indent();
662                }
663            }
664
665            /**
666             * Writes out an end tag for the &lt;span&gt; tag.
667             *
668             * @exception IOException on any I/O error
669             */
670            private void endSpanTag() throws IOException {
671                write(NEWLINE);
672                writeEndTag("</span>");
673                fontAttributes = null;
674            }
675
676            /**
677             * Adds the style named <code>style</code> to the style mapping. This
678             * returns the name that should be used when outputting. CSS does not
679             * allow the full Unicode set to be used as a style name.
680             */
681            private String addStyleName(String style) {
682                if (styleNameMapping == null) {
683                    return style;
684                }
685                StringBuffer sb = null;
686                for (int counter = style.length() - 1; counter >= 0; counter--) {
687                    if (!isValidCharacter(style.charAt(counter))) {
688                        if (sb == null) {
689                            sb = new StringBuffer(style);
690                        }
691                        sb.setCharAt(counter, 'a');
692                    }
693                }
694                String mappedName = (sb != null) ? sb.toString() : style;
695                while (styleNameMapping.get(mappedName) != null) {
696                    mappedName = mappedName + 'x';
697                }
698                styleNameMapping.put(style, mappedName);
699                return mappedName;
700            }
701
702            /**
703             * Returns the mapped style name corresponding to <code>style</code>.
704             */
705            private String mapStyleName(String style) {
706                if (styleNameMapping == null) {
707                    return style;
708                }
709                String retValue = (String) styleNameMapping.get(style);
710                return (retValue == null) ? style : retValue;
711            }
712
713            private boolean isValidCharacter(char character) {
714                return ((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z'));
715            }
716        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.