/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.render.rtf;

// Java
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import java.util.Map;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;

import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FOEventHandler;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.XMLObj;
import org.apache.fop.fo.flow.AbstractGraphics;
import org.apache.fop.fo.flow.BasicLink;
import org.apache.fop.fo.flow.Block;
import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.flow.Character;
import org.apache.fop.fo.flow.ExternalGraphic;
import org.apache.fop.fo.flow.Footnote;
import org.apache.fop.fo.flow.FootnoteBody;
import org.apache.fop.fo.flow.Inline;
import org.apache.fop.fo.flow.InstreamForeignObject;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fo.flow.ListBlock;
import org.apache.fop.fo.flow.ListItem;
import org.apache.fop.fo.flow.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.flow.PageNumberCitation;
import org.apache.fop.fo.flow.PageNumberCitationLast;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableFooter;
import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.PageSequenceMaster;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.EnumLength;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.layoutmgr.inline.ImageLayout;
import org.apache.fop.layoutmgr.table.ColumnSetup;
import org.apache.fop.render.RendererEventProducer;
import org.apache.fop.render.rtf.rtflib.exceptions.RtfException;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfListContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTableContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTextrunContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAfter;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfBefore;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfDocumentArea;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfElement;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfExternalGraphic;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFile;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFootnote;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfPage;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfParagraphBreak;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun;
import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
import org.apache.fop.render.rtf.rtflib.tools.PercentContext;
import org.apache.fop.render.rtf.rtflib.tools.TableContext;

/**
 * RTF Handler: generates RTF output using the structure events from
 * the FO Tree sent to this structure handler.
 */
public class RTFHandler extends FOEventHandler {

    private RtfFile rtfFile;
    private final OutputStream os;
    private static Log log = LogFactory.getLog(RTFHandler.class);
    private RtfSection sect;
    private RtfDocumentArea docArea;
    private boolean bDefer;              //true, if each called handler shall be
                                         //processed at later time.
    private boolean bPrevHeaderSpecified; //true, if there has been a
                                                  //header in any page-sequence
    private boolean bPrevFooterSpecified; //true, if there has been a
                                                  //footer in any page-sequence
    private boolean bHeaderSpecified;  //true, if there is a header
                                               //in current page-sequence
    private boolean bFooterSpecified;  //true, if there is a footer
                                               //in current page-sequence
    private BuilderContext builderContext = new BuilderContext(null);

    private SimplePageMaster pagemaster;

    private int nestedTableDepth = 1;

    private PercentContext percentManager = new PercentContext();


    /**
     * Creates a new RTF structure handler.
     * @param userAgent the FOUserAgent for this process
     * @param os OutputStream to write to
     */
    public RTFHandler(FOUserAgent userAgent, OutputStream os) {
        super(userAgent);
        this.os = os;
        bDefer = true;

        boolean base14Kerning = false;
        FontSetup.setup(fontInfo, null, userAgent.getResourceResolver(), base14Kerning);
    }

    /**
     * Central exception handler for I/O exceptions.
     * @param ioe IOException to handle
     */
    protected void handleIOTrouble(IOException ioe) {
        RendererEventProducer eventProducer = RendererEventProducer.Provider.get(
                getUserAgent().getEventBroadcaster());
        eventProducer.ioError(this, ioe);
    }

    /** {@inheritDoc} */
    public void startDocument() throws SAXException {
        // TODO sections should be created
        try {
            rtfFile = new RtfFile(new OutputStreamWriter(os));
            docArea = rtfFile.startDocumentArea();
        } catch (IOException ioe) {
            // TODO could we throw Exception in all FOEventHandler events?
            throw new SAXException(ioe);
        }
    }

    /** {@inheritDoc} */
    public void endDocument() throws SAXException {
        try {
            rtfFile.flush();
        } catch (IOException ioe) {
            // TODO could we throw Exception in all FOEventHandler events?
            throw new SAXException(ioe);
        }
    }

    /** {@inheritDoc} */
    public void startPageSequence(PageSequence pageSeq)  {
        try {
            //This is needed for region handling
            if (this.pagemaster == null) {
                String reference = pageSeq.getMasterReference();
                this.pagemaster
                        = pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(reference);
                if (this.pagemaster == null) {
                    RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
                            getUserAgent().getEventBroadcaster());
                    eventProducer.onlySPMSupported(this, reference, pageSeq.getLocator());
                    PageSequenceMaster master
                        = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference);
                    if (pageSeq.getMainFlow() != null) {
                        this.pagemaster = master.getNextSimplePageMaster(
                                false, false, false, false, pageSeq.getMainFlow().getFlowName());
                    }
                }
            }

            if (bDefer) {
                return;
            }

            sect = docArea.newSection();

            //read page size and margins, if specified
            //only simple-page-master supported, so pagemaster may be null
            if (pagemaster != null) {
                sect.getRtfAttributes().set(
                    PageAttributesConverter.convertPageAttributes(
                            pagemaster));
            } else {
                RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
                        getUserAgent().getEventBroadcaster());
                eventProducer.noSPMFound(this, pageSeq.getLocator());
            }

            builderContext.pushContainer(sect);

            //Calculate usable page width for this flow
            int useAblePageWidth = pagemaster.getPageWidth().getValue()
                - pagemaster.getCommonMarginBlock().marginLeft.getValue()
                - pagemaster.getCommonMarginBlock().marginRight.getValue()
                - sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_LEFT)
                - sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_RIGHT);
            percentManager.setDimension(pageSeq, useAblePageWidth);

            bHeaderSpecified = false;
            bFooterSpecified = false;
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        }
    }

    /** {@inheritDoc} */
    public void endPageSequence(PageSequence pageSeq) {
        if (bDefer) {
            //If endBlock was called while SAX parsing, and the passed FO is Block
            //nested within another Block, stop deferring.
            //Now process all deferred FOs.
            bDefer = false;
            recurseFONode(pageSeq);
            this.pagemaster = null;
            bDefer = true;

            return;
        } else {
            builderContext.popContainer(RtfSection.class, this);
            this.pagemaster = null;
        }
    }

    /** {@inheritDoc} */
    public void startFlow(Flow fl) {
        if (bDefer) {
            return;
        }

        try {
            log.debug("starting flow: " + fl.getFlowName());
            boolean handled = false;
            Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
            Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
            Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
            if (fl.getFlowName().equals(regionBody.getRegionName())) {
                // if there is no header in current page-sequence but there has been
                // a header in a previous page-sequence, insert an empty header.
                if (bPrevHeaderSpecified && !bHeaderSpecified) {
                    RtfAttributes attr = new RtfAttributes();
                    attr.set(RtfBefore.HEADER);

                    final IRtfBeforeContainer contBefore
                        = (IRtfBeforeContainer)builderContext.getContainer(
                                IRtfBeforeContainer.class, true, this);
                    contBefore.newBefore(attr);
                }

                // if there is no footer in current page-sequence but there has been
                // a footer in a previous page-sequence, insert an empty footer.
                if (bPrevFooterSpecified && !bFooterSpecified) {
                    RtfAttributes attr = new RtfAttributes();
                    attr.set(RtfAfter.FOOTER);

                    final IRtfAfterContainer contAfter
                        = (IRtfAfterContainer)builderContext.getContainer(
                                IRtfAfterContainer.class, true, this);
                    contAfter.newAfter(attr);
                }
                handled = true;
            } else if (regionBefore != null
                    && fl.getFlowName().equals(regionBefore.getRegionName())) {
                bHeaderSpecified = true;
                bPrevHeaderSpecified = true;

                final IRtfBeforeContainer c
                    = (IRtfBeforeContainer)builderContext.getContainer(
                        IRtfBeforeContainer.class,
                        true, this);

                RtfAttributes beforeAttributes = ((RtfElement)c).getRtfAttributes();
                if (beforeAttributes == null) {
                    beforeAttributes = new RtfAttributes();
                }
                beforeAttributes.set(RtfBefore.HEADER);

                RtfBefore before = c.newBefore(beforeAttributes);
                builderContext.pushContainer(before);
                handled = true;
            } else if (regionAfter != null
                    && fl.getFlowName().equals(regionAfter.getRegionName())) {
                bFooterSpecified = true;
                bPrevFooterSpecified = true;

                final IRtfAfterContainer c
                    = (IRtfAfterContainer)builderContext.getContainer(
                        IRtfAfterContainer.class,
                        true, this);

                RtfAttributes afterAttributes = ((RtfElement)c).getRtfAttributes();
                if (afterAttributes == null) {
                    afterAttributes = new RtfAttributes();
                }

                afterAttributes.set(RtfAfter.FOOTER);

                RtfAfter after = c.newAfter(afterAttributes);
                builderContext.pushContainer(after);
                handled = true;
            }
            if (!handled) {
                log.warn("A " + fl.getLocalName() + " has been skipped: " + fl.getFlowName());
            }
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startFlow: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endFlow(Flow fl) {
        if (bDefer) {
            return;
        }

        try {
            Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
            Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
            Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
            if (fl.getFlowName().equals(regionBody.getRegionName())) {
                //just do nothing
            } else if (regionBefore != null
                    && fl.getFlowName().equals(regionBefore.getRegionName())) {
                builderContext.popContainer(RtfBefore.class, this);
            } else if (regionAfter != null
                    && fl.getFlowName().equals(regionAfter.getRegionName())) {
                builderContext.popContainer(RtfAfter.class, this);
            }
        } catch (Exception e) {
            log.error("endFlow: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void startBlock(Block bl) {
        if (bDefer) {
            return;
        }

        try {
            RtfAttributes rtfAttr
                = TextAttributesConverter.convertAttributes(bl);

            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class,
                    true, this);

            RtfTextrun textrun = container.getTextrun();

            textrun.addParagraphBreak();
            textrun.pushBlockAttributes(rtfAttr);
            textrun.addBookmark(bl.getId());
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startBlock: " + e.getMessage());
            throw new RuntimeException("Exception: " + e);
        }
    }

    /** {@inheritDoc} */
    public void endBlock(Block bl) {

        if (bDefer) {
            return;
        }

        try {
            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class,
                    true, this);

            RtfTextrun textrun = container.getTextrun();
            RtfParagraphBreak par = textrun.addParagraphBreak();

            RtfTableCell cellParent = (RtfTableCell)textrun.getParentOfClass(RtfTableCell.class);
            if (cellParent != null && par != null) {
                int iDepth = cellParent.findChildren(textrun);
                cellParent.setLastParagraph(par, iDepth);
            }

            int breakValue = toRtfBreakValue(bl.getBreakAfter());
            textrun.popBlockAttributes(breakValue);

        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startBlock:" + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void startBlockContainer(BlockContainer blc) {
        if (bDefer) {
            return;
        }

        try {
            RtfAttributes rtfAttr
                = TextAttributesConverter.convertBlockContainerAttributes(blc);

            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class,
                    true, this);

            RtfTextrun textrun = container.getTextrun();

            textrun.addParagraphBreak();
            textrun.pushBlockAttributes(rtfAttr);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startBlock: " + e.getMessage());
            throw new RuntimeException("Exception: " + e);
        }
    }

    /** {@inheritDoc} */
    public void endBlockContainer(BlockContainer bl) {
        if (bDefer) {
            return;
        }

        try {
            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class,
                    true, this);

            RtfTextrun textrun = container.getTextrun();

            textrun.addParagraphBreak();
            int breakValue = toRtfBreakValue(bl.getBreakAfter());
            textrun.popBlockAttributes(breakValue);

        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startBlock:" + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private int toRtfBreakValue(int foBreakValue) {
        switch (foBreakValue) {
        case Constants.EN_PAGE:
            return RtfTextrun.BREAK_PAGE;
        case Constants.EN_EVEN_PAGE:
            return RtfTextrun.BREAK_EVEN_PAGE;
        case Constants.EN_ODD_PAGE:
            return RtfTextrun.BREAK_ODD_PAGE;
        case Constants.EN_COLUMN:
            return RtfTextrun.BREAK_COLUMN;
        default:
            return RtfTextrun.BREAK_NONE;
        }
    }

    /** {@inheritDoc} */
    public void startTable(Table tbl) {
        if (bDefer) {
            return;
        }

        // create an RtfTable in the current table container
        TableContext tableContext = new TableContext(builderContext);

        try {
            final IRtfTableContainer tc
                = (IRtfTableContainer)builderContext.getContainer(
                        IRtfTableContainer.class, true, null);

            RtfAttributes atts
                = TableAttributesConverter.convertTableAttributes(tbl);

            RtfTable table = tc.newTable(atts, tableContext);
            table.setNestedTableDepth(nestedTableDepth);
            nestedTableDepth++;

            CommonBorderPaddingBackground border = tbl.getCommonBorderPaddingBackground();
            RtfAttributes borderAttributes = new RtfAttributes();

            BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.BEFORE,
                    borderAttributes, ITableAttributes.CELL_BORDER_TOP);
            BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.AFTER,
                    borderAttributes, ITableAttributes.CELL_BORDER_BOTTOM);
            BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.START,
                    borderAttributes, ITableAttributes.CELL_BORDER_LEFT);
            BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.END,
                    borderAttributes,  ITableAttributes.CELL_BORDER_RIGHT);

            table.setBorderAttributes(borderAttributes);

            builderContext.pushContainer(table);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startTable:" + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }

        builderContext.pushTableContext(tableContext);
    }

    /** {@inheritDoc} */
    public void endTable(Table tbl) {
        if (bDefer) {
            return;
        }

        nestedTableDepth--;
        builderContext.popTableContext();
        builderContext.popContainer(RtfTable.class, this);
    }

    /** {@inheritDoc} */
    public void startColumn(TableColumn tc) {
        if (bDefer) {
            return;
        }

        try {
            int iWidth = tc.getColumnWidth().getValue(percentManager);
            percentManager.setDimension(tc, iWidth);

            //convert to twips
            Float width = FoUnitsConverter.getInstance().convertMptToTwips(iWidth);
            builderContext.getTableContext().setNextColumnWidth(width);
            builderContext.getTableContext().setNextColumnRowSpanning(
                    0, null);
            builderContext.getTableContext().setNextFirstSpanningCol(false);
        } catch (Exception e) {
            log.error("startColumn: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endColumn(TableColumn tc) {
        if (bDefer) {
            return;
        }
    }

    /** {@inheritDoc} */
    public void startHeader(TableHeader header) {
        builderContext.pushPart(header);
        startPart(header);
    }

    /** {@inheritDoc} */
    public void endHeader(TableHeader header) {
        builderContext.popPart(header.getClass(), this);
        endPart(header);
    }

    /** {@inheritDoc} */
    public void startFooter(TableFooter footer) {
        builderContext.pushPart(footer);
        startPart(footer);
    }

    /** {@inheritDoc} */
    public void endFooter(TableFooter footer) {
        builderContext.popPart(footer.getClass(), this);
        endPart(footer);
    }

    /** {@inheritDoc} */
    public void startInline(Inline inl) {
        if (bDefer) {
            return;
        }

        try {
            RtfAttributes rtfAttr
                = TextAttributesConverter.convertCharacterAttributes(inl);

            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class, true, this);

            RtfTextrun textrun = container.getTextrun();
            textrun.pushInlineAttributes(rtfAttr);
            textrun.addBookmark(inl.getId());
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (FOPException fe) {
            log.error("startInline:" + fe.getMessage());
            throw new RuntimeException(fe.getMessage());
        } catch (Exception e) {
            log.error("startInline:" + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endInline(Inline inl) {
        if (bDefer) {
            return;
        }

        try {
            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class, true, this);

            RtfTextrun textrun = container.getTextrun();
            textrun.popInlineAttributes();
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startInline:" + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private void startPart(TablePart part) {
        if (bDefer) {
            return;
        }

        try {
            RtfAttributes atts = TableAttributesConverter.convertTablePartAttributes(part);

            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
            tbl.setHeaderAttribs(atts);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startPart: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private void endPart(TablePart tb) {
        if (bDefer) {
            return;
        }

        try {
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
            tbl.setHeaderAttribs(null);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("endPart: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }


     /**
     * {@inheritDoc}
     */
    public void startBody(TableBody body) {
        builderContext.pushPart(body);
        startPart(body);
    }

    /** {@inheritDoc} */
    public void endBody(TableBody body) {
        builderContext.popPart(TableBody.class, this);
        endPart(body);
    }

    /**
     * {@inheritDoc}
     */
    public void startRow(TableRow tr) {
        if (bDefer) {
            return;
        }

        try {
            // create an RtfTableRow in the current RtfTable
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            final RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class,
                    true, null);

            RtfAttributes atts = TableAttributesConverter.convertRowAttributes(tr,
                    tbl.getHeaderAttribs());

            if (tr.getParent() instanceof TableHeader) {
                atts.set(ITableAttributes.ATTR_HEADER);
            }

            builderContext.pushContainer(tbl.newTableRow(atts));

            // reset column iteration index to correctly access column widths
            builderContext.getTableContext().selectFirstColumn();
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startRow: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endRow(TableRow tr) {
        if (bDefer) {
            return;
        }

        try {
            TableContext tctx = builderContext.getTableContext();
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
                    true, null);

            //while the current column is in row-spanning, act as if
            //a vertical merged cell would have been specified.
            while (tctx.getNumberOfColumns() > tctx.getColumnIndex()
                  && tctx.getColumnRowSpanningNumber() > 0) {
                RtfTableCell vCell = row.newTableCellMergedVertically(
                        (int)tctx.getColumnWidth(),
                        tctx.getColumnRowSpanningAttrs());

                if (!tctx.getFirstSpanningCol()) {
                    vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
                }

                tctx.selectNextColumn();
            }
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("endRow: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }


        builderContext.popContainer(RtfTableRow.class, this);
        builderContext.getTableContext().decreaseRowSpannings();
    }

    /** {@inheritDoc} */
    public void startCell(TableCell tc) {
        if (bDefer) {
            return;
        }

        try {
            TableContext tctx = builderContext.getTableContext();
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
                    true, null);

            int numberRowsSpanned = tc.getNumberRowsSpanned();
            int numberColumnsSpanned = tc.getNumberColumnsSpanned();

            //while the current column is in row-spanning, act as if
            //a vertical merged cell would have been specified.
            while (tctx.getNumberOfColumns() > tctx.getColumnIndex()
                  && tctx.getColumnRowSpanningNumber() > 0) {
                RtfTableCell vCell = row.newTableCellMergedVertically(
                        (int)tctx.getColumnWidth(),
                        tctx.getColumnRowSpanningAttrs());

                if (!tctx.getFirstSpanningCol()) {
                    vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
                }

                tctx.selectNextColumn();
            }

            //get the width of the currently started cell
            float width = tctx.getColumnWidth();

            // create an RtfTableCell in the current RtfTableRow
            RtfAttributes atts = TableAttributesConverter.convertCellAttributes(tc);
            RtfTableCell cell = row.newTableCell((int)width, atts);

            //process number-rows-spanned attribute
            if (numberRowsSpanned > 1) {
                // Start vertical merge
                cell.setVMerge(RtfTableCell.MERGE_START);

                // set the number of rows spanned
                tctx.setCurrentColumnRowSpanning(numberRowsSpanned,
                        cell.getRtfAttributes());
            } else {
                tctx.setCurrentColumnRowSpanning(
                        numberRowsSpanned, null);
            }

            //process number-columns-spanned attribute
            if (numberColumnsSpanned > 0) {
                // Get the number of columns spanned
                tctx.setCurrentFirstSpanningCol(true);

                // We widthdraw one cell because the first cell is already created
                // (it's the current cell) !
                 for (int i = 0; i < numberColumnsSpanned - 1; ++i) {
                    tctx.selectNextColumn();

                    //aggregate width for further elements
                    width += tctx.getColumnWidth();
                    tctx.setCurrentFirstSpanningCol(false);
                    RtfTableCell hCell = row.newTableCellMergedHorizontally(
                            0, null);

                    if (numberRowsSpanned > 1) {
                        // Start vertical merge
                        hCell.setVMerge(RtfTableCell.MERGE_START);

                        // set the number of rows spanned
                        tctx.setCurrentColumnRowSpanning(
                                numberRowsSpanned,
                                cell.getRtfAttributes());
                    } else {
                        tctx.setCurrentColumnRowSpanning(
                                numberRowsSpanned, cell.getRtfAttributes());
                    }
                }
            }
            //save width of the cell, convert from twips to mpt
            percentManager.setDimension(tc, (int)width * 50);

            builderContext.pushContainer(cell);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startCell: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endCell(TableCell tc) {
        if (bDefer) {
            return;
        }
        try {
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfTableCell cell = (RtfTableCell)builderContext.getContainer(RtfTableCell.class, false, this);
            cell.finish();

        } catch (Exception e) {
            log.error("endCell: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }

        builderContext.popContainer(RtfTableCell.class, this);
        builderContext.getTableContext().selectNextColumn();
    }

    // Lists
    /** {@inheritDoc} */
    public void startList(ListBlock lb) {
        if (bDefer) {
            return;
        }

        try  {
            // create an RtfList in the current list container
            final IRtfListContainer c
                = (IRtfListContainer)builderContext.getContainer(
                    IRtfListContainer.class, true, this);
            final RtfList newList = c.newList(
                ListAttributesConverter.convertAttributes(lb));
            builderContext.pushContainer(newList);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (FOPException fe) {
            log.error("startList: " + fe.getMessage());
            throw new RuntimeException(fe.getMessage());
        } catch (Exception e) {
            log.error("startList: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endList(ListBlock lb) {
        if (bDefer) {
            return;
        }

        builderContext.popContainer(RtfList.class, this);
    }

    /** {@inheritDoc} */
    public void startListItem(ListItem li) {
        if (bDefer) {
            return;
        }

        // create an RtfListItem in the current RtfList
        try {
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfList list = (RtfList)builderContext.getContainer(
                    RtfList.class, true, this);

            /**
             * If the current list already contains a list item, then close the
             * list and open a new one, so every single list item gets its own
             * list. This allows every item to have a different list label.
             * If all the items would be in the same list, they had all the
             * same label.
             */
            //TODO: do this only, if the labels content <> previous labels content
            if (list.getChildCount() > 0) {
                this.endListBody(null);
                this.endList((ListBlock) li.getParent());
                this.startList((ListBlock) li.getParent());
                this.startListBody(null);

                list = (RtfList)builderContext.getContainer(
                        RtfList.class, true, this);
            }

            builderContext.pushContainer(list.newListItem());
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startList: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endListItem(ListItem li) {
        if (bDefer) {
            return;
        }

        builderContext.popContainer(RtfListItem.class, this);
    }

    /** {@inheritDoc} */
    public void startListLabel(ListItemLabel listItemLabel) {
        if (bDefer) {
            return;
        }

        try {
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfListItem item
                = (RtfListItem)builderContext.getContainer(RtfListItem.class, true, this);

            RtfListItemLabel label = item.new RtfListItemLabel(item);
            builderContext.pushContainer(label);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startPageNumber: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endListLabel(ListItemLabel listItemLabel) {
        if (bDefer) {
            return;
        }

        builderContext.popContainer(RtfListItemLabel.class, this);
    }

    /** {@inheritDoc} */
    public void startListBody(ListItemBody listItemBody) {
    }

    /** {@inheritDoc} */
    public void endListBody(ListItemBody listItemBody) {
    }

    // Static Regions
    /** {@inheritDoc} */
    public void startStatic(StaticContent staticContent) {
    }

    /** {@inheritDoc} */
    public void endStatic(StaticContent statisContent) {
    }

    /** {@inheritDoc} */
    public void startMarkup() {
    }

    /** {@inheritDoc} */
    public void endMarkup() {
    }

    /** {@inheritDoc} */
    public void startLink(BasicLink basicLink) {
        if (bDefer) {
            return;
        }

        try {
            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class, true, this);

            RtfTextrun textrun = container.getTextrun();

            RtfHyperLink link = textrun.addHyperlink(new RtfAttributes());

            if (basicLink.hasExternalDestination()) {
                link.setExternalURL(basicLink.getExternalDestination());
            } else {
                link.setInternalURL(basicLink.getInternalDestination());
            }

            builderContext.pushContainer(link);

        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startLink: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endLink(BasicLink basicLink) {
        if (bDefer) {
            return;
        }

        builderContext.popContainer(RtfHyperLink.class, this);
    }

    /** {@inheritDoc} */
    public void image(ExternalGraphic eg) {
        if (bDefer) {
            return;
        }

        String uri = eg.getURL();
        ImageInfo info = null;
        try {

            //set image data
            FOUserAgent userAgent = eg.getUserAgent();
            ImageManager manager = userAgent.getImageManager();
            info = manager.getImageInfo(uri, userAgent.getImageSessionContext());

            putGraphic(eg, info);
        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, uri, ie, null);
        } catch (FileNotFoundException fe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
        }
    }

    /** {@inheritDoc} */
    public void endInstreamForeignObject(InstreamForeignObject ifo) {
        if (bDefer) {
            return;
        }

        try {
            XMLObj child = ifo.getChildXMLObj();
            Document doc = child.getDOMDocument();
            String ns = child.getNamespaceURI();

            ImageInfo info = new ImageInfo(null, null);
            // Set the resolution to that of the FOUserAgent
            FOUserAgent ua = ifo.getUserAgent();
            ImageSize size = new ImageSize();
            size.setResolution(ua.getSourceResolution());

            // Set the image size to the size of the svg.
            Point2D csize = new Point2D.Float(-1, -1);
            Point2D intrinsicDimensions = child.getDimension(csize);
            if (intrinsicDimensions == null) {
                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                        getUserAgent().getEventBroadcaster());
                eventProducer.ifoNoIntrinsicSize(this, child.getLocator());
                return;
            }
            size.setSizeInMillipoints(
                    (int)Math.round(intrinsicDimensions.getX() * 1000),
                    (int)Math.round(intrinsicDimensions.getY() * 1000));
            size.calcPixelsFromSize();
            info.setSize(size);

            ImageXMLDOM image = new ImageXMLDOM(info, doc, ns);

            FOUserAgent userAgent = ifo.getUserAgent();
            ImageManager manager = userAgent.getImageManager();
            Map hints = ImageUtil.getDefaultHints(ua.getImageSessionContext());
            Image converted = manager.convertImage(image, FLAVORS, hints);
            putGraphic(ifo, converted);

        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, null, ie, null);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this, null, ioe, null);
        }
    }

    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
        ImageFlavor.RAW_EMF, ImageFlavor.RAW_PNG, ImageFlavor.RAW_JPEG
    };

    /**
     * Puts a graphic/image into the generated RTF file.
     * @param abstractGraphic the graphic (external-graphic or instream-foreign-object)
     * @param info the image info object
     * @throws IOException In case of an I/O error
     */
    private void putGraphic(AbstractGraphics abstractGraphic, ImageInfo info)
            throws IOException {
        try {
            FOUserAgent userAgent = abstractGraphic.getUserAgent();
            ImageManager manager = userAgent.getImageManager();
            ImageSessionContext sessionContext = userAgent.getImageSessionContext();
            Map hints = ImageUtil.getDefaultHints(sessionContext);
            Image image = manager.getImage(info, FLAVORS, hints, sessionContext);

            putGraphic(abstractGraphic, image);
        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, null, ie, null);
        }
    }

    /**
     * Puts a graphic/image into the generated RTF file.
     * @param abstractGraphic the graphic (external-graphic or instream-foreign-object)
     * @param image the image
     * @throws IOException In case of an I/O error
     */
    private void putGraphic(AbstractGraphics abstractGraphic, Image image)
            throws IOException {
        byte[] rawData = null;

        final ImageInfo info = image.getInfo();

        if (image instanceof ImageRawStream) {
            ImageRawStream rawImage = (ImageRawStream)image;
            InputStream in = rawImage.createInputStream();
            try {
                rawData = IOUtils.toByteArray(in);
            } finally {
                IOUtils.closeQuietly(in);
            }
        }

        if (rawData == null) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageWritingError(this, null);
            return;
        }

        //Set up percentage calculations
        this.percentManager.setDimension(abstractGraphic);
        PercentBaseContext pContext = new PercentBaseContext() {

            public int getBaseLength(int lengthBase, FObj fobj) {
                switch (lengthBase) {
                case LengthBase.IMAGE_INTRINSIC_WIDTH:
                    return info.getSize().getWidthMpt();
                case LengthBase.IMAGE_INTRINSIC_HEIGHT:
                    return info.getSize().getHeightMpt();
                default:
                    return percentManager.getBaseLength(lengthBase, fobj);
                }
            }

        };
        ImageLayout layout = new ImageLayout(abstractGraphic, pContext,
                image.getInfo().getSize().getDimensionMpt());

        final IRtfTextrunContainer c
            = (IRtfTextrunContainer)builderContext.getContainer(
                IRtfTextrunContainer.class, true, this);

        final RtfExternalGraphic rtfGraphic = c.getTextrun().newImage();

        //set URL
        if (info.getOriginalURI() != null) {
            rtfGraphic.setURL(info.getOriginalURI());
        }
        rtfGraphic.setImageData(rawData);

        FoUnitsConverter converter = FoUnitsConverter.getInstance();
        Dimension viewport = layout.getViewportSize();
        Rectangle placement = layout.getPlacement();
        int cropLeft = Math.round(converter.convertMptToTwips(-placement.x));
        int cropTop = Math.round(converter.convertMptToTwips(-placement.y));
        int cropRight = Math.round(converter.convertMptToTwips(
                -1 * (viewport.width - placement.x - placement.width)));
        int cropBottom = Math.round(converter.convertMptToTwips(
                -1 * (viewport.height - placement.y - placement.height)));
        rtfGraphic.setCropping(cropLeft, cropTop, cropRight, cropBottom);

        int width = Math.round(converter.convertMptToTwips(viewport.width));
        int height = Math.round(converter.convertMptToTwips(viewport.height));
        width += cropLeft + cropRight;
        height += cropTop + cropBottom;
        rtfGraphic.setWidthTwips(width);
        rtfGraphic.setHeightTwips(height);

        //TODO: make this configurable:
        //      int compression = m_context.m_options.getRtfExternalGraphicCompressionRate ();
        int compression = 0;
        if (compression != 0) {
            if (!rtfGraphic.setCompressionRate(compression)) {
                log.warn("The compression rate " + compression
                    + " is invalid. The value has to be between 1 and 100 %.");
            }
        }
    }

    /** {@inheritDoc} */
    public void pageRef() {
    }

    /** {@inheritDoc} */
    public void startFootnote(Footnote footnote) {
        if (bDefer) {
            return;
        }

        try {
            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class,
                    true, this);

            RtfTextrun textrun = container.getTextrun();
            RtfFootnote rtfFootnote = textrun.addFootnote();

            builderContext.pushContainer(rtfFootnote);

        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startFootnote: " + e.getMessage());
            throw new RuntimeException("Exception: " + e);
        }
    }

    /** {@inheritDoc} */
    public void endFootnote(Footnote footnote) {
        if (bDefer) {
            return;
        }

        builderContext.popContainer(RtfFootnote.class, this);
    }

    /** {@inheritDoc} */
    public void startFootnoteBody(FootnoteBody body) {
        if (bDefer) {
            return;
        }

        try {
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfFootnote rtfFootnote
                = (RtfFootnote)builderContext.getContainer(
                    RtfFootnote.class,
                    true, this);

            rtfFootnote.startBody();
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startFootnoteBody: " + e.getMessage());
            throw new RuntimeException("Exception: " + e);
        }
    }

    /** {@inheritDoc} */
    public void endFootnoteBody(FootnoteBody body) {
        if (bDefer) {
            return;
        }

        try {
            // @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
            RtfFootnote rtfFootnote
                = (RtfFootnote)builderContext.getContainer(
                    RtfFootnote.class,
                    true, this);

            rtfFootnote.endBody();
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("endFootnoteBody: " + e.getMessage());
            throw new RuntimeException("Exception: " + e);
        }
    }

    /** {@inheritDoc} */
    public void startLeader(Leader l) {
        if (bDefer) {
            return;
        }

        try {
            percentManager.setDimension(l);
            RtfAttributes rtfAttr = TextAttributesConverter.convertLeaderAttributes(
                    l, percentManager);

            IRtfTextrunContainer container
                  = (IRtfTextrunContainer)builderContext.getContainer(
                      IRtfTextrunContainer.class, true, this);
            RtfTextrun textrun = container.getTextrun();

            textrun.addLeader(rtfAttr);
        } catch (IOException e) {
            log.error("startLeader: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        } catch (FOPException e) {
            log.error("startLeader: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * @param text FOText object
     * @param characters CharSequence of the characters to process.
     */
    public void text(FOText text, CharSequence characters) {
        if (bDefer) {
            return;
        }

        try {
            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class, true, this);

            RtfTextrun textrun = container.getTextrun();
            RtfAttributes rtfAttr
                = TextAttributesConverter.convertCharacterAttributes(text);

            textrun.pushInlineAttributes(rtfAttr);
            textrun.addString(characters.toString());
            textrun.popInlineAttributes();
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("characters:" + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void startPageNumber(PageNumber pagenum) {
        if (bDefer) {
            return;
        }

        try {
            RtfAttributes rtfAttr
                = TextAttributesConverter.convertCharacterAttributes(
                    pagenum);

            IRtfTextrunContainer container
                = (IRtfTextrunContainer)builderContext.getContainer(
                    IRtfTextrunContainer.class, true, this);

            RtfTextrun textrun = container.getTextrun();
            textrun.addPageNumber(rtfAttr);
        } catch (IOException ioe) {
            handleIOTrouble(ioe);
        } catch (Exception e) {
            log.error("startPageNumber: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void endPageNumber(PageNumber pagenum) {
        if (bDefer) {
            return;
        }
    }

    /** {@inheritDoc} */
    public void startPageNumberCitation(PageNumberCitation l) {
        if (bDefer) {
            return;
        }
        try {

            IRtfTextrunContainer container
                  = (IRtfTextrunContainer)builderContext.getContainer(
                      IRtfTextrunContainer.class, true, this);
            RtfTextrun textrun = container.getTextrun();

            textrun.addPageNumberCitation(l.getRefId());

        } catch (Exception e) {
            log.error("startPageNumberCitation: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /** {@inheritDoc} */
    public void startPageNumberCitationLast(PageNumberCitationLast l) {
        if (bDefer) {
            return;
        }
        try {

            IRtfTextrunContainer container
                  = (IRtfTextrunContainer)builderContext.getContainer(
                      IRtfTextrunContainer.class, true, this);
            RtfTextrun textrun = container.getTextrun();

            textrun.addPageNumberCitation(l.getRefId());

        } catch (RtfException e) {
            log.error("startPageNumberCitationLast: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        } catch (IOException e) {
            log.error("startPageNumberCitationLast: " + e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private void prepareTable(Table tab) {
        // Allows to receive the available width of the table
        percentManager.setDimension(tab);

        // Table gets expanded by half of the border on each side inside Word
        // When using wide borders the table gets cut off
        int tabDiff = tab.getCommonBorderPaddingBackground().getBorderStartWidth(false) / 2
                + tab.getCommonBorderPaddingBackground().getBorderEndWidth(false);

        // check for "auto" value
        if (!(tab.getInlineProgressionDimension().getMaximum(null).getLength()
                    instanceof EnumLength)) {
            // value specified
            percentManager.setDimension(tab,
                    tab.getInlineProgressionDimension().getMaximum(null)
                        .getLength().getValue(percentManager)
                    - tabDiff);
        } else {
            // set table width again without border width
            percentManager.setDimension(tab, percentManager.getBaseLength(
                    LengthBase.CONTAINING_BLOCK_WIDTH, tab) - tabDiff);
        }

        ColumnSetup columnSetup = new ColumnSetup(tab);
        //int sumOfColumns = columnSetup.getSumOfColumnWidths(percentManager);
        float tableWidth = percentManager.getBaseLength(LengthBase.CONTAINING_BLOCK_WIDTH, tab);
        float tableUnit = columnSetup.computeTableUnit(percentManager, Math.round(tableWidth));
        percentManager.setTableUnit(tab, Math.round(tableUnit));

    }

    /**
     * Calls the appropriate event handler for the passed FObj.
     *
     * @param foNode FO node whose event is to be called
     * @param bStart TRUE calls the start handler, FALSE the end handler
     */
    private void invokeDeferredEvent(FONode foNode, boolean bStart) {
        if (foNode instanceof PageSequence) {
            if (bStart) {
                startPageSequence((PageSequence) foNode);
            } else {
                endPageSequence((PageSequence) foNode);
            }
        } else if (foNode instanceof Flow) {
            if (bStart) {
                startFlow((Flow) foNode);
            } else {
                endFlow((Flow) foNode);
            }
        } else if (foNode instanceof StaticContent) {
            if (bStart) {
                startStatic(null);
            } else {
                endStatic(null);
            }
        } else if (foNode instanceof ExternalGraphic) {
            if (bStart) {
                image((ExternalGraphic) foNode);
            }
        } else if (foNode instanceof InstreamForeignObject) {
            if (bStart) {
                endInstreamForeignObject((InstreamForeignObject) foNode);
            }
        } else if (foNode instanceof Block) {
            if (bStart) {
                startBlock((Block) foNode);
            } else {
                endBlock((Block) foNode);
            }
        } else if (foNode instanceof BlockContainer) {
            if (bStart) {
                startBlockContainer((BlockContainer) foNode);
            } else {
                endBlockContainer((BlockContainer) foNode);
            }
        } else if (foNode instanceof BasicLink) {
            //BasicLink must be placed before Inline
            if (bStart) {
                startLink((BasicLink) foNode);
            } else {
                endLink(null);
            }
        } else if (foNode instanceof Inline) {
            if (bStart) {
                startInline((Inline) foNode);
            } else {
                endInline((Inline) foNode);
            }
        } else if (foNode instanceof FOText) {
            if (bStart) {
                FOText text = (FOText) foNode;
                text(text, text.getCharSequence());
            }
        } else if (foNode instanceof Character) {
            if (bStart) {
                Character c = (Character) foNode;
                character(c);
            }
        } else if (foNode instanceof PageNumber) {
            if (bStart) {
                startPageNumber((PageNumber) foNode);
            } else {
                endPageNumber((PageNumber) foNode);
            }
        } else if (foNode instanceof Footnote) {
            if (bStart) {
                startFootnote((Footnote) foNode);
            } else {
                endFootnote((Footnote) foNode);
            }
        } else if (foNode instanceof FootnoteBody) {
            if (bStart) {
                startFootnoteBody((FootnoteBody) foNode);
            } else {
                endFootnoteBody((FootnoteBody) foNode);
            }
        } else if (foNode instanceof ListBlock) {
            if (bStart) {
                startList((ListBlock) foNode);
            } else {
                endList((ListBlock) foNode);
            }
        } else if (foNode instanceof ListItemBody) {
            if (bStart) {
                startListBody(null);
            } else {
                endListBody(null);
            }
        } else if (foNode instanceof ListItem) {
            if (bStart) {
                startListItem((ListItem) foNode);
            } else {
                endListItem((ListItem) foNode);
            }
        } else if (foNode instanceof ListItemLabel) {
            if (bStart) {
                startListLabel(null);
            } else {
                endListLabel(null);
            }
        } else if (foNode instanceof Table) {
            if (bStart) {
                startTable((Table) foNode);
            } else {
                endTable((Table) foNode);
            }
        } else if (foNode instanceof TableHeader) {
            if (bStart) {
                startHeader((TableHeader) foNode);
            } else {
                endHeader((TableHeader) foNode);
            }
        } else if (foNode instanceof TableFooter) {
            if (bStart) {
                startFooter((TableFooter) foNode);
            } else {
                endFooter((TableFooter) foNode);
            }
        } else if (foNode instanceof TableBody) {
            if (bStart) {
                startBody((TableBody) foNode);
            } else {
                endBody((TableBody) foNode);
            }
        } else if (foNode instanceof TableColumn) {
            if (bStart) {
                startColumn((TableColumn) foNode);
            } else {
                endColumn((TableColumn) foNode);
            }
        } else if (foNode instanceof TableRow) {
            if (bStart) {
                startRow((TableRow) foNode);
            } else {
                endRow((TableRow) foNode);
            }
        } else if (foNode instanceof TableCell) {
            if (bStart) {
                startCell((TableCell) foNode);
            } else {
                endCell((TableCell) foNode);
            }
        } else if (foNode instanceof Leader) {
            if (bStart) {
                startLeader((Leader) foNode);
            }
        } else if (foNode instanceof PageNumberCitation) {
            if (bStart) {
                startPageNumberCitation((PageNumberCitation) foNode);
            } else {
                endPageNumberCitation((PageNumberCitation) foNode);
            }
        } else if (foNode instanceof PageNumberCitationLast) {
            if (bStart) {
                startPageNumberCitationLast((PageNumberCitationLast) foNode);
            } else {
                endPageNumberCitationLast((PageNumberCitationLast) foNode);
            }
        } else {
            RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.ignoredDeferredEvent(this, foNode, bStart, foNode.getLocator());
        }
    }

    /**
     * Closes any mismatched tags that are detected in the RTF structure.
     * @param containerClass The class representing the tag to close.
     * @return Determines whether the tag mismatch has been handled.
     */
    public boolean endContainer(Class containerClass) {
        if (containerClass == RtfTableRow.class) {
            endRow(null);
            return true;
        }
        return false;
    }

    /**
     * Calls the event handlers for the passed FONode and all its elements.
     *
     * @param foNode FONode object which shall be recursed
     */
    private void recurseFONode(FONode foNode) {
        invokeDeferredEvent(foNode, true);

        if (foNode instanceof PageSequence) {
            PageSequence pageSequence = (PageSequence) foNode;

            Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
            if (regionBefore != null) {
                FONode staticBefore = pageSequence.getFlowMap().get(
                        regionBefore.getRegionName());
                if (staticBefore != null) {
                    recurseFONode(staticBefore);
                }
            }
            Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
            if (regionAfter != null) {
                FONode staticAfter = pageSequence.getFlowMap().get(
                        regionAfter.getRegionName());
                if (staticAfter != null) {
                    recurseFONode(staticAfter);
                }
            }


            recurseFONode(pageSequence.getMainFlow());
        } else if (foNode instanceof Table) {
            Table table = (Table) foNode;

            //recurse all table-columns
            if (table.getColumns() != null) {
              //Calculation for column-widths which are not set
              prepareTable(table);

                for (Object o : table.getColumns()) {
                    recurseFONode((FONode) o);
                }
            } else {
                //TODO Implement implicit column setup handling!
                RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
                        getUserAgent().getEventBroadcaster());
                eventProducer.explicitTableColumnsRequired(this, table.getLocator());
            }

            //recurse table-header
            if (table.getTableHeader() != null) {
                recurseFONode(table.getTableHeader());
            }

            //recurse table-footer
            if (table.getTableFooter() != null) {
                recurseFONode(table.getTableFooter());
            }

            if (foNode.getChildNodes() != null) {
                for (Iterator it = foNode.getChildNodes(); it.hasNext();) {
                    recurseFONode((FONode) it.next());
                }
            }
        } else if (foNode instanceof ListItem) {
            ListItem item = (ListItem) foNode;

            recurseFONode(item.getLabel());
            recurseFONode(item.getBody());
        } else if (foNode instanceof Footnote) {
            Footnote fn = (Footnote)foNode;

            recurseFONode(fn.getFootnoteCitation());
            recurseFONode(fn.getFootnoteBody());
        } else {
            //Any other FO-Object: Simply recurse through all childNodes.
            if (foNode.getChildNodes() != null) {
                for (Iterator it = foNode.getChildNodes(); it.hasNext();) {
                    FONode fn = (FONode)it.next();
                    if (log.isTraceEnabled()) {
                        log.trace("  ChildNode for " + fn + " (" + fn.getName() + ")");
                    }
                    recurseFONode(fn);
                }
            }
        }

        invokeDeferredEvent(foNode, false);
    }
}
