Coverage Report - org.apache.maven.doxia.module.itext.ITextSink
 
Classes in this File Line Coverage Branch Coverage Complexity
ITextSink
87%
670/763
34%
67/196
2,019
 
 1  
 package org.apache.maven.doxia.module.itext;
 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 com.lowagie.text.BadElementException;
 23  
 import com.lowagie.text.ElementTags;
 24  
 import com.lowagie.text.Image;
 25  
 
 26  
 import java.awt.Color;
 27  
 import java.io.File;
 28  
 import java.io.IOException;
 29  
 import java.io.LineNumberReader;
 30  
 import java.io.StringReader;
 31  
 import java.io.StringWriter;
 32  
 import java.io.Writer;
 33  
 import java.net.MalformedURLException;
 34  
 import java.net.URL;
 35  
 import java.util.HashMap;
 36  
 import java.util.Locale;
 37  
 import java.util.Map;
 38  
 import java.util.Set;
 39  
 import java.util.TreeSet;
 40  
 
 41  
 import org.apache.maven.doxia.sink.AbstractXmlSink;
 42  
 import org.apache.maven.doxia.sink.Sink;
 43  
 import org.apache.maven.doxia.sink.SinkEventAttributes;
 44  
 import org.apache.maven.doxia.util.DoxiaUtils;
 45  
 import org.apache.maven.doxia.util.HtmlTools;
 46  
 
 47  
 import org.codehaus.plexus.util.IOUtil;
 48  
 import org.codehaus.plexus.util.StringUtils;
 49  
 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
 50  
 import org.codehaus.plexus.util.xml.XMLWriter;
 51  
 
 52  
 /**
 53  
  * <p>A doxia Sink which produces an XML Front End document for <code>iText</code> framework.</p>
 54  
  * Known limitations:
 55  
  * <ul>
 56  
  * <li>Roman lists are not supported.</li>
 57  
  * <li>Horizontal rule is not supported with 1.3.
 58  
  * See <a href="http://www.mail-archive.com/itext-questions@lists.sourceforge.net/msg10323.html">
 59  
  * http://www.mail-archive.com/itext-questions@lists.sourceforge.net/msg10323.html</a></li>
 60  
  * <li>iText has some problems with <code>ElementTags.TABLE</code> and <code>ElementTags.TABLEFITSPAGE</code>.
 61  
  * See http://sourceforge.net/tracker/index.php?func=detail&aid=786427&group_id=15255&atid=115255.</li>
 62  
  * <li>Images could be on another page and next text on the last one.</li>
 63  
  * </ul>
 64  
  *
 65  
  * @see <a href="http://www.lowagie.com/iText/tutorial/ch07.html">http://www.lowagie.com/iText/tutorial/ch07.html</a>
 66  
  *
 67  
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 68  
  * @version $Id: ITextSink.java 1090706 2011-04-09 23:15:28Z hboutemy $
 69  
  */
 70  
 public class ITextSink
 71  
     extends AbstractXmlSink
 72  
 {
 73  
     /** This is the place where the iText DTD is located. IMPORTANT: this DTD is not uptodate! */
 74  
     public static final String DTD = "http://itext.sourceforge.net/itext.dtd";
 75  
 
 76  
     /** This is the reference to the DTD. */
 77  
     public static final String DOCTYPE = "ITEXT SYSTEM \"" + DTD + "\"";
 78  
 
 79  
     /** This is the default leading for chapter title */
 80  
     public static final String DEFAULT_CHAPTER_TITLE_LEADING = "36.0";
 81  
 
 82  
     /** This is the default leading for section title */
 83  
     public static final String DEFAULT_SECTION_TITLE_LEADING = "24.0";
 84  
 
 85  
     /** The ClassLoader used */
 86  
     private ClassLoader currentClassLoader;
 87  
 
 88  
     /** The action context */
 89  
     private SinkActionContext actionContext;
 90  
 
 91  
     /** The Writer used */
 92  
     private Writer writer;
 93  
 
 94  
     /** The XML Writer used */
 95  
     private final XMLWriter xmlWriter;
 96  
 
 97  
     private boolean writeStart;
 98  
 
 99  
     /** The Header object */
 100  
     private ITextHeader header;
 101  
 
 102  
     /** The font object */
 103  
     private ITextFont font;
 104  
 
 105  4
     private int numberDepth = 1;
 106  
 
 107  4
     private int depth = 0;
 108  
 
 109  4
     private StringWriter tableCaptionWriter = null;
 110  
 
 111  4
     private XMLWriter tableCaptionXMLWriter = null;
 112  
 
 113  
     /** Flag to know if an anchor is defined or not. Used as workaround for iText which needs a defined local
 114  
      * destination. */
 115  4
     private boolean anchorDefined = false;
 116  
 
 117  
     /** Flag to know if an figure event is called. */
 118  4
     private boolean figureDefined = false;
 119  
 
 120  
     /** Map of warn messages with a String as key to describe the error type and a Set as value.
 121  
      * Using to reduce warn messages. */
 122  
     private Map<String, Set<String>> warnMessages;
 123  
 
 124  
     /**
 125  
      * <p>Constructor for ITextSink.</p>
 126  
      *
 127  
      * @param writer the writer.
 128  
      */
 129  
     protected ITextSink( Writer writer )
 130  
     {
 131  4
         this( writer, "UTF-8" );
 132  4
     }
 133  
 
 134  
     /**
 135  
      * <p>Constructor for ITextSink.</p>
 136  
      *
 137  
      * @param writer the writer.
 138  
      * @param encoding the encoding.
 139  
      * @since 1.1
 140  
      */
 141  
     protected ITextSink( Writer writer, String encoding )
 142  
     {
 143  
         // No doctype since itext doctype is not up to date!
 144  4
         this( new PrettyPrintXMLWriter( writer, encoding, null ) );
 145  
 
 146  4
         this.writer = writer;
 147  4
         this.writeStart = true;
 148  4
     }
 149  
 
 150  
     /**
 151  
      * <p>Constructor for ITextSink.</p>
 152  
      *
 153  
      * @param xmlWriter a pretty-printing xml writer.
 154  
      */
 155  
     protected ITextSink( PrettyPrintXMLWriter xmlWriter )
 156  4
     {
 157  4
         this.xmlWriter = xmlWriter;
 158  
 
 159  4
         this.writeStart = false;
 160  
 
 161  4
         init();
 162  4
     }
 163  
 
 164  
     /**
 165  
      * Get the current classLoader
 166  
      *
 167  
      * @return the current class loader
 168  
      */
 169  
     public ClassLoader getClassLoader()
 170  
     {
 171  6
         return currentClassLoader;
 172  
     }
 173  
 
 174  
     /**
 175  
      * Set a new class loader
 176  
      *
 177  
      * @param cl the class loader.
 178  
      */
 179  
     public void setClassLoader( ClassLoader cl )
 180  
     {
 181  4
         currentClassLoader = cl;
 182  4
     }
 183  
 
 184  
     // ----------------------------------------------------------------------
 185  
     // Document
 186  
     // ----------------------------------------------------------------------
 187  
 
 188  
     /** {@inheritDoc} */
 189  
     public void close()
 190  
     {
 191  4
         IOUtil.close( writer );
 192  
 
 193  4
         init();
 194  4
     }
 195  
 
 196  
     /** {@inheritDoc} */
 197  
     public void flush()
 198  
     {
 199  4
         if ( getLog().isWarnEnabled() && this.warnMessages != null )
 200  
         {
 201  0
             for ( Map.Entry<String, Set<String>> entry : this.warnMessages.entrySet() )
 202  
             {
 203  0
                 for ( String msg : entry.getValue() )
 204  
                 {
 205  0
                     getLog().warn( msg );
 206  
                 }
 207  
             }
 208  
         }
 209  
 
 210  4
         this.warnMessages = null;
 211  4
     }
 212  
 
 213  
     // ----------------------------------------------------------------------
 214  
     // Header
 215  
     // ----------------------------------------------------------------------
 216  
 
 217  
     /** {@inheritDoc} */
 218  
     public void head_()
 219  
     {
 220  4
         actionContext.release();
 221  4
     }
 222  
 
 223  
     /** {@inheritDoc} */
 224  
     public void head()
 225  
     {
 226  
         //init(); // why? this causes DOXIA-413
 227  
 
 228  4
         actionContext.setAction( SinkActionContext.HEAD );
 229  4
     }
 230  
 
 231  
     /** {@inheritDoc} */
 232  
     public void author_()
 233  
     {
 234  4
         actionContext.release();
 235  4
     }
 236  
 
 237  
     /** {@inheritDoc} */
 238  
     public void author()
 239  
     {
 240  4
         actionContext.setAction( SinkActionContext.AUTHOR );
 241  4
     }
 242  
 
 243  
     /** {@inheritDoc} */
 244  
     public void date_()
 245  
     {
 246  4
         actionContext.release();
 247  4
     }
 248  
 
 249  
     /** {@inheritDoc} */
 250  
     public void date()
 251  
     {
 252  4
         actionContext.setAction( SinkActionContext.DATE );
 253  4
     }
 254  
 
 255  
     /** {@inheritDoc} */
 256  
     public void title_()
 257  
     {
 258  4
         actionContext.release();
 259  4
     }
 260  
 
 261  
     /** {@inheritDoc} */
 262  
     public void title()
 263  
     {
 264  4
         actionContext.setAction( SinkActionContext.TITLE );
 265  4
     }
 266  
 
 267  
     // ----------------------------------------------------------------------
 268  
     // Body
 269  
     // ----------------------------------------------------------------------
 270  
 
 271  
     /** {@inheritDoc} */
 272  
     public void body_()
 273  
     {
 274  4
         if ( writeStart )
 275  
         {
 276  4
             writeEndElement(); // ElementTags.CHAPTER
 277  
 
 278  4
             writeEndElement(); // ElementTags.ITEXT
 279  
         }
 280  
 
 281  4
         actionContext.release();
 282  4
     }
 283  
 
 284  
     /** {@inheritDoc} */
 285  
     public void body()
 286  
     {
 287  4
         if ( writeStart )
 288  
         {
 289  4
             writeStartElement( ElementTags.ITEXT );
 290  4
             writeAddAttribute( ElementTags.TITLE, header.getTitle() );
 291  4
             writeAddAttribute( ElementTags.AUTHOR, header.getAuthors() );
 292  4
             writeAddAttribute( ElementTags.CREATIONDATE, header.getDate() );
 293  4
             writeAddAttribute( ElementTags.SUBJECT, header.getTitle() );
 294  4
             writeAddAttribute( ElementTags.KEYWORDS, "" );
 295  4
             writeAddAttribute( ElementTags.PRODUCER, "Generated with Doxia by " + System.getProperty( "user.name" ) );
 296  4
             writeAddAttribute( ElementTags.PAGE_SIZE, ITextUtil.getPageSize( ITextUtil.getDefaultPageSize() ) );
 297  
 
 298  4
             writeStartElement( ElementTags.CHAPTER );
 299  4
             writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
 300  4
             writeAddAttribute( ElementTags.DEPTH, depth );
 301  4
             writeAddAttribute( ElementTags.INDENT, "0.0" );
 302  
 
 303  4
             writeStartElement( ElementTags.TITLE );
 304  4
             writeAddAttribute( ElementTags.LEADING, DEFAULT_CHAPTER_TITLE_LEADING );
 305  4
             writeAddAttribute( ElementTags.FONT, ITextFont.DEFAULT_FONT_NAME );
 306  4
             writeAddAttribute( ElementTags.SIZE, ITextFont.getSectionFontSize( 0 ) );
 307  4
             writeAddAttribute( ElementTags.STYLE, ITextFont.BOLD );
 308  4
             writeAddAttribute( ElementTags.BLUE, ITextFont.DEFAULT_FONT_COLOR_BLUE );
 309  4
             writeAddAttribute( ElementTags.GREEN, ITextFont.DEFAULT_FONT_COLOR_GREEN );
 310  4
             writeAddAttribute( ElementTags.RED, ITextFont.DEFAULT_FONT_COLOR_RED );
 311  4
             writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
 312  
 
 313  
 //            startChunk( ITextFont.DEFAULT_FONT_NAME, ITextFont.getSectionFontSize( 0 ),
 314  
 //                    ITextFont.BOLD, ITextFont.DEFAULT_FONT_COLOR_BLUE, ITextFont.DEFAULT_FONT_COLOR_GREEN,
 315  
 //                    ITextFont.DEFAULT_FONT_COLOR_RED, "top" );
 316  
 
 317  4
             writeStartElement( ElementTags.CHUNK );
 318  4
             writeAddAttribute( ElementTags.FONT, ITextFont.DEFAULT_FONT_NAME );
 319  4
             writeAddAttribute( ElementTags.SIZE, ITextFont.getSectionFontSize( 0 ) );
 320  4
             writeAddAttribute( ElementTags.STYLE, ITextFont.BOLD );
 321  4
             writeAddAttribute( ElementTags.BLUE, ITextFont.DEFAULT_FONT_COLOR_BLUE );
 322  4
             writeAddAttribute( ElementTags.GREEN, ITextFont.DEFAULT_FONT_COLOR_GREEN );
 323  4
             writeAddAttribute( ElementTags.RED, ITextFont.DEFAULT_FONT_COLOR_RED );
 324  
 //            writeAddAttribute( ElementTags.LOCALDESTINATION, "top" );
 325  
 
 326  4
             write( header.getTitle() );
 327  
 
 328  4
             writeEndElement(); // ElementTags.CHUNK
 329  
 
 330  4
             writeEndElement(); // ElementTags.TITLE
 331  
         }
 332  
 
 333  4
         actionContext.setAction( SinkActionContext.BODY );
 334  4
     }
 335  
 
 336  
     // ----------------------------------------------------------------------
 337  
     // Sections
 338  
     // ----------------------------------------------------------------------
 339  
 
 340  
     /** {@inheritDoc} */
 341  
     public void sectionTitle()
 342  
     {
 343  0
         actionContext.release();
 344  0
     }
 345  
 
 346  
     /** {@inheritDoc} */
 347  
     public void sectionTitle_()
 348  
     {
 349  0
         actionContext.setAction( SinkActionContext.SECTION_TITLE );
 350  0
     }
 351  
 
 352  
     /** {@inheritDoc} */
 353  
     public void section1_()
 354  
     {
 355  2
         writeEndElement(); // ElementTags.SECTION
 356  
 
 357  2
         numberDepth--;
 358  2
         depth = 0;
 359  
 
 360  2
         actionContext.release();
 361  2
     }
 362  
 
 363  
     /** {@inheritDoc} */
 364  
     public void section1()
 365  
     {
 366  2
         numberDepth++;
 367  2
         depth = 1;
 368  
 
 369  2
         writeStartElement( ElementTags.SECTION );
 370  2
         writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
 371  2
         writeAddAttribute( ElementTags.DEPTH, depth );
 372  2
         writeAddAttribute( ElementTags.INDENT, "0.0" );
 373  
 
 374  2
         lineBreak();
 375  
 
 376  2
         actionContext.setAction( SinkActionContext.SECTION_1 );
 377  2
     }
 378  
 
 379  
     /** {@inheritDoc} */
 380  
     public void sectionTitle1_()
 381  
     {
 382  2
         writeEndElement(); // ElementTags.TITLE
 383  
 
 384  2
         font.setSize( ITextFont.DEFAULT_FONT_SIZE );
 385  2
         bold_();
 386  
 
 387  2
         actionContext.release();
 388  2
     }
 389  
 
 390  
     /** {@inheritDoc} */
 391  
     public void sectionTitle1()
 392  
     {
 393  2
         font.setSize( ITextFont.getSectionFontSize( 1 ) );
 394  2
         font.setColor( Color.BLACK );
 395  2
         bold();
 396  
 
 397  2
         writeStartElement( ElementTags.TITLE );
 398  2
         writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
 399  2
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 400  2
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 401  2
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 402  2
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 403  2
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 404  2
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 405  
 //        writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
 406  
 
 407  2
         actionContext.setAction( SinkActionContext.SECTION_TITLE_1 );
 408  2
     }
 409  
 
 410  
     /** {@inheritDoc} */
 411  
     public void section2_()
 412  
     {
 413  2
         writeEndElement(); // ElementTags.SECTION
 414  
 
 415  2
         numberDepth--;
 416  2
         depth = 0;
 417  
 
 418  2
         actionContext.release();
 419  2
     }
 420  
 
 421  
     /** {@inheritDoc} */
 422  
     public void section2()
 423  
     {
 424  2
         numberDepth++;
 425  2
         depth = 1;
 426  
 
 427  2
         writeStartElement( ElementTags.SECTION );
 428  2
         writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
 429  2
         writeAddAttribute( ElementTags.DEPTH, depth );
 430  2
         writeAddAttribute( ElementTags.INDENT, "0.0" );
 431  
 
 432  2
         lineBreak();
 433  
 
 434  2
         actionContext.setAction( SinkActionContext.SECTION_2 );
 435  2
     }
 436  
 
 437  
     /** {@inheritDoc} */
 438  
     public void sectionTitle2_()
 439  
     {
 440  2
         writeEndElement(); // ElementTags.TITLE
 441  
 
 442  2
         font.setSize( ITextFont.DEFAULT_FONT_SIZE );
 443  2
         bold_();
 444  
 
 445  2
         actionContext.release();
 446  2
     }
 447  
 
 448  
     /** {@inheritDoc} */
 449  
     public void sectionTitle2()
 450  
     {
 451  2
         font.setSize( ITextFont.getSectionFontSize( 2 ) );
 452  2
         font.setColor( Color.BLACK );
 453  2
         bold();
 454  
 
 455  2
         writeStartElement( ElementTags.TITLE );
 456  2
         writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
 457  2
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 458  2
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 459  2
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 460  2
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 461  2
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 462  2
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 463  
 //        writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
 464  
 
 465  2
         actionContext.setAction( SinkActionContext.SECTION_TITLE_2 );
 466  2
     }
 467  
 
 468  
     /** {@inheritDoc} */
 469  
     public void section3_()
 470  
     {
 471  2
         writeEndElement(); // ElementTags.SECTION
 472  
 
 473  2
         numberDepth--;
 474  2
         depth = 1;
 475  
 
 476  2
         actionContext.release();
 477  2
     }
 478  
 
 479  
     /** {@inheritDoc} */
 480  
     public void section3()
 481  
     {
 482  2
         numberDepth++;
 483  2
         depth = 1;
 484  
 
 485  2
         writeStartElement( ElementTags.SECTION );
 486  2
         writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
 487  2
         writeAddAttribute( ElementTags.DEPTH, depth );
 488  2
         writeAddAttribute( ElementTags.INDENT, "0.0" );
 489  
 
 490  2
         lineBreak();
 491  
 
 492  2
         actionContext.setAction( SinkActionContext.SECTION_3 );
 493  2
     }
 494  
 
 495  
     /** {@inheritDoc} */
 496  
     public void sectionTitle3_()
 497  
     {
 498  2
         writeEndElement(); // ElementTags.TITLE
 499  
 
 500  2
         font.setSize( ITextFont.DEFAULT_FONT_SIZE );
 501  2
         bold_();
 502  
 
 503  2
         actionContext.release();
 504  2
     }
 505  
 
 506  
     /** {@inheritDoc} */
 507  
     public void sectionTitle3()
 508  
     {
 509  2
         font.setSize( ITextFont.getSectionFontSize( 3 ) );
 510  2
         font.setColor( Color.BLACK );
 511  2
         bold();
 512  
 
 513  2
         writeStartElement( ElementTags.TITLE );
 514  2
         writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
 515  2
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 516  2
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 517  2
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 518  2
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 519  2
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 520  2
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 521  
 //        writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
 522  
 
 523  2
         actionContext.setAction( SinkActionContext.SECTION_TITLE_3 );
 524  2
     }
 525  
 
 526  
     /** {@inheritDoc} */
 527  
     public void section4_()
 528  
     {
 529  2
         writeEndElement(); // ElementTags.SECTION
 530  
 
 531  2
         numberDepth--;
 532  2
         depth = 1;
 533  
 
 534  2
         actionContext.release();
 535  2
     }
 536  
 
 537  
     /** {@inheritDoc} */
 538  
     public void section4()
 539  
     {
 540  2
         numberDepth++;
 541  2
         depth = 1;
 542  
 
 543  2
         writeStartElement( ElementTags.SECTION );
 544  2
         writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
 545  2
         writeAddAttribute( ElementTags.DEPTH, depth );
 546  2
         writeAddAttribute( ElementTags.INDENT, "0.0" );
 547  
 
 548  2
         lineBreak();
 549  
 
 550  2
         actionContext.setAction( SinkActionContext.SECTION_4 );
 551  2
     }
 552  
 
 553  
     /** {@inheritDoc} */
 554  
     public void sectionTitle4_()
 555  
     {
 556  2
         writeEndElement(); // ElementTags.TITLE
 557  
 
 558  2
         font.setSize( ITextFont.DEFAULT_FONT_SIZE );
 559  2
         bold_();
 560  
 
 561  2
         actionContext.release();
 562  2
     }
 563  
 
 564  
     /** {@inheritDoc} */
 565  
     public void sectionTitle4()
 566  
     {
 567  2
         font.setSize( ITextFont.getSectionFontSize( 4 ) );
 568  2
         font.setColor( Color.BLACK );
 569  2
         bold();
 570  
 
 571  2
         writeStartElement( ElementTags.TITLE );
 572  2
         writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
 573  2
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 574  2
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 575  2
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 576  2
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 577  2
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 578  2
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 579  
 //        writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
 580  
 
 581  2
         actionContext.setAction( SinkActionContext.SECTION_TITLE_4 );
 582  2
     }
 583  
 
 584  
     /** {@inheritDoc} */
 585  
     public void section5_()
 586  
     {
 587  2
         writeEndElement(); // ElementTags.SECTION
 588  
 
 589  2
         numberDepth--;
 590  2
         depth = 1;
 591  
 
 592  2
         actionContext.release();
 593  2
     }
 594  
 
 595  
     /** {@inheritDoc} */
 596  
     public void section5()
 597  
     {
 598  2
         numberDepth++;
 599  2
         depth = 1;
 600  
 
 601  2
         writeStartElement( ElementTags.SECTION );
 602  2
         writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
 603  2
         writeAddAttribute( ElementTags.DEPTH, depth );
 604  2
         writeAddAttribute( ElementTags.INDENT, "0.0" );
 605  
 
 606  2
         lineBreak();
 607  
 
 608  2
         actionContext.setAction( SinkActionContext.SECTION_5 );
 609  2
     }
 610  
 
 611  
     /** {@inheritDoc} */
 612  
     public void sectionTitle5_()
 613  
     {
 614  2
         writeEndElement(); // ElementTags.TITLE
 615  
 
 616  2
         font.setSize( ITextFont.DEFAULT_FONT_SIZE );
 617  2
         bold_();
 618  
 
 619  2
         actionContext.release();
 620  2
     }
 621  
 
 622  
     /** {@inheritDoc} */
 623  
     public void sectionTitle5()
 624  
     {
 625  2
         font.setSize( ITextFont.getSectionFontSize( 5 ) );
 626  2
         font.setColor( Color.BLACK );
 627  2
         bold();
 628  
 
 629  2
         writeStartElement( ElementTags.TITLE );
 630  2
         writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
 631  2
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 632  2
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 633  2
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 634  2
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 635  2
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 636  2
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 637  
 //        writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
 638  
 
 639  2
         actionContext.setAction( SinkActionContext.SECTION_TITLE_5 );
 640  2
     }
 641  
 
 642  
     // ----------------------------------------------------------------------
 643  
     // Paragraph
 644  
     // ----------------------------------------------------------------------
 645  
 
 646  
     /** {@inheritDoc} */
 647  
     public void paragraph_()
 648  
     {
 649  
         // Special case
 650  28
         if ( ( actionContext.getCurrentAction() == SinkActionContext.LIST_ITEM )
 651  
             || ( actionContext.getCurrentAction() == SinkActionContext.NUMBERED_LIST_ITEM )
 652  
             || ( actionContext.getCurrentAction() == SinkActionContext.DEFINITION ) )
 653  
         {
 654  2
             return;
 655  
         }
 656  
 
 657  26
         writeEndElement(); // ElementTags.PARAGRAPH
 658  
 
 659  26
         actionContext.release();
 660  26
     }
 661  
 
 662  
     /** {@inheritDoc} */
 663  
     public void paragraph()
 664  
     {
 665  
         // Special case
 666  28
         if ( ( actionContext.getCurrentAction() == SinkActionContext.LIST_ITEM )
 667  
             || ( actionContext.getCurrentAction() == SinkActionContext.NUMBERED_LIST_ITEM )
 668  
             || ( actionContext.getCurrentAction() == SinkActionContext.DEFINITION ) )
 669  
         {
 670  2
             return;
 671  
         }
 672  
 
 673  26
         writeStartElement( ElementTags.PARAGRAPH );
 674  26
         writeStartElement( ElementTags.NEWLINE );
 675  26
         writeEndElement();
 676  
 
 677  26
         actionContext.setAction( SinkActionContext.PARAGRAPH );
 678  26
     }
 679  
 
 680  
     // ----------------------------------------------------------------------
 681  
     // Lists
 682  
     // ----------------------------------------------------------------------
 683  
 
 684  
     /** {@inheritDoc} */
 685  
     public void list_()
 686  
     {
 687  4
         writeEndElement(); // ElementTags.LIST
 688  
 
 689  4
         writeEndElement(); // ElementTags.CHUNK
 690  
 
 691  4
         actionContext.release();
 692  4
     }
 693  
 
 694  
     /** {@inheritDoc} */
 695  
     public void list()
 696  
     {
 697  4
         writeStartElement( ElementTags.CHUNK );
 698  4
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 699  4
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 700  4
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 701  4
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 702  4
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 703  4
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 704  
 
 705  4
         writeStartElement( ElementTags.LIST );
 706  4
         writeAddAttribute( ElementTags.NUMBERED, Boolean.FALSE.toString() );
 707  4
         writeAddAttribute( ElementTags.SYMBOLINDENT, "15" );
 708  
 
 709  4
         actionContext.setAction( SinkActionContext.LIST );
 710  4
     }
 711  
 
 712  
     /** {@inheritDoc} */
 713  
     public void listItem_()
 714  
     {
 715  10
         writeEndElement(); // ElementTags.LISTITEM
 716  
 
 717  10
         actionContext.release();
 718  10
     }
 719  
 
 720  
     /** {@inheritDoc} */
 721  
     public void listItem()
 722  
     {
 723  10
         writeStartElement( ElementTags.LISTITEM );
 724  10
         writeAddAttribute( ElementTags.INDENTATIONLEFT, "20.0" );
 725  
 
 726  10
         actionContext.setAction( SinkActionContext.LIST_ITEM );
 727  10
     }
 728  
 
 729  
     /** {@inheritDoc} */
 730  
     public void numberedList_()
 731  
     {
 732  4
         writeEndElement(); // ElementTags.LIST
 733  
 
 734  4
         writeEndElement(); // ElementTags.CHUNK
 735  
 
 736  4
         actionContext.release();
 737  4
     }
 738  
 
 739  
     /** {@inheritDoc} */
 740  
     public void numberedList( int numbering )
 741  
     {
 742  4
         writeStartElement( ElementTags.CHUNK );
 743  4
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 744  4
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 745  4
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 746  4
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 747  4
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 748  4
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 749  
 
 750  4
         writeStartElement( ElementTags.LIST );
 751  4
         writeAddAttribute( ElementTags.NUMBERED, Boolean.TRUE.toString() );
 752  4
         writeAddAttribute( ElementTags.SYMBOLINDENT, "20" );
 753  
 
 754  4
         switch ( numbering )
 755  
         {
 756  
             case Sink.NUMBERING_UPPER_ALPHA:
 757  2
                 writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
 758  2
                 writeAddAttribute( ElementTags.FIRST, 'A' );
 759  2
                 break;
 760  
 
 761  
             case Sink.NUMBERING_LOWER_ALPHA:
 762  0
                 writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
 763  0
                 writeAddAttribute( ElementTags.FIRST, 'a' );
 764  0
                 break;
 765  
 
 766  
             // TODO Doesn't work
 767  
             case Sink.NUMBERING_UPPER_ROMAN:
 768  0
                 writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
 769  0
                 writeAddAttribute( ElementTags.FIRST, 'I' );
 770  0
                 break;
 771  
 
 772  
             case Sink.NUMBERING_LOWER_ROMAN:
 773  0
                 writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
 774  0
                 writeAddAttribute( ElementTags.FIRST, 'i' );
 775  0
                 break;
 776  
 
 777  
             case Sink.NUMBERING_DECIMAL:
 778  
             default:
 779  2
                 writeAddAttribute( ElementTags.LETTERED, Boolean.FALSE.toString() );
 780  
         }
 781  
 
 782  4
         actionContext.setAction( SinkActionContext.NUMBERED_LIST );
 783  4
     }
 784  
 
 785  
     /** {@inheritDoc} */
 786  
     public void numberedListItem_()
 787  
     {
 788  8
         writeEndElement(); // ElementTags.LISTITEM
 789  
 
 790  8
         actionContext.release();
 791  8
     }
 792  
 
 793  
     /** {@inheritDoc} */
 794  
     public void numberedListItem()
 795  
     {
 796  8
         writeStartElement( ElementTags.LISTITEM );
 797  8
         writeAddAttribute( ElementTags.INDENTATIONLEFT, "20" );
 798  
 
 799  8
         actionContext.setAction( SinkActionContext.NUMBERED_LIST_ITEM );
 800  8
     }
 801  
 
 802  
     /** {@inheritDoc} */
 803  
     public void definitionList_()
 804  
     {
 805  2
         actionContext.release();
 806  2
     }
 807  
 
 808  
     /** {@inheritDoc} */
 809  
     public void definitionList()
 810  
     {
 811  2
         lineBreak();
 812  
 
 813  2
         actionContext.setAction( SinkActionContext.DEFINITION_LIST );
 814  2
     }
 815  
 
 816  
     /** {@inheritDoc} */
 817  
     public void definedTerm_()
 818  
     {
 819  4
         font.setSize( ITextFont.DEFAULT_FONT_SIZE );
 820  4
         bold_();
 821  
 
 822  4
         writeEndElement(); // ElementTags.CHUNK
 823  
 
 824  4
         actionContext.release();
 825  
 
 826  4
         lineBreak();
 827  4
     }
 828  
 
 829  
     /** {@inheritDoc} */
 830  
     public void definedTerm()
 831  
     {
 832  4
         font.setSize( ITextFont.DEFAULT_FONT_SIZE + 2 );
 833  4
         bold();
 834  
 
 835  4
         writeStartElement( ElementTags.CHUNK );
 836  4
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 837  4
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 838  4
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 839  4
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 840  4
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 841  4
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 842  
 
 843  4
         actionContext.setAction( SinkActionContext.DEFINED_TERM );
 844  4
     }
 845  
 
 846  
     /** {@inheritDoc} */
 847  
     public void definition_()
 848  
     {
 849  4
         writeEndElement(); // ElementTags.CHUNK
 850  
 
 851  4
         actionContext.release();
 852  
 
 853  4
         lineBreak();
 854  4
     }
 855  
 
 856  
     /** {@inheritDoc} */
 857  
     public void definition()
 858  
     {
 859  4
         writeStartElement( ElementTags.CHUNK );
 860  4
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 861  4
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 862  4
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 863  4
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 864  4
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 865  4
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 866  
 
 867  
 
 868  4
         writeStartElement( ElementTags.CHUNK );
 869  4
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 870  4
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 871  4
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 872  4
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 873  4
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 874  4
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 875  
 
 876  
         // We need to add a non break space first to display empty string
 877  4
         write( "\u00A0" + StringUtils.repeat( " ", 16 ), false, false );
 878  
 
 879  4
         writeEndElement(); // ElementTags.CHUNK
 880  
 
 881  4
         actionContext.setAction( SinkActionContext.DEFINITION );
 882  4
     }
 883  
 
 884  
     /** {@inheritDoc} */
 885  
     public void definitionListItem_()
 886  
     {
 887  4
         actionContext.release();
 888  4
     }
 889  
 
 890  
     /** {@inheritDoc} */
 891  
     public void definitionListItem()
 892  
     {
 893  4
         actionContext.setAction( SinkActionContext.DEFINITION_LIST_ITEM );
 894  4
     }
 895  
 
 896  
     // ----------------------------------------------------------------------
 897  
     //  Tables
 898  
     // ----------------------------------------------------------------------
 899  
 
 900  
     /** {@inheritDoc} */
 901  
     public void table_()
 902  
     {
 903  6
         if ( tableCaptionXMLWriter != null )
 904  
         {
 905  2
             tableCaptionXMLWriter = null;
 906  
 
 907  2
             writeEndElement(); // ElementTags.TABLE
 908  
 
 909  2
             writeEndElement(); // ElementTags.CHUNK
 910  
 
 911  2
             writeStartElement( ElementTags.PARAGRAPH );
 912  2
             writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
 913  
 
 914  2
             write( tableCaptionWriter.toString(), true );
 915  
 
 916  2
             writeEndElement(); // ElementTags.PARAGRAPH
 917  
 
 918  2
             tableCaptionWriter = null;
 919  
         }
 920  
         else
 921  
         {
 922  4
             writeEndElement(); // ElementTags.TABLE
 923  
 
 924  4
             writeEndElement(); // ElementTags.CHUNK
 925  
         }
 926  6
         actionContext.release();
 927  6
     }
 928  
 
 929  
     /** {@inheritDoc} */
 930  
     public void table()
 931  
     {
 932  6
         writeStartElement( ElementTags.CHUNK );
 933  6
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 934  6
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 935  6
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 936  6
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 937  6
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 938  6
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 939  
 
 940  6
         writeStartElement( ElementTags.TABLE );
 941  6
         writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
 942  6
         writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
 943  6
         writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
 944  6
         writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
 945  6
         writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
 946  6
         writeAddAttribute( ElementTags.WIDTH, "100.0%" );
 947  6
         writeAddAttribute( ElementTags.TABLEFITSPAGE, Boolean.TRUE.toString() );
 948  6
         writeAddAttribute( ElementTags.CELLSFITPAGE, Boolean.TRUE.toString() );
 949  6
         writeAddAttribute( ElementTags.CELLPADDING, "10" );
 950  
         //writeAddAttribute( ElementTags.COLUMNS, "2" );
 951  
 
 952  6
         actionContext.setAction( SinkActionContext.TABLE );
 953  6
     }
 954  
 
 955  
     /** {@inheritDoc} */
 956  
     public void tableCaption_()
 957  
     {
 958  2
         actionContext.release();
 959  2
     }
 960  
 
 961  
     /** {@inheritDoc} */
 962  
     public void tableCaption()
 963  
     {
 964  2
         tableCaptionWriter = new StringWriter();
 965  2
         tableCaptionXMLWriter = new PrettyPrintXMLWriter( tableCaptionWriter );
 966  2
         actionContext.setAction( SinkActionContext.TABLE_CAPTION );
 967  2
     }
 968  
 
 969  
     /** {@inheritDoc} */
 970  
     public void tableCell_()
 971  
     {
 972  24
         writeEndElement(); // ElementTags.CELL
 973  
 
 974  24
         actionContext.release();
 975  24
     }
 976  
 
 977  
     /** {@inheritDoc} */
 978  
     public void tableCell()
 979  
     {
 980  24
         writeStartElement( ElementTags.CELL );
 981  24
         writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
 982  24
         writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
 983  24
         writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
 984  24
         writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
 985  24
         writeAddAttribute( ElementTags.HORIZONTALALIGN, ElementTags.ALIGN_LEFT );
 986  
 
 987  24
         actionContext.setAction( SinkActionContext.TABLE_CELL );
 988  24
     }
 989  
 
 990  
     /** {@inheritDoc} */
 991  
     public void tableCell( String width )
 992  
     {
 993  0
         actionContext.setAction( SinkActionContext.TABLE_CELL );
 994  0
     }
 995  
 
 996  
     /** {@inheritDoc} */
 997  
     public void tableHeaderCell_()
 998  
     {
 999  4
         writeEndElement(); // ElementTags.CELL
 1000  
 
 1001  4
         actionContext.release();
 1002  4
     }
 1003  
 
 1004  
     /** {@inheritDoc} */
 1005  
     public void tableHeaderCell()
 1006  
     {
 1007  4
         writeStartElement( ElementTags.CELL );
 1008  4
         writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
 1009  4
         writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
 1010  4
         writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
 1011  4
         writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
 1012  4
         writeAddAttribute( ElementTags.HEADER, Boolean.TRUE.toString() );
 1013  4
         writeAddAttribute( ElementTags.BGRED, Color.GRAY.getRed() );
 1014  4
         writeAddAttribute( ElementTags.BGBLUE, Color.GRAY.getBlue() );
 1015  4
         writeAddAttribute( ElementTags.BGGREEN, Color.GRAY.getGreen() );
 1016  4
         writeAddAttribute( ElementTags.HORIZONTALALIGN, ElementTags.ALIGN_CENTER );
 1017  
 
 1018  4
         actionContext.setAction( SinkActionContext.TABLE_HEADER_CELL );
 1019  4
     }
 1020  
 
 1021  
     /** {@inheritDoc} */
 1022  
     public void tableHeaderCell( String width )
 1023  
     {
 1024  0
         actionContext.setAction( SinkActionContext.TABLE_HEADER_CELL );
 1025  0
     }
 1026  
 
 1027  
     /** {@inheritDoc} */
 1028  
     public void tableRow_()
 1029  
     {
 1030  12
         writeEndElement(); // ElementTags.ROW
 1031  
 
 1032  12
         actionContext.release();
 1033  12
     }
 1034  
 
 1035  
     /** {@inheritDoc} */
 1036  
     public void tableRow()
 1037  
     {
 1038  12
         writeStartElement( ElementTags.ROW );
 1039  
 
 1040  12
         actionContext.setAction( SinkActionContext.TABLE_ROW );
 1041  12
     }
 1042  
 
 1043  
     /** {@inheritDoc} */
 1044  
     public void tableRows_()
 1045  
     {
 1046  
         //writeEndElement(); // ElementTags.TABLE
 1047  
 
 1048  6
         actionContext.release();
 1049  6
     }
 1050  
 
 1051  
     /** {@inheritDoc} */
 1052  
     public void tableRows( int[] justification, boolean grid )
 1053  
     {
 1054  
         // ElementTags.TABLE
 1055  6
         writeAddAttribute( ElementTags.COLUMNS, justification.length );
 1056  
 
 1057  6
         actionContext.setAction( SinkActionContext.TABLE_ROWS );
 1058  6
     }
 1059  
 
 1060  
     // ----------------------------------------------------------------------
 1061  
     // Verbatim
 1062  
     // ----------------------------------------------------------------------
 1063  
 
 1064  
     /** {@inheritDoc} */
 1065  
     public void verbatim_()
 1066  
     {
 1067  4
         writeEndElement(); // ElementTags.CELL
 1068  
 
 1069  4
         writeEndElement(); // ElementTags.ROW
 1070  
 
 1071  4
         writeEndElement(); // ElementTags.TABLE
 1072  
 
 1073  4
         writeEndElement(); // ElementTags.CHUNK
 1074  
 
 1075  4
         actionContext.release();
 1076  4
     }
 1077  
 
 1078  
     /** {@inheritDoc} */
 1079  
     public void verbatim( boolean boxed )
 1080  
     {
 1081  
         // Always boxed
 1082  4
         writeStartElement( ElementTags.CHUNK );
 1083  4
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1084  4
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1085  4
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1086  4
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 1087  4
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 1088  4
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 1089  
 
 1090  4
         writeStartElement( ElementTags.TABLE );
 1091  4
         writeAddAttribute( ElementTags.COLUMNS, "1" );
 1092  4
         writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
 1093  4
         writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
 1094  4
         writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
 1095  4
         writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
 1096  4
         writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
 1097  4
         writeAddAttribute( ElementTags.TABLEFITSPAGE, Boolean.TRUE.toString() );
 1098  4
         writeAddAttribute( ElementTags.CELLSFITPAGE, Boolean.TRUE.toString() );
 1099  4
         writeAddAttribute( ElementTags.CELLPADDING, "10" );
 1100  4
         writeAddAttribute( ElementTags.WIDTH, "100.0%" );
 1101  
 
 1102  4
         writeStartElement( ElementTags.ROW );
 1103  
 
 1104  4
         writeStartElement( ElementTags.CELL );
 1105  4
         writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
 1106  4
         writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
 1107  4
         writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
 1108  4
         writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
 1109  
 
 1110  4
         actionContext.setAction( SinkActionContext.VERBATIM );
 1111  4
     }
 1112  
 
 1113  
     // ----------------------------------------------------------------------
 1114  
     // Figures
 1115  
     // ----------------------------------------------------------------------
 1116  
 
 1117  
     /** {@inheritDoc} */
 1118  
     public void figure_()
 1119  
     {
 1120  2
         writeEndElement(); // ElementTags.IMAGE
 1121  
 
 1122  2
         writeEndElement(); // ElementTags.CHUNK
 1123  
 
 1124  2
         actionContext.release();
 1125  
 
 1126  2
         figureDefined = false;
 1127  2
     }
 1128  
 
 1129  
     /** {@inheritDoc} */
 1130  
     public void figure()
 1131  
     {
 1132  2
         figureDefined = true;
 1133  
 
 1134  2
         writeStartElement( ElementTags.CHUNK );
 1135  2
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1136  2
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1137  2
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1138  2
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 1139  2
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 1140  2
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 1141  
 
 1142  2
         writeStartElement( ElementTags.IMAGE );
 1143  
 
 1144  2
         actionContext.setAction( SinkActionContext.FIGURE );
 1145  2
     }
 1146  
 
 1147  
     /** {@inheritDoc} */
 1148  
     public void figureCaption_()
 1149  
     {
 1150  2
         actionContext.release();
 1151  2
     }
 1152  
 
 1153  
     /** {@inheritDoc} */
 1154  
     public void figureCaption()
 1155  
     {
 1156  2
         actionContext.setAction( SinkActionContext.FIGURE_CAPTION );
 1157  2
     }
 1158  
 
 1159  
     /**
 1160  
      * If the <code>name</code> is a relative link, the internal link will used a System property <code>itext.basedir</code>,
 1161  
      * or the class loader.
 1162  
      * {@inheritDoc} */
 1163  
     public void figureGraphics( String name )
 1164  
     {
 1165  2
         String urlName = null;
 1166  2
         File nameFile = null;
 1167  2
         if ( ( name.toLowerCase( Locale.ENGLISH ).startsWith( "http://" ) )
 1168  
             || ( name.toLowerCase( Locale.ENGLISH ).startsWith( "https://" ) ) )
 1169  
         {
 1170  0
             urlName = name;
 1171  
         }
 1172  
         else
 1173  
         {
 1174  2
             if ( System.getProperty( "itext.basedir" ) != null )
 1175  
             {
 1176  
                 try
 1177  
                 {
 1178  0
                     nameFile = new File( System.getProperty( "itext.basedir" ), name );
 1179  0
                     urlName = nameFile.toURI().toURL().toString();
 1180  
                 }
 1181  0
                 catch ( MalformedURLException e )
 1182  
                 {
 1183  0
                     getLog().error( "MalformedURLException: " + e.getMessage(), e );
 1184  0
                 }
 1185  
             }
 1186  
             else
 1187  
             {
 1188  2
                 if ( getClassLoader() != null )
 1189  
                 {
 1190  2
                     if ( getClassLoader().getResource( name ) != null )
 1191  
                     {
 1192  2
                         urlName = getClassLoader().getResource( name ).toString();
 1193  
                     }
 1194  
                 }
 1195  
                 else
 1196  
                 {
 1197  0
                     if ( ITextSink.class.getClassLoader().getResource( name ) != null )
 1198  
                     {
 1199  0
                         urlName = ITextSink.class.getClassLoader().getResource( name ).toString();
 1200  
                     }
 1201  
                 }
 1202  
             }
 1203  
         }
 1204  
 
 1205  2
         if ( urlName == null )
 1206  
         {
 1207  0
             String msg =
 1208  
                 "No image '" + name
 1209  
                     + "' found in the class loader. Try to call setClassLoader(ClassLoader) before.";
 1210  0
             logMessage( "imageNotFound", msg );
 1211  
 
 1212  0
             return;
 1213  
         }
 1214  
 
 1215  2
         if ( nameFile != null && !nameFile.exists() )
 1216  
         {
 1217  0
             String msg = "No image '" + nameFile + "' found in your system, check the path.";
 1218  0
             logMessage( "imageNotFound", msg );
 1219  
 
 1220  0
             return;
 1221  
         }
 1222  
 
 1223  2
         boolean figureCalled = figureDefined;
 1224  2
         if ( !figureCalled )
 1225  
         {
 1226  0
             figure();
 1227  
         }
 1228  
 
 1229  2
         float width = 0;
 1230  2
         float height = 0;
 1231  
         try
 1232  
         {
 1233  2
             Image image = Image.getInstance( new URL( urlName ) );
 1234  2
             image.scaleToFit( ITextUtil.getDefaultPageSize().width() / 2, ITextUtil.getDefaultPageSize().height() / 2 );
 1235  2
             width = image.plainWidth();
 1236  2
             height = image.plainHeight();
 1237  
         }
 1238  0
         catch ( BadElementException e )
 1239  
         {
 1240  0
             getLog().error( "BadElementException: " + e.getMessage(), e );
 1241  
         }
 1242  0
         catch ( MalformedURLException e )
 1243  
         {
 1244  0
             getLog().error( "MalformedURLException: " + e.getMessage(), e );
 1245  
         }
 1246  0
         catch ( IOException e )
 1247  
         {
 1248  0
             getLog().error( "IOException: " + e.getMessage(), e );
 1249  2
         }
 1250  
 
 1251  2
         writeAddAttribute( ElementTags.URL, urlName );
 1252  2
         writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_MIDDLE );
 1253  2
         writeAddAttribute( ElementTags.PLAINWIDTH, String.valueOf( width ) );
 1254  2
         writeAddAttribute( ElementTags.PLAINHEIGHT, String.valueOf( height ) );
 1255  
 
 1256  2
         actionContext.setAction( SinkActionContext.FIGURE_GRAPHICS );
 1257  
 
 1258  2
         if ( !figureCalled )
 1259  
         {
 1260  0
             figure_();
 1261  
         }
 1262  2
     }
 1263  
 
 1264  
     // ----------------------------------------------------------------------
 1265  
     // Fonts
 1266  
     // ----------------------------------------------------------------------
 1267  
 
 1268  
     /** {@inheritDoc} */
 1269  
     public void bold_()
 1270  
     {
 1271  16
         font.removeBold();
 1272  16
     }
 1273  
 
 1274  
     /** {@inheritDoc} */
 1275  
     public void bold()
 1276  
     {
 1277  16
         font.addBold();
 1278  16
     }
 1279  
 
 1280  
     /** {@inheritDoc} */
 1281  
     public void italic_()
 1282  
     {
 1283  2
         font.removeItalic();
 1284  2
     }
 1285  
 
 1286  
     /** {@inheritDoc} */
 1287  
     public void italic()
 1288  
     {
 1289  2
         font.addItalic();
 1290  2
     }
 1291  
 
 1292  
     /** {@inheritDoc} */
 1293  
     public void monospaced_()
 1294  
     {
 1295  2
         font.setMonoSpaced( false );
 1296  2
     }
 1297  
 
 1298  
     /** {@inheritDoc} */
 1299  
     public void monospaced()
 1300  
     {
 1301  2
         font.setMonoSpaced( true );
 1302  2
     }
 1303  
 
 1304  
     // ----------------------------------------------------------------------
 1305  
     // Links
 1306  
     // ----------------------------------------------------------------------
 1307  
 
 1308  
     /** {@inheritDoc} */
 1309  
     public void link_()
 1310  
     {
 1311  12
         writeEndElement(); // ElementTags.ANCHOR
 1312  
 
 1313  12
         font.setColor( Color.BLACK );
 1314  12
         font.removeUnderlined();
 1315  
 
 1316  12
         actionContext.release();
 1317  12
     }
 1318  
 
 1319  
     /** {@inheritDoc} */
 1320  
     public void link( String name )
 1321  
     {
 1322  12
         if ( name == null )
 1323  
         {
 1324  0
             throw new NullPointerException( "Link name cannot be null!" );
 1325  
         }
 1326  
 
 1327  12
         font.setColor( Color.BLUE );
 1328  12
         font.addUnderlined();
 1329  
 
 1330  12
         writeStartElement( ElementTags.ANCHOR );
 1331  12
         if ( StringUtils.isNotEmpty( name )&& name.startsWith( "#" ) && StringUtils.isNotEmpty( header.getTitle() ))
 1332  
         {
 1333  8
             name = "#" + DoxiaUtils.encodeId( header.getTitle(), true ) + "_" + name.substring( 1 );
 1334  
         }
 1335  12
         writeAddAttribute( ElementTags.REFERENCE, HtmlTools.escapeHTML( name ) );
 1336  12
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1337  12
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1338  12
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1339  12
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 1340  12
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 1341  12
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 1342  
 
 1343  12
         actionContext.setAction( SinkActionContext.LINK );
 1344  12
     }
 1345  
 
 1346  
     /** {@inheritDoc} */
 1347  
     public void anchor_()
 1348  
     {
 1349  6
         if ( !anchorDefined )
 1350  
         {
 1351  
             // itext needs a defined local destination, we put an invisible text
 1352  2
             writeAddAttribute( ElementTags.BLUE, "255" );
 1353  2
             writeAddAttribute( ElementTags.GREEN, "255" );
 1354  2
             writeAddAttribute( ElementTags.RED, "255" );
 1355  
 
 1356  2
             write( "_" );
 1357  
         }
 1358  
 
 1359  6
         anchorDefined = false;
 1360  
 
 1361  6
         writeEndElement(); // ElementTags.ANCHOR
 1362  
 
 1363  6
         actionContext.release();
 1364  6
     }
 1365  
 
 1366  
     /** {@inheritDoc} */
 1367  
     public void anchor( String name )
 1368  
     {
 1369  6
         if ( name == null )
 1370  
         {
 1371  0
             throw new NullPointerException( "Anchor name cannot be null!" );
 1372  
         }
 1373  
 
 1374  6
         if ( StringUtils.isNotEmpty( header.getTitle() ) )
 1375  
         {
 1376  6
             name = header.getTitle() + "_" + name;
 1377  
         }
 1378  6
         String id = name;
 1379  
 
 1380  6
         if ( !DoxiaUtils.isValidId( id ) )
 1381  
         {
 1382  0
             id = DoxiaUtils.encodeId( name, true );
 1383  
 
 1384  0
             String msg = "Modified invalid link: '" + name + "' to '" + id + "'";
 1385  0
             logMessage( "modifiedLink", msg );
 1386  
         }
 1387  
 
 1388  6
         writeStartElement( ElementTags.ANCHOR );
 1389  6
         writeAddAttribute( ElementTags.NAME, id );
 1390  6
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1391  6
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1392  6
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1393  
 
 1394  6
         actionContext.setAction( SinkActionContext.ANCHOR );
 1395  6
     }
 1396  
 
 1397  
     // ----------------------------------------------------------------------
 1398  
     // Misc
 1399  
     // ----------------------------------------------------------------------
 1400  
 
 1401  
     /** {@inheritDoc} */
 1402  
     public void lineBreak()
 1403  
     {
 1404  
         // Special case for the header
 1405  66
         if ( ( actionContext.getCurrentAction() == SinkActionContext.AUTHOR )
 1406  
             || ( actionContext.getCurrentAction() == SinkActionContext.DATE )
 1407  
             || ( actionContext.getCurrentAction() == SinkActionContext.TITLE ) )
 1408  
         {
 1409  0
             return;
 1410  
         }
 1411  
 
 1412  66
         writeStartElement( ElementTags.NEWLINE );
 1413  66
         writeEndElement();
 1414  66
     }
 1415  
 
 1416  
     /** {@inheritDoc} */
 1417  
     public void nonBreakingSpace()
 1418  
     {
 1419  4
         write( " " );
 1420  4
     }
 1421  
 
 1422  
     /** {@inheritDoc} */
 1423  
     public void pageBreak()
 1424  
     {
 1425  2
         writeStartElement( ElementTags.NEWPAGE );
 1426  2
         writeEndElement();
 1427  2
     }
 1428  
 
 1429  
     /** {@inheritDoc} */
 1430  
     public void horizontalRule()
 1431  
     {
 1432  2
         writeStartElement( ElementTags.PARAGRAPH );
 1433  2
         writeAddAttribute( ElementTags.BLUE, "255" );
 1434  2
         writeAddAttribute( ElementTags.GREEN, "255" );
 1435  2
         writeAddAttribute( ElementTags.RED, "255" );
 1436  2
         write( "_" );
 1437  2
         writeEndElement();
 1438  
 
 1439  2
         writeStartElement( ElementTags.PARAGRAPH );
 1440  2
         writeStartElement( ElementTags.HORIZONTALRULE );
 1441  2
         writeEndElement();
 1442  2
         writeEndElement();
 1443  2
     }
 1444  
 
 1445  
     // ----------------------------------------------------------------------
 1446  
     // Text
 1447  
     // ----------------------------------------------------------------------
 1448  
 
 1449  
     /** {@inheritDoc} */
 1450  
     public void rawText( String text )
 1451  
     {
 1452  0
         writeStartElement( ElementTags.CHUNK );
 1453  0
         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1454  0
         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1455  0
         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1456  0
         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 1457  0
         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 1458  0
         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 1459  
 
 1460  0
         write( text, false );
 1461  
 
 1462  0
         writeEndElement(); // ElementTags.CHUNK
 1463  0
     }
 1464  
 
 1465  
     /** {@inheritDoc} */
 1466  
     public void text( String text )
 1467  
     {
 1468  184
         if ( StringUtils.isEmpty( text ) )
 1469  
         {
 1470  0
             return;
 1471  
         }
 1472  
 
 1473  184
         switch ( actionContext.getCurrentAction() )
 1474  
         {
 1475  
             case SinkActionContext.AUTHOR:
 1476  4
                 header.addAuthor( text );
 1477  4
                 break;
 1478  
 
 1479  
             case SinkActionContext.DATE:
 1480  4
                 header.setDate( text );
 1481  4
                 break;
 1482  
 
 1483  
             case SinkActionContext.TITLE:
 1484  4
                 header.setTitle( text );
 1485  4
                 break;
 1486  
 
 1487  
             case SinkActionContext.TABLE_CAPTION:
 1488  2
                 this.tableCaptionXMLWriter.writeText( text );
 1489  2
                 break;
 1490  
 
 1491  
             case SinkActionContext.VERBATIM:
 1492  
                 // Used to preserve indentation and formating
 1493  4
                 LineNumberReader lnr = new LineNumberReader( new StringReader( text ) );
 1494  
                 String line;
 1495  
                 try
 1496  
                 {
 1497  10
                     while ( ( line = lnr.readLine() ) != null )
 1498  
                     {
 1499  6
                         writeStartElement( ElementTags.CHUNK );
 1500  6
                         writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1501  6
                         writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1502  6
                         writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1503  6
                         writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 1504  6
                         writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 1505  6
                         writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 1506  
 
 1507  6
                         write( "<![CDATA[", true );
 1508  
                         // Special case
 1509  6
                         line = StringUtils.replace( line, "<![CDATA[", "< ![CDATA[" );
 1510  6
                         line = StringUtils.replace( line, "]]>", "]] >" );
 1511  6
                         write( line, true, false );
 1512  6
                         write( "]]>", true );
 1513  
 
 1514  6
                         writeEndElement();
 1515  6
                         lineBreak();
 1516  
                     }
 1517  
                 }
 1518  0
                 catch ( IOException e )
 1519  
                 {
 1520  0
                     throw new RuntimeException( "IOException: ", e );
 1521  4
                 }
 1522  
                 break;
 1523  
 
 1524  
             case SinkActionContext.FIGURE_CAPTION:
 1525  2
                 writeAddAttribute( ElementTags.ALT, text );
 1526  2
                 break;
 1527  
 
 1528  
             case SinkActionContext.SECTION_TITLE:
 1529  
             case SinkActionContext.SECTION_1:
 1530  
             case SinkActionContext.SECTION_2:
 1531  
             case SinkActionContext.SECTION_3:
 1532  
             case SinkActionContext.SECTION_4:
 1533  
             case SinkActionContext.SECTION_5:
 1534  
             case SinkActionContext.FIGURE:
 1535  
             case SinkActionContext.FIGURE_GRAPHICS:
 1536  
             case SinkActionContext.TABLE_ROW:
 1537  
             case SinkActionContext.TABLE:
 1538  
             case SinkActionContext.HEAD:
 1539  
             case SinkActionContext.UNDEFINED:
 1540  0
                 break;
 1541  
 
 1542  
             case SinkActionContext.ANCHOR:
 1543  4
                 anchorDefined = true;
 1544  
             case SinkActionContext.PARAGRAPH:
 1545  
             case SinkActionContext.LINK:
 1546  
             case SinkActionContext.TABLE_CELL:
 1547  
             case SinkActionContext.TABLE_HEADER_CELL:
 1548  
             case SinkActionContext.DEFINITION:
 1549  
             case SinkActionContext.DEFINED_TERM:
 1550  
             case SinkActionContext.NUMBERED_LIST_ITEM:
 1551  
             case SinkActionContext.LIST_ITEM:
 1552  
             case SinkActionContext.SECTION_TITLE_5:
 1553  
             case SinkActionContext.SECTION_TITLE_4:
 1554  
             case SinkActionContext.SECTION_TITLE_3:
 1555  
             case SinkActionContext.SECTION_TITLE_2:
 1556  
             case SinkActionContext.SECTION_TITLE_1:
 1557  
             default:
 1558  164
                 writeStartElement( ElementTags.CHUNK );
 1559  164
                 writeAddAttribute( ElementTags.FONT, font.getFontName() );
 1560  164
                 writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
 1561  164
                 writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
 1562  164
                 writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
 1563  164
                 writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
 1564  164
                 writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
 1565  
 
 1566  164
                 write( text );
 1567  
 
 1568  164
                 writeEndElement(); // ElementTags.CHUNK
 1569  
         }
 1570  184
     }
 1571  
 
 1572  
     /**
 1573  
      * {@inheritDoc}
 1574  
      *
 1575  
      * Unkown events just log a warning message but are ignored otherwise.
 1576  
      * @see org.apache.maven.doxia.sink.Sink#unknown(String,Object[],SinkEventAttributes)
 1577  
      */
 1578  
     public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes )
 1579  
     {
 1580  0
         String msg = "Unknown Sink event: '" + name + "', ignoring!";
 1581  0
         logMessage( "unknownEvent", msg );
 1582  0
     }
 1583  
 
 1584  
     /** {@inheritDoc} */
 1585  
     protected void init()
 1586  
     {
 1587  8
         super.init();
 1588  
 
 1589  8
         this.actionContext = new SinkActionContext();
 1590  8
         this.font = new ITextFont();
 1591  8
         this.header = new ITextHeader();
 1592  
 
 1593  8
         this.numberDepth = 1;
 1594  8
         this.depth = 0;
 1595  8
         this.tableCaptionWriter = null;
 1596  8
         this.tableCaptionXMLWriter = null;
 1597  8
         this.anchorDefined = false;
 1598  8
         this.figureDefined = false;
 1599  8
         this.warnMessages = null;
 1600  8
     }
 1601  
 
 1602  
     /**
 1603  
      * Convenience method to write a starting element.
 1604  
      *
 1605  
      * @param tag the name of the tag
 1606  
      */
 1607  
     private void writeStartElement( String tag )
 1608  
     {
 1609  470
         if ( tableCaptionXMLWriter == null )
 1610  
         {
 1611  470
             xmlWriter.startElement( tag );
 1612  
         }
 1613  
         else
 1614  
         {
 1615  0
             tableCaptionXMLWriter.startElement( tag );
 1616  
         }
 1617  470
     }
 1618  
 
 1619  
     /**
 1620  
      * Convenience method to write a key-value pair.
 1621  
      *
 1622  
      * @param key the name of an attribute
 1623  
      * @param value the value of an attribute
 1624  
      */
 1625  
     private void writeAddAttribute( String key, String value )
 1626  
     {
 1627  1772
         if ( tableCaptionXMLWriter == null )
 1628  
         {
 1629  1772
             xmlWriter.addAttribute( key, value );
 1630  
         }
 1631  
         else
 1632  
         {
 1633  0
             tableCaptionXMLWriter.addAttribute( key, value );
 1634  
         }
 1635  1772
     }
 1636  
 
 1637  
     /**
 1638  
      * Convenience method to write a key-value pair.
 1639  
      *
 1640  
      * @param key the name of an attribute
 1641  
      * @param value the value of an attribute
 1642  
      */
 1643  
     private void writeAddAttribute( String key, int value )
 1644  
     {
 1645  80
         if ( tableCaptionXMLWriter == null )
 1646  
         {
 1647  80
             xmlWriter.addAttribute( key, String.valueOf( value ) );
 1648  
         }
 1649  
         else
 1650  
         {
 1651  0
             tableCaptionXMLWriter.addAttribute( key, String.valueOf( value ) );
 1652  
         }
 1653  80
     }
 1654  
 
 1655  
     /**
 1656  
      * Convenience method to write an end element.
 1657  
      */
 1658  
     private void writeEndElement()
 1659  
     {
 1660  470
         if ( tableCaptionXMLWriter == null )
 1661  
         {
 1662  470
             xmlWriter.endElement();
 1663  
         }
 1664  
         else
 1665  
         {
 1666  0
             tableCaptionXMLWriter.endElement();
 1667  
         }
 1668  470
     }
 1669  
 
 1670  
     /**
 1671  
      * Convenience method to write a String
 1672  
      *
 1673  
      * @param aString
 1674  
      */
 1675  
     protected void write( String aString )
 1676  
     {
 1677  176
         write( aString, false );
 1678  176
     }
 1679  
 
 1680  
     /**
 1681  
      * Convenience method to write a String depending the escapeHtml flag
 1682  
      *
 1683  
      * @param aString
 1684  
      * @param escapeHtml
 1685  
      */
 1686  
     private void write( String aString, boolean escapeHtml )
 1687  
     {
 1688  190
         write( aString, escapeHtml, true );
 1689  190
     }
 1690  
 
 1691  
     /**
 1692  
      * Convenience method to write a String depending the escapeHtml flag
 1693  
      *
 1694  
      * @param aString
 1695  
      * @param escapeHtml
 1696  
      * @param trim
 1697  
      */
 1698  
     private void write( String aString, boolean escapeHtml, boolean trim )
 1699  
     {
 1700  200
         if ( aString == null )
 1701  
         {
 1702  0
             return;
 1703  
         }
 1704  
 
 1705  200
         if ( trim )
 1706  
         {
 1707  190
             aString = StringUtils.replace( aString, "\n", "" );
 1708  
 
 1709  190
             LineNumberReader lnr = new LineNumberReader( new StringReader( aString ) );
 1710  190
             StringBuffer sb = new StringBuffer();
 1711  
             String line;
 1712  
             try
 1713  
             {
 1714  380
                 while ( ( line = lnr.readLine() ) != null )
 1715  
                 {
 1716  190
                     sb.append( beautifyPhrase( line.trim() ) );
 1717  190
                     sb.append( " " );
 1718  
                 }
 1719  
 
 1720  190
                 aString = sb.toString();
 1721  
             }
 1722  0
             catch ( IOException e )
 1723  
             {
 1724  
                 // nop
 1725  190
             }
 1726  190
             if ( aString.trim().length() == 0 )
 1727  
             {
 1728  4
                 return;
 1729  
             }
 1730  
         }
 1731  196
         if ( escapeHtml )
 1732  
         {
 1733  20
             if ( tableCaptionXMLWriter == null )
 1734  
             {
 1735  20
                 xmlWriter.writeMarkup( aString );
 1736  
             }
 1737  
             else
 1738  
             {
 1739  0
                 tableCaptionXMLWriter.writeMarkup( aString );
 1740  
             }
 1741  
         }
 1742  
         else
 1743  
         {
 1744  176
             if ( tableCaptionXMLWriter == null )
 1745  
             {
 1746  176
                 xmlWriter.writeText( aString );
 1747  
             }
 1748  
             else
 1749  
             {
 1750  0
                 tableCaptionXMLWriter.writeText( aString );
 1751  
             }
 1752  
         }
 1753  196
     }
 1754  
 
 1755  
     /**
 1756  
      * Convenience method to return a beautify phrase, i.e. one space between words.
 1757  
      *
 1758  
      * @param aString
 1759  
      * @return a String with only one space between words
 1760  
      */
 1761  
     private static String beautifyPhrase( String aString )
 1762  
     {
 1763  190
         String[] strings = StringUtils.split( aString, " " );
 1764  190
         StringBuffer sb = new StringBuffer();
 1765  592
         for ( int i = 0; i < strings.length; i++ )
 1766  
         {
 1767  402
             if ( strings[i].trim().length() != 0 )
 1768  
             {
 1769  402
                 sb.append( strings[i].trim() );
 1770  402
                 sb.append( " " );
 1771  
             }
 1772  
         }
 1773  
 
 1774  190
         return sb.toString().trim();
 1775  
     }
 1776  
 
 1777  
     private void startChunk( String fontName, int fontSize, String fontStyle, int fontColorBlue, int fontColorGreen,
 1778  
                              int fontColorRed, String localDestination )
 1779  
     {
 1780  0
         writeStartElement( ElementTags.CHUNK );
 1781  0
         writeAddAttribute( ElementTags.FONT, fontName );
 1782  0
         writeAddAttribute( ElementTags.SIZE, fontSize );
 1783  0
         writeAddAttribute( ElementTags.STYLE, fontStyle );
 1784  0
         writeAddAttribute( ElementTags.BLUE, fontColorBlue );
 1785  0
         writeAddAttribute( ElementTags.GREEN, fontColorGreen );
 1786  0
         writeAddAttribute( ElementTags.RED, fontColorRed );
 1787  
 //        writeAddAttribute( ElementTags.LOCALDESTINATION, localDestination );
 1788  0
     }
 1789  
 
 1790  
     /**
 1791  
      * If debug mode is enabled, log the <code>msg</code> as is, otherwise add unique msg in <code>warnMessages</code>.
 1792  
      *
 1793  
      * @param key not null
 1794  
      * @param msg not null
 1795  
      * @see #close()
 1796  
      * @since 1.1.1
 1797  
      */
 1798  
     private void logMessage( String key, String msg )
 1799  
     {
 1800  0
         msg = "[iText Sink] " + msg;
 1801  0
         if ( getLog().isDebugEnabled() )
 1802  
         {
 1803  0
             getLog().debug( msg );
 1804  
 
 1805  0
             return;
 1806  
         }
 1807  
 
 1808  0
         if ( warnMessages == null )
 1809  
         {
 1810  0
             warnMessages = new HashMap<String, Set<String>>();
 1811  
         }
 1812  
 
 1813  0
         Set<String> set = warnMessages.get( key );
 1814  0
         if ( set == null )
 1815  
         {
 1816  0
             set = new TreeSet<String>();
 1817  
         }
 1818  0
         set.add( msg );
 1819  0
         warnMessages.put( key, set );
 1820  0
     }
 1821  
 }