| 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> |
| */ |
| 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(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * Convenience method to write a String |
| */ |
| 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(); |
| } |
| |
| /** |
| * 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 ); |
| } |
| } |