blob: 92771c0a1351573b5cc80fb192788376ed04d4ce [file] [log] [blame]
package org.apache.maven.doxia.module.itext;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import com.lowagie.text.BadElementException;
import com.lowagie.text.ElementTags;
import com.lowagie.text.Image;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.SinkEventAttributes;
import org.apache.maven.doxia.sink.impl.AbstractXmlSink;
import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
import org.apache.maven.doxia.util.DoxiaUtils;
import org.apache.maven.doxia.util.HtmlTools;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.XMLWriter;
/**
* <p>A doxia Sink which produces an XML Front End document for <code>iText</code> framework.</p>
* Known limitations:
* <ul>
* <li>Roman lists are not supported.</li>
* <li>Horizontal rule is not supported with 1.3.
* See <a href="http://www.mail-archive.com/itext-questions@lists.sourceforge.net/msg10323.html">
* http://www.mail-archive.com/itext-questions@lists.sourceforge.net/msg10323.html</a></li>
* <li>iText has some problems with <code>ElementTags.TABLE</code> and <code>ElementTags.TABLEFITSPAGE</code>.
* See <a href="http://sourceforge.net/tracker/index.php?func=detail&aid=786427&group_id=15255&atid=115255">
* SourceForce Tracker</a>.</li>
* <li>Images could be on another page and next text on the last one.</li>
* </ul>
*
* @see <a href="http://www.lowagie.com/iText/tutorial/ch07.html">http://www.lowagie.com/iText/tutorial/ch07.html</a>
*
* @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
* @version $Id$
*/
public class ITextSink
extends AbstractXmlSink
{
/** This is the place where the iText DTD is located. IMPORTANT: this DTD is not uptodate! */
public static final String DTD = "http://itext.sourceforge.net/itext.dtd";
/** This is the reference to the DTD. */
public static final String DOCTYPE = "ITEXT SYSTEM \"" + DTD + "\"";
/** This is the default leading for chapter title */
public static final String DEFAULT_CHAPTER_TITLE_LEADING = "36.0";
/** This is the default leading for section title */
public static final String DEFAULT_SECTION_TITLE_LEADING = "24.0";
/** The ClassLoader used */
private ClassLoader currentClassLoader;
/** The action context */
private SinkActionContext actionContext;
/** The Writer used */
private Writer writer;
/** The XML Writer used */
private final XMLWriter xmlWriter;
private boolean writeStart;
/** The Header object */
private ITextHeader header;
/** The font object */
private ITextFont font;
private int numberDepth = 1;
private int depth = 0;
private StringWriter tableCaptionWriter = null;
private XMLWriter tableCaptionXMLWriter = null;
/** Flag to know if an anchor is defined or not. Used as workaround for iText which needs a defined local
* destination. */
private boolean anchorDefined = false;
/** Flag to know if an figure event is called. */
private boolean figureDefined = false;
/** Keep track of the closing tags for inline events. */
protected Stack<List<String>> inlineStack = new Stack<>();
/** Map of warn messages with a String as key to describe the error type and a Set as value.
* Using to reduce warn messages. */
private Map<String, Set<String>> warnMessages;
/**
* <p>Constructor for ITextSink.</p>
*
* @param writer the writer.
*/
protected ITextSink( Writer writer )
{
this( writer, "UTF-8" );
}
/**
* <p>Constructor for ITextSink.</p>
*
* @param writer the writer.
* @param encoding the encoding.
* @since 1.1
*/
protected ITextSink( Writer writer, String encoding )
{
// No doctype since itext doctype is not up to date!
this( new PrettyPrintXMLWriter( writer, encoding, null ) );
this.writer = writer;
this.writeStart = true;
}
/**
* <p>Constructor for ITextSink.</p>
*
* @param xmlWriter a pretty-printing xml writer.
*/
protected ITextSink( PrettyPrintXMLWriter xmlWriter )
{
this.xmlWriter = xmlWriter;
this.writeStart = false;
init();
}
/**
* Get the current classLoader
*
* @return the current class loader
*/
public ClassLoader getClassLoader()
{
return currentClassLoader;
}
/**
* Set a new class loader
*
* @param cl the class loader.
*/
public void setClassLoader( ClassLoader cl )
{
currentClassLoader = cl;
}
// ----------------------------------------------------------------------
// Document
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void close()
{
IOUtil.close( writer );
init();
}
/** {@inheritDoc} */
public void flush()
{
if ( getLog().isWarnEnabled() && this.warnMessages != null )
{
for ( Map.Entry<String, Set<String>> entry : this.warnMessages.entrySet() )
{
for ( String msg : entry.getValue() )
{
getLog().warn( msg );
}
}
}
this.warnMessages = null;
}
// ----------------------------------------------------------------------
// Header
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void head_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void head()
{
//init(); // why? this causes DOXIA-413
actionContext.setAction( SinkActionContext.HEAD );
}
/** {@inheritDoc} */
public void author_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void author()
{
actionContext.setAction( SinkActionContext.AUTHOR );
}
/** {@inheritDoc} */
public void date_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void date()
{
actionContext.setAction( SinkActionContext.DATE );
}
/** {@inheritDoc} */
public void title_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void title()
{
actionContext.setAction( SinkActionContext.TITLE );
}
// ----------------------------------------------------------------------
// Body
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void body_()
{
if ( writeStart )
{
writeEndElement(); // ElementTags.CHAPTER
writeEndElement(); // ElementTags.ITEXT
}
actionContext.release();
}
/** {@inheritDoc} */
public void body()
{
if ( writeStart )
{
writeStartElement( ElementTags.ITEXT );
writeAddAttribute( ElementTags.TITLE, header.getTitle() );
writeAddAttribute( ElementTags.AUTHOR, header.getAuthors() );
writeAddAttribute( ElementTags.CREATIONDATE, header.getDate() );
writeAddAttribute( ElementTags.SUBJECT, header.getTitle() );
writeAddAttribute( ElementTags.KEYWORDS, "" );
writeAddAttribute( ElementTags.PRODUCER, "Generated with Doxia by " + System.getProperty( "user.name" ) );
writeAddAttribute( ElementTags.PAGE_SIZE, ITextUtil.getPageSize( ITextUtil.getDefaultPageSize() ) );
writeStartElement( ElementTags.CHAPTER );
writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
writeAddAttribute( ElementTags.DEPTH, depth );
writeAddAttribute( ElementTags.INDENT, "0.0" );
writeStartElement( ElementTags.TITLE );
writeAddAttribute( ElementTags.LEADING, DEFAULT_CHAPTER_TITLE_LEADING );
writeAddAttribute( ElementTags.FONT, ITextFont.DEFAULT_FONT_NAME );
writeAddAttribute( ElementTags.SIZE, ITextFont.getSectionFontSize( 0 ) );
writeAddAttribute( ElementTags.STYLE, ITextFont.BOLD );
writeAddAttribute( ElementTags.BLUE, ITextFont.DEFAULT_FONT_COLOR_BLUE );
writeAddAttribute( ElementTags.GREEN, ITextFont.DEFAULT_FONT_COLOR_GREEN );
writeAddAttribute( ElementTags.RED, ITextFont.DEFAULT_FONT_COLOR_RED );
writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
// startChunk( ITextFont.DEFAULT_FONT_NAME, ITextFont.getSectionFontSize( 0 ),
// ITextFont.BOLD, ITextFont.DEFAULT_FONT_COLOR_BLUE, ITextFont.DEFAULT_FONT_COLOR_GREEN,
// ITextFont.DEFAULT_FONT_COLOR_RED, "top" );
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, ITextFont.DEFAULT_FONT_NAME );
writeAddAttribute( ElementTags.SIZE, ITextFont.getSectionFontSize( 0 ) );
writeAddAttribute( ElementTags.STYLE, ITextFont.BOLD );
writeAddAttribute( ElementTags.BLUE, ITextFont.DEFAULT_FONT_COLOR_BLUE );
writeAddAttribute( ElementTags.GREEN, ITextFont.DEFAULT_FONT_COLOR_GREEN );
writeAddAttribute( ElementTags.RED, ITextFont.DEFAULT_FONT_COLOR_RED );
// writeAddAttribute( ElementTags.LOCALDESTINATION, "top" );
write( header.getTitle() );
writeEndElement(); // ElementTags.CHUNK
writeEndElement(); // ElementTags.TITLE
}
actionContext.setAction( SinkActionContext.BODY );
}
// ----------------------------------------------------------------------
// Sections
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void sectionTitle()
{
actionContext.release();
}
/** {@inheritDoc} */
public void sectionTitle_()
{
actionContext.setAction( SinkActionContext.SECTION_TITLE );
}
/** {@inheritDoc} */
public void section1_()
{
writeEndElement(); // ElementTags.SECTION
numberDepth--;
depth = 0;
actionContext.release();
}
/** {@inheritDoc} */
public void section1()
{
numberDepth++;
depth = 1;
writeStartElement( ElementTags.SECTION );
writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
writeAddAttribute( ElementTags.DEPTH, depth );
writeAddAttribute( ElementTags.INDENT, "0.0" );
lineBreak();
actionContext.setAction( SinkActionContext.SECTION_1 );
}
/** {@inheritDoc} */
public void sectionTitle1_()
{
writeEndElement(); // ElementTags.TITLE
font.setSize( ITextFont.DEFAULT_FONT_SIZE );
bold_();
actionContext.release();
}
/** {@inheritDoc} */
public void sectionTitle1()
{
font.setSize( ITextFont.getSectionFontSize( 1 ) );
font.setColor( Color.BLACK );
bold();
writeStartElement( ElementTags.TITLE );
writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
// writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
actionContext.setAction( SinkActionContext.SECTION_TITLE_1 );
}
/** {@inheritDoc} */
public void section2_()
{
writeEndElement(); // ElementTags.SECTION
numberDepth--;
depth = 0;
actionContext.release();
}
/** {@inheritDoc} */
public void section2()
{
numberDepth++;
depth = 1;
writeStartElement( ElementTags.SECTION );
writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
writeAddAttribute( ElementTags.DEPTH, depth );
writeAddAttribute( ElementTags.INDENT, "0.0" );
lineBreak();
actionContext.setAction( SinkActionContext.SECTION_2 );
}
/** {@inheritDoc} */
public void sectionTitle2_()
{
writeEndElement(); // ElementTags.TITLE
font.setSize( ITextFont.DEFAULT_FONT_SIZE );
bold_();
actionContext.release();
}
/** {@inheritDoc} */
public void sectionTitle2()
{
font.setSize( ITextFont.getSectionFontSize( 2 ) );
font.setColor( Color.BLACK );
bold();
writeStartElement( ElementTags.TITLE );
writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
// writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
actionContext.setAction( SinkActionContext.SECTION_TITLE_2 );
}
/** {@inheritDoc} */
public void section3_()
{
writeEndElement(); // ElementTags.SECTION
numberDepth--;
depth = 1;
actionContext.release();
}
/** {@inheritDoc} */
public void section3()
{
numberDepth++;
depth = 1;
writeStartElement( ElementTags.SECTION );
writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
writeAddAttribute( ElementTags.DEPTH, depth );
writeAddAttribute( ElementTags.INDENT, "0.0" );
lineBreak();
actionContext.setAction( SinkActionContext.SECTION_3 );
}
/** {@inheritDoc} */
public void sectionTitle3_()
{
writeEndElement(); // ElementTags.TITLE
font.setSize( ITextFont.DEFAULT_FONT_SIZE );
bold_();
actionContext.release();
}
/** {@inheritDoc} */
public void sectionTitle3()
{
font.setSize( ITextFont.getSectionFontSize( 3 ) );
font.setColor( Color.BLACK );
bold();
writeStartElement( ElementTags.TITLE );
writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
// writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
actionContext.setAction( SinkActionContext.SECTION_TITLE_3 );
}
/** {@inheritDoc} */
public void section4_()
{
writeEndElement(); // ElementTags.SECTION
numberDepth--;
depth = 1;
actionContext.release();
}
/** {@inheritDoc} */
public void section4()
{
numberDepth++;
depth = 1;
writeStartElement( ElementTags.SECTION );
writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
writeAddAttribute( ElementTags.DEPTH, depth );
writeAddAttribute( ElementTags.INDENT, "0.0" );
lineBreak();
actionContext.setAction( SinkActionContext.SECTION_4 );
}
/** {@inheritDoc} */
public void sectionTitle4_()
{
writeEndElement(); // ElementTags.TITLE
font.setSize( ITextFont.DEFAULT_FONT_SIZE );
bold_();
actionContext.release();
}
/** {@inheritDoc} */
public void sectionTitle4()
{
font.setSize( ITextFont.getSectionFontSize( 4 ) );
font.setColor( Color.BLACK );
bold();
writeStartElement( ElementTags.TITLE );
writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
// writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
actionContext.setAction( SinkActionContext.SECTION_TITLE_4 );
}
/** {@inheritDoc} */
public void section5_()
{
writeEndElement(); // ElementTags.SECTION
numberDepth--;
depth = 1;
actionContext.release();
}
/** {@inheritDoc} */
public void section5()
{
numberDepth++;
depth = 1;
writeStartElement( ElementTags.SECTION );
writeAddAttribute( ElementTags.NUMBERDEPTH, numberDepth );
writeAddAttribute( ElementTags.DEPTH, depth );
writeAddAttribute( ElementTags.INDENT, "0.0" );
lineBreak();
actionContext.setAction( SinkActionContext.SECTION_5 );
}
/** {@inheritDoc} */
public void sectionTitle5_()
{
writeEndElement(); // ElementTags.TITLE
font.setSize( ITextFont.DEFAULT_FONT_SIZE );
bold_();
actionContext.release();
}
/** {@inheritDoc} */
public void sectionTitle5()
{
font.setSize( ITextFont.getSectionFontSize( 5 ) );
font.setColor( Color.BLACK );
bold();
writeStartElement( ElementTags.TITLE );
writeAddAttribute( ElementTags.LEADING, DEFAULT_SECTION_TITLE_LEADING );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
// writeAddAttribute( ElementTags.LOCALDESTINATION, "top" ); // trygve
actionContext.setAction( SinkActionContext.SECTION_TITLE_5 );
}
// ----------------------------------------------------------------------
// Paragraph
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void paragraph_()
{
// Special case
if ( ( actionContext.getCurrentAction() == SinkActionContext.LIST_ITEM )
|| ( actionContext.getCurrentAction() == SinkActionContext.NUMBERED_LIST_ITEM )
|| ( actionContext.getCurrentAction() == SinkActionContext.DEFINITION ) )
{
return;
}
writeEndElement(); // ElementTags.PARAGRAPH
actionContext.release();
}
/** {@inheritDoc} */
public void paragraph()
{
// Special case
if ( ( actionContext.getCurrentAction() == SinkActionContext.LIST_ITEM )
|| ( actionContext.getCurrentAction() == SinkActionContext.NUMBERED_LIST_ITEM )
|| ( actionContext.getCurrentAction() == SinkActionContext.DEFINITION ) )
{
return;
}
writeStartElement( ElementTags.PARAGRAPH );
writeStartElement( ElementTags.NEWLINE );
writeEndElement();
actionContext.setAction( SinkActionContext.PARAGRAPH );
}
// ----------------------------------------------------------------------
// Lists
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void list_()
{
writeEndElement(); // ElementTags.LIST
writeEndElement(); // ElementTags.CHUNK
actionContext.release();
}
/** {@inheritDoc} */
public void list()
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
writeStartElement( ElementTags.LIST );
writeAddAttribute( ElementTags.NUMBERED, Boolean.FALSE.toString() );
writeAddAttribute( ElementTags.SYMBOLINDENT, "15" );
actionContext.setAction( SinkActionContext.LIST );
}
/** {@inheritDoc} */
public void listItem_()
{
writeEndElement(); // ElementTags.LISTITEM
actionContext.release();
}
/** {@inheritDoc} */
public void listItem()
{
writeStartElement( ElementTags.LISTITEM );
writeAddAttribute( ElementTags.INDENTATIONLEFT, "20.0" );
actionContext.setAction( SinkActionContext.LIST_ITEM );
}
/** {@inheritDoc} */
public void numberedList_()
{
writeEndElement(); // ElementTags.LIST
writeEndElement(); // ElementTags.CHUNK
actionContext.release();
}
/** {@inheritDoc} */
public void numberedList( int numbering )
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
writeStartElement( ElementTags.LIST );
writeAddAttribute( ElementTags.NUMBERED, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.SYMBOLINDENT, "20" );
switch ( numbering )
{
case Sink.NUMBERING_UPPER_ALPHA:
writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.FIRST, 'A' );
break;
case Sink.NUMBERING_LOWER_ALPHA:
writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.FIRST, 'a' );
break;
// TODO Doesn't work
case Sink.NUMBERING_UPPER_ROMAN:
writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.FIRST, 'I' );
break;
case Sink.NUMBERING_LOWER_ROMAN:
writeAddAttribute( ElementTags.LETTERED, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.FIRST, 'i' );
break;
case Sink.NUMBERING_DECIMAL:
default:
writeAddAttribute( ElementTags.LETTERED, Boolean.FALSE.toString() );
}
actionContext.setAction( SinkActionContext.NUMBERED_LIST );
}
/** {@inheritDoc} */
public void numberedListItem_()
{
writeEndElement(); // ElementTags.LISTITEM
actionContext.release();
}
/** {@inheritDoc} */
public void numberedListItem()
{
writeStartElement( ElementTags.LISTITEM );
writeAddAttribute( ElementTags.INDENTATIONLEFT, "20" );
actionContext.setAction( SinkActionContext.NUMBERED_LIST_ITEM );
}
/** {@inheritDoc} */
public void definitionList_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void definitionList()
{
lineBreak();
actionContext.setAction( SinkActionContext.DEFINITION_LIST );
}
/** {@inheritDoc} */
public void definedTerm_()
{
font.setSize( ITextFont.DEFAULT_FONT_SIZE );
bold_();
writeEndElement(); // ElementTags.CHUNK
actionContext.release();
lineBreak();
}
/** {@inheritDoc} */
public void definedTerm()
{
font.setSize( ITextFont.DEFAULT_FONT_SIZE + 2 );
bold();
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
actionContext.setAction( SinkActionContext.DEFINED_TERM );
}
/** {@inheritDoc} */
public void definition_()
{
writeEndElement(); // ElementTags.CHUNK
actionContext.release();
lineBreak();
}
/** {@inheritDoc} */
public void definition()
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
// We need to add a non break space first to display empty string
write( "\u00A0" + StringUtils.repeat( " ", 16 ), false, false );
writeEndElement(); // ElementTags.CHUNK
actionContext.setAction( SinkActionContext.DEFINITION );
}
/** {@inheritDoc} */
public void definitionListItem_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void definitionListItem()
{
actionContext.setAction( SinkActionContext.DEFINITION_LIST_ITEM );
}
// ----------------------------------------------------------------------
// Tables
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void table_()
{
if ( tableCaptionXMLWriter != null )
{
tableCaptionXMLWriter = null;
writeEndElement(); // ElementTags.TABLE
writeEndElement(); // ElementTags.CHUNK
writeStartElement( ElementTags.PARAGRAPH );
writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
write( tableCaptionWriter.toString(), true );
writeEndElement(); // ElementTags.PARAGRAPH
tableCaptionWriter = null;
}
else
{
writeEndElement(); // ElementTags.TABLE
writeEndElement(); // ElementTags.CHUNK
}
actionContext.release();
}
/** {@inheritDoc} */
public void table()
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
writeStartElement( ElementTags.TABLE );
writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
writeAddAttribute( ElementTags.WIDTH, "100.0%" );
writeAddAttribute( ElementTags.TABLEFITSPAGE, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.CELLSFITPAGE, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.CELLPADDING, "10" );
//writeAddAttribute( ElementTags.COLUMNS, "2" );
actionContext.setAction( SinkActionContext.TABLE );
}
/** {@inheritDoc} */
public void tableCaption_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void tableCaption()
{
tableCaptionWriter = new StringWriter();
tableCaptionXMLWriter = new PrettyPrintXMLWriter( tableCaptionWriter );
actionContext.setAction( SinkActionContext.TABLE_CAPTION );
}
/** {@inheritDoc} */
public void tableCell_()
{
writeEndElement(); // ElementTags.CELL
actionContext.release();
}
/** {@inheritDoc} */
public void tableCell()
{
writeStartElement( ElementTags.CELL );
writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.HORIZONTALALIGN, ElementTags.ALIGN_LEFT );
actionContext.setAction( SinkActionContext.TABLE_CELL );
}
/** {@inheritDoc} */
public void tableCell( String width )
{
actionContext.setAction( SinkActionContext.TABLE_CELL );
}
/** {@inheritDoc} */
public void tableHeaderCell_()
{
writeEndElement(); // ElementTags.CELL
actionContext.release();
}
/** {@inheritDoc} */
public void tableHeaderCell()
{
writeStartElement( ElementTags.CELL );
writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.HEADER, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.BGRED, Color.GRAY.getRed() );
writeAddAttribute( ElementTags.BGBLUE, Color.GRAY.getBlue() );
writeAddAttribute( ElementTags.BGGREEN, Color.GRAY.getGreen() );
writeAddAttribute( ElementTags.HORIZONTALALIGN, ElementTags.ALIGN_CENTER );
actionContext.setAction( SinkActionContext.TABLE_HEADER_CELL );
}
/** {@inheritDoc} */
public void tableHeaderCell( String width )
{
actionContext.setAction( SinkActionContext.TABLE_HEADER_CELL );
}
/** {@inheritDoc} */
public void tableRow_()
{
writeEndElement(); // ElementTags.ROW
actionContext.release();
}
/** {@inheritDoc} */
public void tableRow()
{
writeStartElement( ElementTags.ROW );
actionContext.setAction( SinkActionContext.TABLE_ROW );
}
/** {@inheritDoc} */
public void tableRows_()
{
//writeEndElement(); // ElementTags.TABLE
actionContext.release();
}
/** {@inheritDoc} */
public void tableRows( int[] justification, boolean grid )
{
// ElementTags.TABLE
writeAddAttribute( ElementTags.COLUMNS, justification.length );
actionContext.setAction( SinkActionContext.TABLE_ROWS );
}
// ----------------------------------------------------------------------
// Verbatim
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void verbatim_()
{
writeEndElement(); // ElementTags.CELL
writeEndElement(); // ElementTags.ROW
writeEndElement(); // ElementTags.TABLE
writeEndElement(); // ElementTags.CHUNK
actionContext.release();
}
/** {@inheritDoc} */
public void verbatim( boolean boxed )
{
// Always boxed
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
writeStartElement( ElementTags.TABLE );
writeAddAttribute( ElementTags.COLUMNS, "1" );
writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_CENTER );
writeAddAttribute( ElementTags.TABLEFITSPAGE, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.CELLSFITPAGE, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.CELLPADDING, "10" );
writeAddAttribute( ElementTags.WIDTH, "100.0%" );
writeStartElement( ElementTags.ROW );
writeStartElement( ElementTags.CELL );
writeAddAttribute( ElementTags.LEFT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.RIGHT, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.TOP, Boolean.TRUE.toString() );
writeAddAttribute( ElementTags.BOTTOM, Boolean.TRUE.toString() );
actionContext.setAction( SinkActionContext.VERBATIM );
}
// ----------------------------------------------------------------------
// Figures
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void figure_()
{
writeEndElement(); // ElementTags.IMAGE
writeEndElement(); // ElementTags.CHUNK
actionContext.release();
figureDefined = false;
}
/** {@inheritDoc} */
public void figure()
{
figureDefined = true;
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
writeStartElement( ElementTags.IMAGE );
actionContext.setAction( SinkActionContext.FIGURE );
}
/** {@inheritDoc} */
public void figureCaption_()
{
actionContext.release();
}
/** {@inheritDoc} */
public void figureCaption()
{
actionContext.setAction( SinkActionContext.FIGURE_CAPTION );
}
/**
* If the <code>name</code> is a relative link, the internal link will used a System property
* <code>itext.basedir</code>, or the class loader.
* {@inheritDoc}
*/
public void figureGraphics( String name )
{
String urlName = null;
File nameFile = null;
if ( ( name.toLowerCase( Locale.ENGLISH ).startsWith( "http://" ) )
|| ( name.toLowerCase( Locale.ENGLISH ).startsWith( "https://" ) ) )
{
urlName = name;
}
else
{
if ( System.getProperty( "itext.basedir" ) != null )
{
try
{
nameFile = new File( System.getProperty( "itext.basedir" ), name );
urlName = nameFile.toURI().toURL().toString();
}
catch ( MalformedURLException e )
{
getLog().error( "MalformedURLException: " + e.getMessage(), e );
}
}
else
{
if ( getClassLoader() != null )
{
if ( getClassLoader().getResource( name ) != null )
{
urlName = getClassLoader().getResource( name ).toString();
}
}
else
{
if ( ITextSink.class.getClassLoader().getResource( name ) != null )
{
urlName = ITextSink.class.getClassLoader().getResource( name ).toString();
}
}
}
}
if ( urlName == null )
{
String msg =
"No image '" + name
+ "' found in the class loader. Try to call setClassLoader(ClassLoader) before.";
logMessage( "imageNotFound", msg );
return;
}
if ( nameFile != null && !nameFile.exists() )
{
String msg = "No image '" + nameFile + "' found in your system, check the path.";
logMessage( "imageNotFound", msg );
return;
}
boolean figureCalled = figureDefined;
if ( !figureCalled )
{
figure();
}
float width = 0;
float height = 0;
try
{
Image image = Image.getInstance( new URL( urlName ) );
image.scaleToFit( ITextUtil.getDefaultPageSize().width() / 2, ITextUtil.getDefaultPageSize().height() / 2 );
width = image.plainWidth();
height = image.plainHeight();
}
catch ( BadElementException e )
{
getLog().error( "BadElementException: " + e.getMessage(), e );
}
catch ( MalformedURLException e )
{
getLog().error( "MalformedURLException: " + e.getMessage(), e );
}
catch ( IOException e )
{
getLog().error( "IOException: " + e.getMessage(), e );
}
writeAddAttribute( ElementTags.URL, urlName );
writeAddAttribute( ElementTags.ALIGN, ElementTags.ALIGN_MIDDLE );
writeAddAttribute( ElementTags.PLAINWIDTH, String.valueOf( width ) );
writeAddAttribute( ElementTags.PLAINHEIGHT, String.valueOf( height ) );
actionContext.setAction( SinkActionContext.FIGURE_GRAPHICS );
if ( !figureCalled )
{
figure_();
}
}
// ----------------------------------------------------------------------
// Fonts
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void inline()
{
inline( null );
}
/** {@inheritDoc} */
public void inline( SinkEventAttributes attributes )
{
List<String> tags = new ArrayList<>();
if ( attributes != null )
{
if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "italic" ) )
{
font.addItalic();
tags.add( 0, "italic" );
}
if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "bold" ) )
{
font.addBold();
tags.add( 0, "bold" );
}
if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "code" ) )
{
font.setMonoSpaced( true );
tags.add( 0, "code" );
}
}
inlineStack.push( tags );
}
/** {@inheritDoc} */
public void inline_()
{
for ( String tag: inlineStack.pop() )
{
if ( "italic".equals( tag ) )
{
font.removeItalic();
}
else if ( "bold".equals( tag ) )
{
font.removeBold();
}
else if ( "code".equals( tag ) )
{
font.setMonoSpaced( false );
}
}
}
/** {@inheritDoc} */
public void bold_()
{
inline_();
}
/** {@inheritDoc} */
public void bold()
{
inline( SinkEventAttributeSet.Semantics.BOLD );
}
/** {@inheritDoc} */
public void italic_()
{
inline_();
}
/** {@inheritDoc} */
public void italic()
{
inline( SinkEventAttributeSet.Semantics.ITALIC );
}
/** {@inheritDoc} */
public void monospaced_()
{
inline_();
}
/** {@inheritDoc} */
public void monospaced()
{
inline( SinkEventAttributeSet.Semantics.CODE );
}
// ----------------------------------------------------------------------
// Links
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void link_()
{
writeEndElement(); // ElementTags.ANCHOR
font.setColor( Color.BLACK );
font.removeUnderlined();
actionContext.release();
}
/** {@inheritDoc} */
public void link( String name )
{
if ( name == null )
{
throw new NullPointerException( "Link name cannot be null!" );
}
font.setColor( Color.BLUE );
font.addUnderlined();
writeStartElement( ElementTags.ANCHOR );
if ( StringUtils.isNotEmpty( name ) && name.startsWith( "#" ) && StringUtils.isNotEmpty( header.getTitle() ) )
{
name = "#" + DoxiaUtils.encodeId( header.getTitle(), true ) + "_" + name.substring( 1 );
}
writeAddAttribute( ElementTags.REFERENCE, HtmlTools.escapeHTML( name ) );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
actionContext.setAction( SinkActionContext.LINK );
}
/** {@inheritDoc} */
public void anchor_()
{
if ( !anchorDefined )
{
// itext needs a defined local destination, we put an invisible text
writeAddAttribute( ElementTags.BLUE, "255" );
writeAddAttribute( ElementTags.GREEN, "255" );
writeAddAttribute( ElementTags.RED, "255" );
write( "_" );
}
anchorDefined = false;
writeEndElement(); // ElementTags.ANCHOR
actionContext.release();
}
/** {@inheritDoc} */
public void anchor( String name )
{
if ( name == null )
{
throw new NullPointerException( "Anchor name cannot be null!" );
}
if ( StringUtils.isNotEmpty( header.getTitle() ) )
{
name = header.getTitle() + "_" + name;
}
String id = name;
if ( !DoxiaUtils.isValidId( id ) )
{
id = DoxiaUtils.encodeId( name, true );
String msg = "Modified invalid link: '" + name + "' to '" + id + "'";
logMessage( "modifiedLink", msg );
}
writeStartElement( ElementTags.ANCHOR );
writeAddAttribute( ElementTags.NAME, id );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
actionContext.setAction( SinkActionContext.ANCHOR );
}
// ----------------------------------------------------------------------
// Misc
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void lineBreak()
{
// Special case for the header
if ( ( actionContext.getCurrentAction() == SinkActionContext.AUTHOR )
|| ( actionContext.getCurrentAction() == SinkActionContext.DATE )
|| ( actionContext.getCurrentAction() == SinkActionContext.TITLE ) )
{
return;
}
writeStartElement( ElementTags.NEWLINE );
writeEndElement();
}
/** {@inheritDoc} */
public void nonBreakingSpace()
{
write( " " );
}
/** {@inheritDoc} */
public void pageBreak()
{
writeStartElement( ElementTags.NEWPAGE );
writeEndElement();
}
/** {@inheritDoc} */
public void horizontalRule()
{
writeStartElement( ElementTags.PARAGRAPH );
writeAddAttribute( ElementTags.BLUE, "255" );
writeAddAttribute( ElementTags.GREEN, "255" );
writeAddAttribute( ElementTags.RED, "255" );
write( "_" );
writeEndElement();
writeStartElement( ElementTags.PARAGRAPH );
writeStartElement( ElementTags.HORIZONTALRULE );
writeEndElement();
writeEndElement();
}
// ----------------------------------------------------------------------
// Text
// ----------------------------------------------------------------------
/** {@inheritDoc} */
public void rawText( String text )
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
write( text, false );
writeEndElement(); // ElementTags.CHUNK
}
/** {@inheritDoc} */
public void text( String text )
{
if ( StringUtils.isEmpty( text ) )
{
return;
}
switch ( actionContext.getCurrentAction() )
{
case SinkActionContext.AUTHOR:
header.addAuthor( text );
break;
case SinkActionContext.DATE:
header.setDate( text );
break;
case SinkActionContext.TITLE:
header.setTitle( text );
break;
case SinkActionContext.TABLE_CAPTION:
this.tableCaptionXMLWriter.writeText( text );
break;
case SinkActionContext.VERBATIM:
// Used to preserve indentation and formating
LineNumberReader lnr = new LineNumberReader( new StringReader( text ) );
String line;
try
{
while ( ( line = lnr.readLine() ) != null )
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
write( "<![CDATA[", true );
// Special case
line = StringUtils.replace( line, "<![CDATA[", "< ![CDATA[" );
line = StringUtils.replace( line, "]]>", "]] >" );
write( line, true, false );
write( "]]>", true );
writeEndElement();
lineBreak();
}
}
catch ( IOException e )
{
throw new RuntimeException( "IOException: ", e );
}
break;
case SinkActionContext.FIGURE_CAPTION:
writeAddAttribute( ElementTags.ALT, text );
break;
case SinkActionContext.SECTION_TITLE:
case SinkActionContext.SECTION_1:
case SinkActionContext.SECTION_2:
case SinkActionContext.SECTION_3:
case SinkActionContext.SECTION_4:
case SinkActionContext.SECTION_5:
case SinkActionContext.FIGURE:
case SinkActionContext.FIGURE_GRAPHICS:
case SinkActionContext.TABLE_ROW:
case SinkActionContext.TABLE:
case SinkActionContext.HEAD:
case SinkActionContext.UNDEFINED:
break;
case SinkActionContext.ANCHOR:
anchorDefined = true;
case SinkActionContext.PARAGRAPH:
case SinkActionContext.LINK:
case SinkActionContext.TABLE_CELL:
case SinkActionContext.TABLE_HEADER_CELL:
case SinkActionContext.DEFINITION:
case SinkActionContext.DEFINED_TERM:
case SinkActionContext.NUMBERED_LIST_ITEM:
case SinkActionContext.LIST_ITEM:
case SinkActionContext.SECTION_TITLE_5:
case SinkActionContext.SECTION_TITLE_4:
case SinkActionContext.SECTION_TITLE_3:
case SinkActionContext.SECTION_TITLE_2:
case SinkActionContext.SECTION_TITLE_1:
default:
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, font.getFontName() );
writeAddAttribute( ElementTags.SIZE, font.getFontSize() );
writeAddAttribute( ElementTags.STYLE, font.getFontStyle() );
writeAddAttribute( ElementTags.BLUE, font.getFontColorBlue() );
writeAddAttribute( ElementTags.GREEN, font.getFontColorGreen() );
writeAddAttribute( ElementTags.RED, font.getFontColorRed() );
write( text );
writeEndElement(); // ElementTags.CHUNK
}
}
/**
* {@inheritDoc}
*
* Unkown events just log a warning message but are ignored otherwise.
* @see org.apache.maven.doxia.sink.Sink#unknown(String,Object[],SinkEventAttributes)
*/
public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes )
{
String msg = "Unknown Sink event: '" + name + "', ignoring!";
logMessage( "unknownEvent", msg );
}
/** {@inheritDoc} */
protected void init()
{
super.init();
this.actionContext = new SinkActionContext();
this.font = new ITextFont();
this.header = new ITextHeader();
this.numberDepth = 1;
this.depth = 0;
this.tableCaptionWriter = null;
this.tableCaptionXMLWriter = null;
this.anchorDefined = false;
this.figureDefined = false;
this.warnMessages = null;
}
/**
* Convenience method to write a starting element.
*
* @param tag the name of the tag
*/
private void writeStartElement( String tag )
{
if ( tableCaptionXMLWriter == null )
{
xmlWriter.startElement( tag );
}
else
{
tableCaptionXMLWriter.startElement( tag );
}
}
/**
* Convenience method to write a key-value pair.
*
* @param key the name of an attribute
* @param value the value of an attribute
*/
private void writeAddAttribute( String key, String value )
{
if ( tableCaptionXMLWriter == null )
{
xmlWriter.addAttribute( key, value );
}
else
{
tableCaptionXMLWriter.addAttribute( key, value );
}
}
/**
* Convenience method to write a key-value pair.
*
* @param key the name of an attribute
* @param value the value of an attribute
*/
private void writeAddAttribute( String key, int value )
{
if ( tableCaptionXMLWriter == null )
{
xmlWriter.addAttribute( key, String.valueOf( value ) );
}
else
{
tableCaptionXMLWriter.addAttribute( key, String.valueOf( value ) );
}
}
/**
* Convenience method to write an end element.
*/
private void writeEndElement()
{
if ( tableCaptionXMLWriter == null )
{
xmlWriter.endElement();
}
else
{
tableCaptionXMLWriter.endElement();
}
}
/**
* Convenience method to write a String
*
* @param aString
*/
protected void write( String aString )
{
write( aString, false );
}
/**
* Convenience method to write a String depending the escapeHtml flag
*
* @param aString
* @param escapeHtml
*/
private void write( String aString, boolean escapeHtml )
{
write( aString, escapeHtml, true );
}
/**
* Convenience method to write a String depending the escapeHtml flag
*
* @param aString
* @param escapeHtml
* @param trim
*/
private void write( String aString, boolean escapeHtml, boolean trim )
{
if ( aString == null )
{
return;
}
if ( trim )
{
aString = StringUtils.replace( aString, "\n", "" );
LineNumberReader lnr = new LineNumberReader( new StringReader( aString ) );
StringBuilder sb = new StringBuilder();
String line;
try
{
while ( ( line = lnr.readLine() ) != null )
{
sb.append( beautifyPhrase( line.trim() ) );
sb.append( " " );
}
aString = sb.toString();
}
catch ( IOException e )
{
// nop
}
if ( aString.trim().length() == 0 )
{
return;
}
}
if ( escapeHtml )
{
if ( tableCaptionXMLWriter == null )
{
xmlWriter.writeMarkup( aString );
}
else
{
tableCaptionXMLWriter.writeMarkup( aString );
}
}
else
{
if ( tableCaptionXMLWriter == null )
{
xmlWriter.writeText( aString );
}
else
{
tableCaptionXMLWriter.writeText( aString );
}
}
}
/**
* Convenience method to return a beautify phrase, i.e. one space between words.
*
* @param aString
* @return a String with only one space between words
*/
private static String beautifyPhrase( String aString )
{
String[] strings = StringUtils.split( aString, " " );
StringBuilder sb = new StringBuilder();
for ( String string : strings )
{
if ( string.trim().length() != 0 )
{
sb.append( string.trim() );
sb.append( " " );
}
}
return sb.toString().trim();
}
private void startChunk( String fontName, int fontSize, String fontStyle, int fontColorBlue, int fontColorGreen,
int fontColorRed, String localDestination )
{
writeStartElement( ElementTags.CHUNK );
writeAddAttribute( ElementTags.FONT, fontName );
writeAddAttribute( ElementTags.SIZE, fontSize );
writeAddAttribute( ElementTags.STYLE, fontStyle );
writeAddAttribute( ElementTags.BLUE, fontColorBlue );
writeAddAttribute( ElementTags.GREEN, fontColorGreen );
writeAddAttribute( ElementTags.RED, fontColorRed );
// writeAddAttribute( ElementTags.LOCALDESTINATION, localDestination );
}
/**
* If debug mode is enabled, log the <code>msg</code> as is, otherwise add unique msg in <code>warnMessages</code>.
*
* @param key not null
* @param msg not null
* @see #close()
* @since 1.1.1
*/
private void logMessage( String key, String msg )
{
msg = "[iText Sink] " + msg;
if ( getLog().isDebugEnabled() )
{
getLog().debug( msg );
return;
}
if ( warnMessages == null )
{
warnMessages = new HashMap<>();
}
Set<String> set = warnMessages.get( key );
if ( set == null )
{
set = new TreeSet<>();
}
set.add( msg );
warnMessages.put( key, set );
}
}