Coverage Report - org.apache.maven.doxia.module.xdoc.XdocSink
 
Classes in this File Line Coverage Branch Coverage Complexity
XdocSink
97%
135/139
92%
48/52
2,08
 
 1  
 package org.apache.maven.doxia.module.xdoc;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.Writer;
 23  
 
 24  
 import javax.swing.text.MutableAttributeSet;
 25  
 import javax.swing.text.html.HTML.Attribute;
 26  
 
 27  
 import org.apache.maven.doxia.sink.SinkEventAttributeSet;
 28  
 import org.apache.maven.doxia.sink.SinkEventAttributes;
 29  
 import org.apache.maven.doxia.sink.SinkUtils;
 30  
 import org.apache.maven.doxia.sink.XhtmlBaseSink;
 31  
 import org.apache.maven.doxia.util.HtmlTools;
 32  
 
 33  
 import org.codehaus.plexus.util.StringUtils;
 34  
 
 35  
 /**
 36  
  * <a href="http://maven.apache.org/doxia/references/xdoc-format.html">Xdoc</a> Sink implementation.
 37  
  * <br/>
 38  
  * It uses the Xdoc XSD <a href="http://maven.apache.org/xsd/xdoc-2.0.xsd">
 39  
  * http://maven.apache.org/xsd/xdoc-2.0.xsd</a>.
 40  
  *
 41  
  * @author <a href="mailto:james@jamestaylor.org">James Taylor</a>
 42  
  * @version $Id: XdocSink.java 926772 2010-03-23 20:52:37Z ltheussl $
 43  
  * @since 1.0
 44  
  */
 45  
 public class XdocSink
 46  
     extends XhtmlBaseSink
 47  
     implements XdocMarkup
 48  
 {
 49  
     // ----------------------------------------------------------------------
 50  
     // Instance fields
 51  
     // ----------------------------------------------------------------------
 52  
 
 53  
     /** An indication on if we're inside a box (verbatim). */
 54  
     private boolean boxedFlag;
 55  
 
 56  
     private String encoding;
 57  
 
 58  
     private String languageId;
 59  
 
 60  
     // ----------------------------------------------------------------------
 61  
     // Constructors
 62  
     // ----------------------------------------------------------------------
 63  
 
 64  
     /**
 65  
      * Constructor, initialize the Writer.
 66  
      *
 67  
      * @param writer not null writer to write the result. <b>Should</b> be an UTF-8 Writer.
 68  
      * You could use <code>newXmlWriter</code> methods from {@link org.codehaus.plexus.util.WriterFactory}.
 69  
      */
 70  
     protected XdocSink( Writer writer )
 71  
     {
 72  150
         super( writer );
 73  150
     }
 74  
 
 75  
     /**
 76  
      * Constructor, initialize the Writer and tells which encoding is used.
 77  
      *
 78  
      * @param writer not null writer to write the result.
 79  
      * @param encoding the encoding used, that should be written to the generated HTML content
 80  
      * if not <code>null</code>.
 81  
      * @since 1.1
 82  
      */
 83  
     protected XdocSink( Writer writer, String encoding )
 84  
     {
 85  136
         this( writer );
 86  136
         this.encoding = encoding;
 87  136
     }
 88  
 
 89  
     /**
 90  
      * Constructor, initialize the Writer and tells which encoding and languageId are used.
 91  
      *
 92  
      * @param writer not null writer to write the result.
 93  
      * @param encoding the encoding used, that should be written to the generated HTML content
 94  
      * if not <code>null</code>.
 95  
      * @param languageId language identifier for the root element as defined by
 96  
      * <a href="ftp://ftp.isi.edu/in-notes/bcp/bcp47.txt">IETF BCP 47</a>, Tags for the Identification of Languages;
 97  
      * in addition, the empty string may be specified.
 98  
      * @since 1.1
 99  
      */
 100  
     protected XdocSink( Writer writer, String encoding, String languageId )
 101  
     {
 102  68
         this( writer, encoding );
 103  
 
 104  68
         this.languageId = languageId;
 105  68
     }
 106  
 
 107  
     // ----------------------------------------------------------------------
 108  
     // Public protected methods
 109  
     // ----------------------------------------------------------------------
 110  
 
 111  
     /** {@inheritDoc} */
 112  
     protected void init()
 113  
     {
 114  454
         super.init();
 115  
 
 116  454
         boxedFlag = false;
 117  454
     }
 118  
 
 119  
     /**
 120  
      * {@inheritDoc}
 121  
      * @see #head(org.apache.maven.doxia.sink.SinkEventAttributes)
 122  
      */
 123  
     public void head()
 124  
     {
 125  10
         head( null );
 126  10
     }
 127  
 
 128  
     /**
 129  
      * {@inheritDoc}
 130  
      * @see XdocMarkup#DOCUMENT_TAG
 131  
      * @see XdocMarkup#PROPERTIES_TAG
 132  
      */
 133  
     public void head( SinkEventAttributes attributes )
 134  
     {
 135  14
         init();
 136  
 
 137  14
         setHeadFlag( true );
 138  
 
 139  14
         write( "<?xml version=\"1.0\"" );
 140  14
         if ( encoding != null )
 141  
         {
 142  8
             write( " encoding=\"" + encoding + "\"" );
 143  
         }
 144  14
         write( "?>" );
 145  
 
 146  14
         MutableAttributeSet atts = new SinkEventAttributeSet();
 147  14
         atts.addAttribute( "xmlns", XDOC_NAMESPACE );
 148  14
         atts.addAttribute( "xmlns:xsi", XML_NAMESPACE );
 149  14
         atts.addAttribute( "xsi:schemaLocation", XDOC_NAMESPACE + " " + XDOC_SYSTEM_ID );
 150  
 
 151  14
         if ( languageId != null )
 152  
         {
 153  4
             atts.addAttribute( Attribute.LANG.toString(), languageId );
 154  4
             atts.addAttribute( "xml:lang", languageId );
 155  
         }
 156  
 
 157  14
         if ( attributes != null )
 158  
         {
 159  4
             atts.addAttributes( attributes );
 160  
         }
 161  
 
 162  14
         writeStartTag( DOCUMENT_TAG, atts );
 163  
 
 164  14
         writeStartTag( PROPERTIES_TAG );
 165  14
     }
 166  
 
 167  
     /**
 168  
      * {@inheritDoc}
 169  
      * @see XdocMarkup#DOCUMENT_TAG
 170  
      * @see XdocMarkup#PROPERTIES_TAG
 171  
      */
 172  
     public void head_()
 173  
     {
 174  14
         setHeadFlag( false );
 175  
 
 176  14
         writeEndTag( PROPERTIES_TAG );
 177  14
     }
 178  
 
 179  
     /**
 180  
      * {@inheritDoc}
 181  
      * @see javax.swing.text.html.HTML.Tag#TITLE
 182  
      */
 183  
     public void title()
 184  
     {
 185  14
         writeStartTag( TITLE );
 186  14
     }
 187  
 
 188  
     /**
 189  
      * {@inheritDoc}
 190  
      * @see javax.swing.text.html.HTML.Tag#TITLE
 191  
      */
 192  
     public void title_()
 193  
     {
 194  14
         content( getTextBuffer().toString() );
 195  
 
 196  14
         writeEndTag( TITLE );
 197  
 
 198  14
         resetTextBuffer();
 199  14
     }
 200  
 
 201  
     /**
 202  
      * {@inheritDoc}
 203  
      * @see XdocMarkup#AUTHOR_TAG
 204  
      */
 205  
     public void author_()
 206  
     {
 207  14
         if ( getTextBuffer().length() > 0 )
 208  
         {
 209  10
             writeStartTag( AUTHOR_TAG );
 210  10
             String text = HtmlTools.escapeHTML( getTextBuffer().toString() );
 211  
             // hack: un-escape numerical entities that have been escaped above
 212  
             // note that numerical entities should really be written as one unicode character in the first place
 213  10
             text = StringUtils.replace( text, "&amp;#", "&#" );
 214  10
             write( text );
 215  10
             writeEndTag( AUTHOR_TAG );
 216  10
             resetTextBuffer();
 217  
         }
 218  14
     }
 219  
 
 220  
     /**
 221  
      * {@inheritDoc}
 222  
      * @see XdocMarkup#DATE_TAG
 223  
      */
 224  
     public void date_()
 225  
     {
 226  10
         if ( getTextBuffer().length() > 0 )
 227  
         {
 228  6
             writeStartTag( DATE_TAG );
 229  6
             content( getTextBuffer().toString() );
 230  6
             writeEndTag( DATE_TAG );
 231  6
             resetTextBuffer();
 232  
         }
 233  10
     }
 234  
 
 235  
     /**
 236  
      * {@inheritDoc}
 237  
      * @see #body(org.apache.maven.doxia.sink.SinkEventAttributes)
 238  
      */
 239  
     public void body()
 240  
     {
 241  10
        body( null );
 242  10
     }
 243  
 
 244  
     /**
 245  
      * {@inheritDoc}
 246  
      * @see javax.swing.text.html.HTML.Tag#BODY
 247  
      */
 248  
     public void body( SinkEventAttributes attributes )
 249  
     {
 250  14
         writeStartTag( BODY, attributes );
 251  14
     }
 252  
 
 253  
     /**
 254  
      * {@inheritDoc}
 255  
      * @see javax.swing.text.html.HTML.Tag#BODY
 256  
      * @see XdocMarkup#DOCUMENT_TAG
 257  
      */
 258  
     public void body_()
 259  
     {
 260  14
         writeEndTag( BODY );
 261  
 
 262  14
         writeEndTag( DOCUMENT_TAG );
 263  
 
 264  14
         flush();
 265  
 
 266  14
         init();
 267  14
     }
 268  
 
 269  
     // ----------------------------------------------------------------------
 270  
     // Sections
 271  
     // ----------------------------------------------------------------------
 272  
 
 273  
     /**
 274  
      * {@inheritDoc}
 275  
      *
 276  
      * Starts a section.
 277  
      * @see XdocMarkup#SECTION_TAG
 278  
      * @see XdocMarkup#SUBSECTION_TAG
 279  
      */
 280  
     protected void onSection( int depth, SinkEventAttributes attributes )
 281  
     {
 282  60
         if ( depth == SECTION_LEVEL_1 )
 283  
         {
 284  14
             write( String.valueOf( LESS_THAN ) + SECTION_TAG.toString()
 285  
                     + SinkUtils.getAttributeString(
 286  
                         SinkUtils.filterAttributes( attributes, SinkUtils.SINK_BASE_ATTRIBUTES ) )
 287  
                     + String.valueOf( SPACE ) + Attribute.NAME + String.valueOf( EQUAL ) + String.valueOf( QUOTE ) );
 288  
         }
 289  46
         else if ( depth == SECTION_LEVEL_2 )
 290  
         {
 291  16
             write( String.valueOf( LESS_THAN ) + SUBSECTION_TAG.toString()
 292  
                     + SinkUtils.getAttributeString(
 293  
                         SinkUtils.filterAttributes( attributes, SinkUtils.SINK_BASE_ATTRIBUTES  ) )
 294  
                     + String.valueOf( SPACE ) + Attribute.NAME + String.valueOf( EQUAL ) + String.valueOf( QUOTE ) );
 295  
         }
 296  60
     }
 297  
 
 298  
     /**
 299  
      * {@inheritDoc}
 300  
      *
 301  
      * Ends a section.
 302  
      * @see XdocMarkup#SECTION_TAG
 303  
      * @see XdocMarkup#SUBSECTION_TAG
 304  
      */
 305  
     protected void onSection_( int depth )
 306  
     {
 307  60
         if ( depth == SECTION_LEVEL_1 )
 308  
         {
 309  14
             writeEndTag( SECTION_TAG );
 310  
         }
 311  46
         else if ( depth == SECTION_LEVEL_2 )
 312  
         {
 313  16
             writeEndTag( SUBSECTION_TAG );
 314  
         }
 315  60
     }
 316  
 
 317  
     /**
 318  
      * {@inheritDoc}
 319  
      *
 320  
      * Starts a section title.
 321  
      * @see javax.swing.text.html.HTML.Tag#H4
 322  
      * @see javax.swing.text.html.HTML.Tag#H5
 323  
      * @see javax.swing.text.html.HTML.Tag#H6
 324  
      */
 325  
     protected void onSectionTitle( int depth, SinkEventAttributes attributes )
 326  
     {
 327  60
         MutableAttributeSet atts = SinkUtils.filterAttributes(
 328  
                 attributes, SinkUtils.SINK_SECTION_ATTRIBUTES  );
 329  
 
 330  60
         if ( depth == SECTION_LEVEL_3 )
 331  
         {
 332  10
             writeStartTag( H4, atts );
 333  
         }
 334  50
         else if ( depth == SECTION_LEVEL_4 )
 335  
         {
 336  10
             writeStartTag( H5, atts );
 337  
         }
 338  40
         else if ( depth == SECTION_LEVEL_5 )
 339  
         {
 340  10
             writeStartTag( H6, atts );
 341  
         }
 342  60
     }
 343  
 
 344  
     /**
 345  
      * {@inheritDoc}
 346  
      *
 347  
      * Ends a section title.
 348  
      * @see javax.swing.text.html.HTML.Tag#H4
 349  
      * @see javax.swing.text.html.HTML.Tag#H5
 350  
      * @see javax.swing.text.html.HTML.Tag#H6
 351  
      */
 352  
     protected void onSectionTitle_( int depth )
 353  
     {
 354  60
         if ( depth == SECTION_LEVEL_1 || depth == SECTION_LEVEL_2 )
 355  
         {
 356  30
             write( String.valueOf( QUOTE ) + String.valueOf( GREATER_THAN ) );
 357  
         }
 358  30
         else if ( depth == SECTION_LEVEL_3 )
 359  
         {
 360  10
             writeEndTag( H4 );
 361  
         }
 362  20
         else if ( depth == SECTION_LEVEL_4 )
 363  
         {
 364  10
             writeEndTag( H5 );
 365  
         }
 366  10
         else if ( depth == SECTION_LEVEL_5 )
 367  
         {
 368  10
             writeEndTag( H6 );
 369  
         }
 370  60
     }
 371  
 
 372  
     // -----------------------------------------------------------------------
 373  
     //
 374  
     // -----------------------------------------------------------------------
 375  
 
 376  
     /**
 377  
      * {@inheritDoc}
 378  
      * @see XdocMarkup#SOURCE_TAG
 379  
      * @see javax.swing.text.html.HTML.Tag#PRE
 380  
      */
 381  
     public void verbatim( SinkEventAttributes attributes )
 382  
     {
 383  30
         setVerbatimFlag( true );
 384  
 
 385  30
         MutableAttributeSet atts = SinkUtils.filterAttributes(
 386  
                 attributes, SinkUtils.SINK_VERBATIM_ATTRIBUTES  );
 387  
 
 388  
 
 389  30
         if ( atts == null )
 390  
         {
 391  4
             atts = new SinkEventAttributeSet();
 392  
         }
 393  
 
 394  30
         boolean boxed = false;
 395  
 
 396  30
         if ( atts.isDefined( SinkEventAttributes.DECORATION ) )
 397  
         {
 398  22
             boxed = "boxed".equals(
 399  
                 (String) atts.getAttribute( SinkEventAttributes.DECORATION ) );
 400  
         }
 401  
 
 402  30
         boxedFlag = boxed;
 403  30
         atts.removeAttribute( SinkEventAttributes.DECORATION );
 404  
 
 405  30
         if ( boxed )
 406  
         {
 407  22
             writeStartTag( SOURCE_TAG, atts );
 408  
         }
 409  
         else
 410  
         {
 411  8
             atts.removeAttribute( Attribute.ALIGN.toString() );
 412  8
             writeStartTag( PRE, atts );
 413  
         }
 414  30
     }
 415  
 
 416  
     /**
 417  
      * {@inheritDoc}
 418  
      * @see XdocMarkup#SOURCE_TAG
 419  
      * @see javax.swing.text.html.HTML.Tag#PRE
 420  
      */
 421  
     public void verbatim_()
 422  
     {
 423  30
         if ( boxedFlag )
 424  
         {
 425  22
             writeEndTag( SOURCE_TAG );
 426  
         }
 427  
         else
 428  
         {
 429  8
             writeEndTag( PRE );
 430  
         }
 431  
 
 432  30
         setVerbatimFlag( false );
 433  
 
 434  30
         boxedFlag = false;
 435  30
     }
 436  
 
 437  
     /**
 438  
      * The default align is <code>center</code>.
 439  
      *
 440  
      * {@inheritDoc}
 441  
      * @see javax.swing.text.html.HTML.Tag#TABLE
 442  
      */
 443  
     public void tableRows( int[] justification, boolean grid )
 444  
     {
 445  
         // similar to super.tableRows( justification, grid ) but without class.
 446  
 
 447  22
         this.tableRows = true;
 448  
 
 449  22
         setCellJustif( justification );
 450  
 
 451  22
         if ( this.tableAttributes == null )
 452  
         {
 453  0
             this.tableAttributes = new SinkEventAttributeSet( 0 );
 454  
         }
 455  
 
 456  22
         MutableAttributeSet att = new SinkEventAttributeSet();
 457  
 
 458  22
         if ( !tableAttributes.isDefined( Attribute.BORDER.toString() ) )
 459  
         {
 460  22
             att.addAttribute( Attribute.BORDER, ( grid ? "1" : "0" ) );
 461  
         }
 462  
 
 463  22
         att.addAttributes( tableAttributes );
 464  
 
 465  22
         tableAttributes.removeAttributes( tableAttributes );
 466  
 
 467  22
         writeStartTag( TABLE, att );
 468  22
     }
 469  
 
 470  
     /**
 471  
      * The default valign is <code>top</code>.
 472  
      *
 473  
      * {@inheritDoc}
 474  
      * @see javax.swing.text.html.HTML.Tag#TR
 475  
      */
 476  
     public void tableRow()
 477  
     {
 478  40
         MutableAttributeSet att = new SinkEventAttributeSet();
 479  40
         att.addAttribute( Attribute.VALIGN, "top" );
 480  
 
 481  40
         writeStartTag( TR, att );
 482  
 
 483  40
         setCellCount( 0 );
 484  40
     }
 485  
 
 486  
     public void close()
 487  
     {
 488  138
         super.close();
 489  
 
 490  138
         init();
 491  138
     }
 492  
 
 493  
     /**
 494  
      * Adds a link with an optional target.
 495  
      *
 496  
      * @param name the link name.
 497  
      * @param target the link target, may be null.
 498  
      */
 499  
     public void link( String name, String target )
 500  
     {
 501  8
         if ( isHeadFlag() )
 502  
         {
 503  0
             return;
 504  
         }
 505  
 
 506  8
         MutableAttributeSet att = new SinkEventAttributeSet();
 507  
 
 508  8
         att.addAttribute( Attribute.HREF, HtmlTools.escapeHTML( name ) );
 509  
 
 510  8
         if ( target != null )
 511  
         {
 512  4
             att.addAttribute( Attribute.TARGET, target );
 513  
         }
 514  
 
 515  8
         writeStartTag( A, att );
 516  8
     }
 517  
 
 518  
     // ----------------------------------------------------------------------
 519  
     //
 520  
     // ----------------------------------------------------------------------
 521  
 
 522  
     /**
 523  
      * Write text to output, preserving white space.
 524  
      *
 525  
      * @param text The text to write.
 526  
      * @deprecated use write(String)
 527  
      */
 528  
     protected void markup( String text )
 529  
     {
 530  0
         write( text );
 531  0
     }
 532  
 }