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

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;

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

import org.apache.xmlgraphics.image.loader.ImageException;
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.util.QName;

import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Trait.Background;
import org.apache.fop.area.Trait.InternalLink;
import org.apache.fop.area.inline.AbstractTextArea;
import org.apache.fop.area.inline.Container;
import org.apache.fop.area.inline.ForeignObject;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineBlock;
import org.apache.fop.area.inline.InlineBlockParent;
import org.apache.fop.area.inline.InlineParent;
import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.Direction;
import org.apache.fop.traits.Visibility;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.ConversionUtils;
import org.apache.fop.util.DefaultErrorListener;
import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;

import static org.apache.fop.fo.Constants.FO_REGION_AFTER;
import static org.apache.fop.fo.Constants.FO_REGION_BEFORE;
import static org.apache.fop.fo.Constants.FO_REGION_BODY;
import static org.apache.fop.fo.Constants.FO_REGION_END;
import static org.apache.fop.fo.Constants.FO_REGION_START;

/**
 * This is a parser for the area tree XML (intermediate format) which is used to reread an area
 * tree (or part of it) into memory again for rendering to the final output format.
 */
public class AreaTreeParser {

    /** Logger instance */
    protected static final Log log = LogFactory.getLog(AreaTreeParser.class);

    private static SAXTransformerFactory tFactory
        = (SAXTransformerFactory)SAXTransformerFactory.newInstance();

    /**
     * Parses an intermediate file (area tree XML) into an AreaTreeModel instance by adding
     * pages to it.
     * @param src the Source instance pointing to the intermediate file
     * @param treeModel the AreaTreeModel that the parsed pages are added to
     * @param userAgent the user agent
     * @throws TransformerException if an error occurs while parsing the area tree XML
     */
    public void parse(Source src, AreaTreeModel treeModel, FOUserAgent userAgent)
            throws TransformerException {
        Transformer transformer = tFactory.newTransformer();
        transformer.setErrorListener(new DefaultErrorListener(log));

        SAXResult res = new SAXResult(getContentHandler(treeModel, userAgent));

        transformer.transform(src, res);
    }

    /**
     * Creates a new ContentHandler instance that you can send the area tree XML to. The parsed
     * pages are added to the AreaTreeModel instance you pass in as a parameter.
     * @param treeModel the AreaTreeModel that the parsed pages are added to
     * @param userAgent the user agent
     * @return the ContentHandler instance to receive the SAX stream from the area tree XML
     */
    public ContentHandler getContentHandler(AreaTreeModel treeModel, FOUserAgent userAgent) {
        ElementMappingRegistry elementMappingRegistry
            = userAgent.getElementMappingRegistry();
        return new Handler(treeModel, userAgent, elementMappingRegistry);
    }

    private static class Handler extends DefaultHandler {

        private Map<String, AbstractMaker> makers = new java.util.HashMap<String, AbstractMaker>();

        private AreaTreeModel treeModel;
        private FOUserAgent userAgent;
        private ElementMappingRegistry elementMappingRegistry;

        private Attributes lastAttributes;

        private CharBuffer content = CharBuffer.allocate(64);
        private boolean ignoreCharacters = true;

        private PageViewport currentPageViewport;
        private Map<String, PageViewport> pageViewportsByKey
                = new java.util.HashMap<String, PageViewport>();
        // set of "ID firsts" that have already been assigned to a PV:
        private Set<String> idFirstsAssigned = new java.util.HashSet<String>();

        private Stack<Object> areaStack = new Stack<Object>();
        private boolean firstFlow;

        private Stack<String> delegateStack = new Stack<String>();
        private ContentHandler delegate;
        private DOMImplementation domImplementation;
        private Locator locator;

        public Handler(AreaTreeModel treeModel, FOUserAgent userAgent,
                ElementMappingRegistry elementMappingRegistry) {
            this.treeModel = treeModel;
            this.userAgent = userAgent;
            this.elementMappingRegistry = elementMappingRegistry;
            makers.put("areaTree", new AreaTreeMaker());
            makers.put("page", new PageMaker());
            makers.put("pageSequence", new PageSequenceMaker());
            makers.put("title", new TitleMaker());
            makers.put("pageViewport", new PageViewportMaker());
            makers.put("regionViewport", new RegionViewportMaker());
            makers.put("regionBefore", new RegionBeforeMaker());
            makers.put("regionAfter", new RegionAfterMaker());
            makers.put("regionStart", new RegionStartMaker());
            makers.put("regionEnd", new RegionEndMaker());
            makers.put("regionBody", new RegionBodyMaker());
            makers.put("flow", new FlowMaker());
            makers.put("mainReference", new MainReferenceMaker());
            makers.put("span", new SpanMaker());
            makers.put("footnote", new FootnoteMaker());
            makers.put("beforeFloat", new BeforeFloatMaker());
            makers.put("block", new BlockMaker());
            makers.put("lineArea", new LineAreaMaker());
            makers.put("inline", new InlineMaker());
            makers.put("inlineblock", new InlineBlockMaker());
            makers.put("inlineparent", new InlineParentMaker());
            makers.put("inlineblockparent", new InlineBlockParentMaker());
            makers.put("text", new TextMaker());
            makers.put("word", new WordMaker());
            makers.put("space", new SpaceMaker());
            makers.put("leader", new LeaderMaker());
            makers.put("viewport", new InlineViewportMaker());
            makers.put("container", new ContainerMaker());
            makers.put("image", new ImageMaker());
            makers.put("foreignObject", new ForeignObjectMaker());
            makers.put("bookmarkTree", new BookmarkTreeMaker());
            makers.put("bookmark", new BookmarkMaker());
            makers.put("destination", new DestinationMaker());
        }

        private Area findAreaType(Class clazz) {
            if (areaStack.size() > 0) {
                int pos = areaStack.size() - 1;
                Object obj = null;
                while (pos >= 0) {
                    obj = areaStack.get(pos);
                    if (clazz.isInstance(obj)) {
                        break;
                    } else {
                        pos--;
                    }
                }
                if (pos >= 0) {
                    return (Area)obj;
                }
            }
            return null;
        }

        private RegionViewport getCurrentRegionViewport() {
            return (RegionViewport)findAreaType(RegionViewport.class);
        }

        private BodyRegion getCurrentBodyRegion() {
            return (BodyRegion)findAreaType(BodyRegion.class);
        }

        private BlockParent getCurrentBlockParent() {
            return (BlockParent)findAreaType(BlockParent.class);
        }

        private AbstractTextArea getCurrentText() {
            return (AbstractTextArea)findAreaType(AbstractTextArea.class);
        }

        private InlineViewport getCurrentViewport() {
            return (InlineViewport)findAreaType(InlineViewport.class);
        }

        /** {@inheritDoc} */
        public void setDocumentLocator(Locator locator) {
            this.locator = locator;
        }

        private Locator getLocator() {
            return this.locator;
        }

        /** {@inheritDoc} */
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                    throws SAXException {
            if (delegate != null) {
                delegateStack.push(qName);
                delegate.startElement(uri, localName, qName, attributes);
            } else if (domImplementation != null) {
                //domImplementation is set so we need to start a new DOM building sub-process
                TransformerHandler handler;
                try {
                    handler = tFactory.newTransformerHandler();
                } catch (TransformerConfigurationException e) {
                    throw new SAXException("Error creating a new TransformerHandler", e);
                }
                Document doc = domImplementation.createDocument(uri, qName, null);
                //It's easier to work with an empty document, so remove the root element
                doc.removeChild(doc.getDocumentElement());
                handler.setResult(new DOMResult(doc));
                Area parent = (Area)areaStack.peek();
                ((ForeignObject)parent).setDocument(doc);

                //activate delegate for nested foreign document
                domImplementation = null; //Not needed anymore now
                this.delegate = handler;
                delegateStack.push(qName);
                delegate.startDocument();
                delegate.startElement(uri, localName, qName, attributes);
            } else {
                boolean handled = true;
                if ("".equals(uri)) {
                    if (localName.equals("structureTree")) {

                        /* The area tree parser no longer supports the structure tree. */
                        delegate = new DefaultHandler();

                        delegateStack.push(qName);
                        delegate.startDocument();
                        delegate.startElement(uri, localName, qName, attributes);
                    } else {
                        handled = startAreaTreeElement(localName, attributes);
                    }
                } else {
                    ContentHandlerFactoryRegistry registry
                            = userAgent.getContentHandlerFactoryRegistry();
                    ContentHandlerFactory factory = registry.getFactory(uri);
                    if (factory != null) {
                        delegate = factory.createContentHandler();
                        delegateStack.push(qName);
                        delegate.startDocument();
                        delegate.startElement(uri, localName, qName, attributes);
                    } else {
                        handled = false;
                    }
                }
                if (!handled) {
                    if (uri == null || uri.length() == 0) {
                        throw new SAXException("Unhandled element " + localName
                                + " in namespace: " + uri);
                    } else {
                        log.warn("Unhandled element " + localName
                                + " in namespace: " + uri);
                    }
                }
            }
        }

        private boolean startAreaTreeElement(String localName, Attributes attributes)
                throws SAXException {
            lastAttributes = new AttributesImpl(attributes);
            Maker maker = makers.get(localName);
            content.clear();
            ignoreCharacters = true;
            if (maker != null) {
                ignoreCharacters = maker.ignoreCharacters();
                maker.startElement(attributes);
            } else if ("extension-attachments".equals(localName)) {
                //TODO implement me
            } else {
                return false;
            }
            return true;
        }

        /** {@inheritDoc} */
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (delegate != null) {
                delegate.endElement(uri, localName, qName);
                delegateStack.pop();
                if (delegateStack.size() == 0) {
                    delegate.endDocument();
                    if (delegate instanceof ContentHandlerFactory.ObjectSource) {
                        Object obj = ((ContentHandlerFactory.ObjectSource)delegate).getObject();
                        handleExternallyGeneratedObject(obj);
                    }
                    delegate = null; //Sub-document is processed, return to normal processing
                }
            } else {
                if ("".equals(uri)) {
                    Maker maker = makers.get(localName);
                    if (maker != null) {
                        maker.endElement();
                        content.clear();
                    }
                    ignoreCharacters = true;
                } else {
                    //log.debug("Ignoring " + localName + " in namespace: " + uri);
                }
            }
        }

        // ============== Maker classes for the area tree objects =============

        private interface Maker {
            void startElement(Attributes attributes) throws SAXException;
            void endElement();
            boolean ignoreCharacters();
        }

        private abstract class AbstractMaker implements Maker {

            public void startElement(Attributes attributes) throws SAXException {
                //nop
            }

            public void endElement() {
                //nop
            }

            public boolean ignoreCharacters() {
                return true;
            }
        }

        private class AreaTreeMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                // In case the Handler is reused:
                idFirstsAssigned.clear();
            }
        }

        private class PageSequenceMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                PageSequence pageSequence = new PageSequence(null);
                String lang = attributes.getValue(javax.xml.XMLConstants.XML_NS_URI, "lang");
                if (lang != null) {
                    pageSequence.setLocale(LanguageTags.toLocale(lang));
                }
                transferForeignObjects(attributes, pageSequence);
                areaStack.push(pageSequence);
            }
        }

        private class TitleMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                LineArea line = new LineArea();
                transferForeignObjects(attributes, line);
                areaStack.push(line);
            }

            public void endElement() {
                LineArea line = (LineArea)areaStack.pop();
                PageSequence pageSequence = (PageSequence)areaStack.peek();
                pageSequence.setTitle(line);
            }

        }

        private class PageViewportMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                if (!areaStack.isEmpty()) {
                    PageSequence pageSequence = (PageSequence)areaStack.peek();
                    treeModel.startPageSequence(pageSequence);
                    areaStack.pop();
                }
                if (currentPageViewport != null) {
                    throw new IllegalStateException("currentPageViewport must be null");
                }
                Rectangle viewArea = XMLUtil.getAttributeAsRectangle(attributes, "bounds");
                int pageNumber = XMLUtil.getAttributeAsInt(attributes, "nr", -1);
                String key = attributes.getValue("key");
                String pageNumberString = attributes.getValue("formatted-nr");
                String pageMaster = attributes.getValue("simple-page-master-name");
                boolean blank = XMLUtil.getAttributeAsBoolean(attributes, "blank", false);
                currentPageViewport = new PageViewport(viewArea,
                        pageNumber, pageNumberString,
                        pageMaster, blank);
                transferForeignObjects(attributes, currentPageViewport);
                currentPageViewport.setKey(key);
                pageViewportsByKey.put(key, currentPageViewport);
            }

        }

        private class PageMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                Page p = new Page();
                currentPageViewport.setPage(p);
            }

            public void endElement() {
                treeModel.addPage(currentPageViewport);
                currentPageViewport = null;
            }
        }

        private class RegionViewportMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                RegionViewport rv = getCurrentRegionViewport();
                if (rv != null) {
                    throw new IllegalStateException("Current RegionViewport must be null");
                }
                Rectangle2D viewArea = XMLUtil.getAttributeAsRectangle2D(attributes, "rect");
                rv = new RegionViewport(viewArea);
                transferForeignObjects(attributes, rv);
                rv.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clipped", false));
                setAreaAttributes(attributes, rv);
                setTraits(attributes, rv, SUBSET_COMMON);
                setTraits(attributes, rv, SUBSET_BOX);
                setTraits(attributes, rv, SUBSET_COLOR);
                areaStack.push(rv);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), RegionViewport.class);
            }
        }

        private class RegionBeforeMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                pushNewRegionReference(attributes, FO_REGION_BEFORE);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), RegionReference.class);
            }
        }

        private class RegionAfterMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                pushNewRegionReference(attributes, FO_REGION_AFTER);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), RegionReference.class);
            }
        }

        private class RegionStartMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                pushNewRegionReference(attributes, FO_REGION_START);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), RegionReference.class);
            }
        }

        private class RegionEndMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                pushNewRegionReference(attributes, FO_REGION_END);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), RegionReference.class);
            }
        }

        private class RegionBodyMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                BodyRegion body = getCurrentBodyRegion();
                if (body != null) {
                    throw new IllegalStateException("Current BodyRegion must be null");
                }
                String regionName = attributes.getValue("name");
                int columnCount = XMLUtil.getAttributeAsInt(attributes, "columnCount", 1);
                int columnGap = XMLUtil.getAttributeAsInt(attributes, "columnGap", 0);
                RegionViewport rv = getCurrentRegionViewport();
                body = new BodyRegion(FO_REGION_BODY, regionName, rv, columnCount, columnGap);
                transferForeignObjects(attributes, body);
                body.setCTM(getAttributeAsCTM(attributes, "ctm"));
                setAreaAttributes(attributes, body);
                setTraits(attributes, body, SUBSET_BORDER_PADDING);
                rv.setRegionReference(body);
                currentPageViewport.getPage().setRegionViewport(FO_REGION_BODY, rv);
                areaStack.push(body);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), BodyRegion.class);
            }
        }

        private class FlowMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                BodyRegion body = getCurrentBodyRegion();
                if (!firstFlow) {
                    body.getMainReference().getCurrentSpan().moveToNextFlow();
                } else {
                    firstFlow = false;
                }
                NormalFlow flow = body.getMainReference().getCurrentSpan().getCurrentFlow();
                transferForeignObjects(attributes, flow);
                setAreaAttributes(attributes, flow);
                areaStack.push(flow);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), NormalFlow.class);
            }
        }

        private class MainReferenceMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                //mainReference is created by the BodyRegion
                MainReference mr = getCurrentBodyRegion().getMainReference();
                transferForeignObjects(attributes, mr);
                setAreaAttributes(attributes, mr);
            }
        }

        private class SpanMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                int ipd = XMLUtil.getAttributeAsInt(attributes, "ipd", 0);
                int columnCount = XMLUtil.getAttributeAsInt(attributes, "columnCount", 1);
                BodyRegion body = getCurrentBodyRegion();
                Span span = new Span(columnCount,
                        body.getColumnGap(), ipd);

                String blockDirection = attributes.getValue("block-progression-direction");
                if (blockDirection != null) {
                    span.addTrait(Trait.BLOCK_PROGRESSION_DIRECTION, Direction.valueOf(blockDirection));
                }

                String inlineDirection = attributes.getValue("inline-progression-direction");
                if (inlineDirection != null) {
                    span.addTrait(Trait.INLINE_PROGRESSION_DIRECTION, Direction.valueOf(inlineDirection));
                }

                transferForeignObjects(attributes, span);
                setAreaAttributes(attributes, span);
                body.getMainReference().getSpans().add(span);
                firstFlow = true;
            }
        }

        private class FootnoteMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                Footnote fn = getCurrentBodyRegion().getFootnote();
                transferForeignObjects(attributes, fn);
                fn.setTop(XMLUtil.getAttributeAsInt(attributes, "top-offset", 0));
                areaStack.push(fn);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), Footnote.class);
            }
        }

        private class BeforeFloatMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                BeforeFloat bf = getCurrentBodyRegion().getBeforeFloat();
                transferForeignObjects(attributes, bf);
                areaStack.push(bf);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), BeforeFloat.class);
            }
        }

        private class BlockMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                boolean isViewport = XMLUtil.getAttributeAsBoolean(attributes,
                        "is-viewport-area", false);
                Block block;
                if (isViewport) {
                    BlockViewport bv = new BlockViewport();
                    bv.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clipped", false));
                    bv.setCTM(getAttributeAsCTM(attributes, "ctm"));
                    if (bv.getPositioning() != BlockViewport.RELATIVE) {
                        bv.setXOffset(
                                XMLUtil.getAttributeAsInt(attributes, "left-position", 0));
                        bv.setYOffset(
                                XMLUtil.getAttributeAsInt(attributes, "top-position", 0));
                    }
                    block = bv;
                } else {
                    block = new Block();
                }
                String positioning = attributes.getValue("positioning");
                if ("absolute".equalsIgnoreCase(positioning)) {
                    block.setPositioning(Block.ABSOLUTE);
                } else if ("fixed".equalsIgnoreCase(positioning)) {
                    block.setPositioning(Block.FIXED);
                } else if ("relative".equalsIgnoreCase(positioning)) {
                    block.setPositioning(Block.RELATIVE);
                } else {
                    block.setPositioning(Block.STACK);
                }
                if (attributes.getValue("left-offset") != null) {
                    block.setXOffset(XMLUtil.getAttributeAsInt(attributes, "left-offset", 0));
                }
                if (attributes.getValue("top-offset") != null) {
                    block.setYOffset(XMLUtil.getAttributeAsInt(attributes, "top-offset", 0));
                }
                if (attributes.getValue("visibility") != null) {
                    block.addTrait(Trait.VISIBILITY, Visibility.valueOf(attributes.getValue("visibility")));
                }

                transferForeignObjects(attributes, block);
                setAreaAttributes(attributes, block);
                setTraits(attributes, block, SUBSET_COMMON);
                setTraits(attributes, block, SUBSET_BOX);
                setTraits(attributes, block, SUBSET_COLOR);
                Area parent = (Area)areaStack.peek();
                //BlockParent parent = getCurrentBlockParent();
                parent.addChildArea(block);
                areaStack.push(block);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), Block.class);
            }
        }

        private class LineAreaMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                LineArea line = new LineArea();
                setAreaAttributes(attributes, line);
                setTraits(attributes, line, SUBSET_COMMON);
                setTraits(attributes, line, SUBSET_BOX);
                setTraits(attributes, line, SUBSET_COLOR);
                BlockParent parent = getCurrentBlockParent();
                parent.addChildArea(line);
                areaStack.push(line);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), LineArea.class);
            }
        }

        // Maker for "generic" inline areas
        private class InlineMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                InlineArea inl = new InlineArea();
                transferForeignObjects(attributes, inl);
                inl.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
                setAreaAttributes(attributes, inl);
                setTraits(attributes, inl, SUBSET_COMMON);
                setTraits(attributes, inl, SUBSET_BOX);
                setTraits(attributes, inl, SUBSET_COLOR);
                Area parent = (Area)areaStack.peek();
                parent.addChildArea(inl);
                areaStack.push(inl);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), InlineArea.class);
            }
        }

        private class InlineBlockMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {

                Block block = new Block();

                if (attributes.getValue("left-offset") != null) {
                    block.setXOffset(XMLUtil.getAttributeAsInt(attributes, "left-offset", 0));
                }
                if (attributes.getValue("top-offset") != null) {
                    block.setYOffset(XMLUtil.getAttributeAsInt(attributes, "top-offset", 0));
                }
                transferForeignObjects(attributes, block);
                setAreaAttributes(attributes, block);
                setTraits(attributes, block, SUBSET_COMMON);
                setTraits(attributes, block, SUBSET_BOX);
                setTraits(attributes, block, SUBSET_COLOR);
                Area parent = (Area)areaStack.peek();
                InlineBlock inlineBlock = new InlineBlock(block);
                parent.addChildArea(inlineBlock);
                areaStack.push(inlineBlock);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), InlineBlock.class);
            }
        }

        private class InlineParentMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                InlineParent ip = new InlineParent();
                transferForeignObjects(attributes, ip);
                ip.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
                setAreaAttributes(attributes, ip);
                setTraits(attributes, ip, SUBSET_COMMON);
                setTraits(attributes, ip, SUBSET_BOX);
                setTraits(attributes, ip, SUBSET_COLOR);
                setTraits(attributes, ip, SUBSET_LINK);
                Area parent = (Area)areaStack.peek();
                parent.addChildArea(ip);
                areaStack.push(ip);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), InlineParent.class);
            }
        }

        private class InlineBlockParentMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                InlineBlockParent ibp = new InlineBlockParent();
                transferForeignObjects(attributes, ibp);
                ibp.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
                setAreaAttributes(attributes, ibp);
                setTraits(attributes, ibp, SUBSET_COMMON);
                setTraits(attributes, ibp, SUBSET_BOX);
                setTraits(attributes, ibp, SUBSET_COLOR);
                Area parent = (Area)areaStack.peek();
                parent.addChildArea(ibp);
                areaStack.push(ibp);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), InlineBlockParent.class);
            }
        }

        private class TextMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                if (getCurrentText() != null) {
                    throw new IllegalStateException("Current Text must be null");
                }
                TextArea text = new TextArea();
                setAreaAttributes(attributes, text);
                setTraits(attributes, text, SUBSET_COMMON);
                setTraits(attributes, text, SUBSET_BOX);
                setTraits(attributes, text, SUBSET_COLOR);
                setTraits(attributes, text, SUBSET_FONT);
                text.setBaselineOffset(XMLUtil.getAttributeAsInt(attributes, "baseline", 0));
                text.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
                text.setTextLetterSpaceAdjust(XMLUtil.getAttributeAsInt(attributes,
                        "tlsadjust", 0));
                text.setTextWordSpaceAdjust(XMLUtil.getAttributeAsInt(attributes,
                        "twsadjust", 0));
                Area parent = (Area)areaStack.peek();
                parent.addChildArea(text);
                areaStack.push(text);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), TextArea.class);
            }
        }

        private class WordMaker extends AbstractMaker {

            public void endElement() {
                int offset = XMLUtil.getAttributeAsInt(lastAttributes, "offset", 0);
                int[] letterAdjust
                        = ConversionUtils.toIntArray(
                            lastAttributes.getValue("letter-adjust"), "\\s");
                int level = XMLUtil.getAttributeAsInt(lastAttributes, "level", -1);
                boolean reversed = XMLUtil.getAttributeAsBoolean(lastAttributes, "reversed", false);
                int[][] gposAdjustments
                    = XMLUtil.getAttributeAsPositionAdjustments(lastAttributes, "position-adjust");
                content.flip();
                WordArea word = new WordArea(
                    offset, level, content.toString().trim(), letterAdjust,
                      null, gposAdjustments, reversed);
                AbstractTextArea text = getCurrentText();
                word.setParentArea(text);
                text.addChildArea(word);
            }

            public boolean ignoreCharacters() {
                return false;
            }
        }

        private class SpaceMaker extends AbstractMaker {

            public void endElement() {
                int offset = XMLUtil.getAttributeAsInt(lastAttributes, "offset", 0);
                //TODO the isAdjustable parameter is currently not used/implemented
                if (content.position() > 0) {
                    content.flip();
                    boolean adjustable = XMLUtil.getAttributeAsBoolean(lastAttributes, "adj", true);
                    int level = XMLUtil.getAttributeAsInt(lastAttributes, "level", -1);
                    SpaceArea space = new SpaceArea(offset, level, content.charAt(0), adjustable);
                    AbstractTextArea text = getCurrentText();
                    space.setParentArea(text);
                    text.addChildArea(space);
                } else {
                    Space space = new Space();
                    setAreaAttributes(lastAttributes, space);
                    setTraits(lastAttributes, space, SUBSET_COMMON);
                    setTraits(lastAttributes, space, SUBSET_BOX);
                    setTraits(lastAttributes, space, SUBSET_COLOR);
                    space.setBlockProgressionOffset(offset);
                    Area parent = (Area)areaStack.peek();
                    parent.addChildArea(space);
                }
            }

            public boolean ignoreCharacters() {
                return false;
            }
        }

        private class LeaderMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                Leader leader = new Leader();
                transferForeignObjects(attributes, leader);
                setAreaAttributes(attributes, leader);
                setTraits(attributes, leader, SUBSET_COMMON);
                setTraits(attributes, leader, SUBSET_BOX);
                setTraits(attributes, leader, SUBSET_COLOR);
                setTraits(attributes, leader, SUBSET_FONT);
                leader.setBlockProgressionOffset(
                    XMLUtil.getAttributeAsInt(attributes, "offset", 0));
                String ruleStyle = attributes.getValue("ruleStyle");
                if (ruleStyle != null) {
                    leader.setRuleStyle(ruleStyle);
                }
                leader.setRuleThickness(
                        XMLUtil.getAttributeAsInt(attributes, "ruleThickness", 0));
                Area parent = (Area)areaStack.peek();
                parent.addChildArea(leader);
            }
        }

        private class ContainerMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                Container container = new Container();
                transferForeignObjects(attributes, container);
                InlineViewport parent = (InlineViewport) areaStack.peek();
                parent.setContent(container);
                areaStack.push(container);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), Container.class);
            }
        }

        private class InlineViewportMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                int level = XMLUtil.getAttributeAsInt(attributes, "level", -1);
                InlineViewport viewport = new InlineViewport(null, level);
                transferForeignObjects(attributes, viewport);
                setAreaAttributes(attributes, viewport);
                setTraits(attributes, viewport, SUBSET_COMMON);
                setTraits(attributes, viewport, SUBSET_BOX);
                setTraits(attributes, viewport, SUBSET_COLOR);
                viewport.setContentPosition(XMLUtil.getAttributeAsRectangle2D(attributes, "pos"));
                viewport.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clip", false));
                viewport.setBlockProgressionOffset(
                    XMLUtil.getAttributeAsInt(attributes, "offset", 0));
                Area parent = (Area)areaStack.peek();
                parent.addChildArea(viewport);
                areaStack.push(viewport);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), InlineViewport.class);
            }
        }

        private class ImageMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                String url = attributes.getValue("url");
                Image image = new Image(url);
                transferForeignObjects(attributes, image);
                setAreaAttributes(attributes, image);
                setTraits(attributes, image, SUBSET_COMMON);
                getCurrentViewport().setContent(image);
            }
        }

        private class ForeignObjectMaker extends AbstractMaker {

            public void startElement(Attributes attributes) throws SAXException {
                String ns = attributes.getValue("ns");
                domImplementation
                    = elementMappingRegistry.getDOMImplementationForNamespace(ns);
                if (domImplementation == null) {
                    throw new SAXException("No DOMImplementation could be"
                            + " identified to handle namespace: " + ns);
                }
                ForeignObject foreign = new ForeignObject(ns);
                transferForeignObjects(attributes, foreign);
                setAreaAttributes(attributes, foreign);
                setTraits(attributes, foreign, SUBSET_COMMON);
                getCurrentViewport().setContent(foreign);
                areaStack.push(foreign);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), ForeignObject.class);
            }
        }

        private class BookmarkTreeMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                BookmarkData bm = new BookmarkData();
                areaStack.push(bm);
            }

            public void endElement() {
                Object tos = areaStack.pop();
                assertObjectOfClass(tos, BookmarkData.class);
                treeModel.handleOffDocumentItem((BookmarkData) tos);
                // as long as the bookmark tree comes after the last PageViewport in the
                // area tree XML, we don't have to worry about resolved/unresolved. The
                // only resolution needed is the mapping of the pvKey to the PV instance.
            }
        }

        private class BookmarkMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                String title = attributes.getValue("title");
                boolean showChildren = XMLUtil.getAttributeAsBoolean(
                        attributes, "show-children", false);
                String[] linkdata
                        = InternalLink.parseXMLAttribute(attributes.getValue("internal-link"));
                PageViewport pv = pageViewportsByKey.get(linkdata[0]);
                BookmarkData bm = new BookmarkData(title, showChildren, pv, linkdata[1]);
                Object tos = areaStack.peek();
                if (tos instanceof BookmarkData) {
                    BookmarkData parent = (BookmarkData) tos;
                    parent.addSubData(bm);
                }
                areaStack.push(bm);
            }

            public void endElement() {
                assertObjectOfClass(areaStack.pop(), BookmarkData.class);
            }
        }

        private class DestinationMaker extends AbstractMaker {

            public void startElement(Attributes attributes) {
                String[] linkdata
                    = InternalLink.parseXMLAttribute(lastAttributes.getValue("internal-link"));
                PageViewport pv = pageViewportsByKey.get(linkdata[0]);
                DestinationData dest = new DestinationData(linkdata[1]);
                List<PageViewport> pages = new java.util.ArrayList<PageViewport>();
                pages.add(pv);
                dest.resolveIDRef(linkdata[1], pages);
                areaStack.push(dest);
            }

            public void endElement() {
                Object tos = areaStack.pop();
                assertObjectOfClass(tos, DestinationData.class);
                treeModel.handleOffDocumentItem((DestinationData) tos);
            }
        }

        // ====================================================================


        private void pushNewRegionReference(Attributes attributes, int side) {
            String regionName = attributes.getValue("name");
            RegionViewport rv = getCurrentRegionViewport();
            RegionReference reg = new RegionReference(side,
                    regionName, rv);
            transferForeignObjects(attributes, reg);
            reg.setCTM(getAttributeAsCTM(attributes, "ctm"));
            setAreaAttributes(attributes, reg);
            setTraits(attributes, reg, SUBSET_BORDER_PADDING);
            rv.setRegionReference(reg);
            currentPageViewport.getPage().setRegionViewport(
                    side, rv);
            areaStack.push(reg);
        }

        private void assertObjectOfClass(Object obj, Class clazz) {
            if (!clazz.isInstance(obj)) {
                throw new IllegalStateException("Object is not an instance of "
                        + clazz.getName() + " but of " + obj.getClass().getName());
            }
        }

        /**
         * Handles objects created by "sub-parsers" that implement the ObjectSource interface.
         * An example of object handled here are ExtensionAttachments.
         * @param obj the Object to be handled.
         */
        protected void handleExternallyGeneratedObject(Object obj) {
            if (areaStack.size() == 0 && obj instanceof ExtensionAttachment) {
                ExtensionAttachment attachment = (ExtensionAttachment)obj;
                if (this.currentPageViewport == null) {
                    this.treeModel.handleOffDocumentItem(
                            new OffDocumentExtensionAttachment(attachment));
                } else {
                    this.currentPageViewport.addExtensionAttachment(attachment);
                }
            } else {
                Object o = areaStack.peek();
                if (o instanceof AreaTreeObject && obj instanceof ExtensionAttachment) {
                    AreaTreeObject ato = (AreaTreeObject)o;
                    ExtensionAttachment attachment = (ExtensionAttachment)obj;
                    ato.addExtensionAttachment(attachment);
                } else {
                log.warn("Don't know how to handle externally generated object: " + obj);
            }
        }
        }

        private void setAreaAttributes(Attributes attributes, Area area) {
            area.setIPD(Integer.parseInt(attributes.getValue("ipd")));
            area.setBPD(Integer.parseInt(attributes.getValue("bpd")));
            area.setBidiLevel(XMLUtil.getAttributeAsInt(attributes, "level", -1));
        }

        private static final Object[] SUBSET_COMMON = new Object[] {
            Trait.PROD_ID, Trait.LAYER};
        private static final Object[] SUBSET_LINK = new Object[] {
            Trait.INTERNAL_LINK, Trait.EXTERNAL_LINK};
        private static final Object[] SUBSET_COLOR = new Object[] {
            Trait.BACKGROUND, Trait.COLOR};
        private static final Object[] SUBSET_FONT = new Object[] {
            Trait.FONT, Trait.FONT_SIZE, Trait.BLINK,
            Trait.OVERLINE, Trait.OVERLINE_COLOR,
            Trait.LINETHROUGH, Trait.LINETHROUGH_COLOR,
            Trait.UNDERLINE, Trait.UNDERLINE_COLOR};
        private static final Object[] SUBSET_BOX = new Object[] {
            Trait.BORDER_BEFORE, Trait.BORDER_AFTER, Trait.BORDER_START, Trait.BORDER_END,
            Trait.SPACE_BEFORE, Trait.SPACE_AFTER, Trait.SPACE_START, Trait.SPACE_END,
            Trait.PADDING_BEFORE, Trait.PADDING_AFTER, Trait.PADDING_START, Trait.PADDING_END,
            Trait.START_INDENT, Trait.END_INDENT,
            Trait.IS_REFERENCE_AREA, Trait.IS_VIEWPORT_AREA};
        private static final Object[] SUBSET_BORDER_PADDING = new Object[] {
            Trait.BORDER_BEFORE, Trait.BORDER_AFTER, Trait.BORDER_START, Trait.BORDER_END,
            Trait.PADDING_BEFORE, Trait.PADDING_AFTER, Trait.PADDING_START, Trait.PADDING_END};

        private void setTraits(Attributes attributes, Area area, Object[] traitSubset) {
            for (int i = traitSubset.length; --i >= 0;) {
                Integer trait = (Integer) traitSubset[i];
                String traitName = Trait.getTraitName(trait);
                String value = attributes.getValue(traitName);
                if (value != null) {
                    Class cl = Trait.getTraitClass(trait);
                    if (cl == Integer.class) {
                        area.addTrait(trait, Integer.valueOf(value));
                    } else if (cl == Boolean.class) {
                        area.addTrait(trait, Boolean.valueOf(value));
                    } else if (cl == String.class) {
                        area.addTrait(trait, value);
                        if (Trait.PROD_ID.equals(trait)
                                && !idFirstsAssigned.contains(value)
                                && currentPageViewport != null) {
                            currentPageViewport.setFirstWithID(value);
                            idFirstsAssigned.add(value);
                        }
                    } else if (cl == Color.class) {
                        try {
                            area.addTrait(trait, ColorUtil.parseColorString(this.userAgent, value));
                        } catch (PropertyException e) {
                            throw new IllegalArgumentException(e.getMessage());
                        }
                    } else if (cl == InternalLink.class) {
                        area.addTrait(trait, new InternalLink(value));
                    } else if (cl == Trait.ExternalLink.class) {
                        area.addTrait(trait, Trait.ExternalLink.makeFromTraitValue(value));
                    } else if (cl == Background.class) {
                        Background bkg = new Background();
                        try {
                            Color col = ColorUtil.parseColorString(
                                        this.userAgent, attributes.getValue("bkg-color"));
                            bkg.setColor(col);
                        } catch (PropertyException e) {
                            throw new IllegalArgumentException(e.getMessage());
                        }
                        String uri = attributes.getValue("bkg-img");
                        if (uri != null) {
                            bkg.setURL(uri);

                            try {
                                ImageManager manager = userAgent.getImageManager();
                                ImageSessionContext sessionContext
                                    = userAgent.getImageSessionContext();
                                ImageInfo info = manager.getImageInfo(uri, sessionContext);
                                bkg.setImageInfo(info);
                            } catch (ImageException e) {
                                ResourceEventProducer eventProducer
                                    = ResourceEventProducer.Provider.get(
                                        this.userAgent.getEventBroadcaster());
                                eventProducer.imageError(this, uri, e, getLocator());
                            } catch (FileNotFoundException fnfe) {
                                ResourceEventProducer eventProducer
                                    = ResourceEventProducer.Provider.get(
                                        this.userAgent.getEventBroadcaster());
                                eventProducer.imageNotFound(this, uri, fnfe, getLocator());
                            } catch (IOException ioe) {
                                ResourceEventProducer eventProducer
                                    = ResourceEventProducer.Provider.get(
                                        this.userAgent.getEventBroadcaster());
                                eventProducer.imageIOError(this, uri, ioe, getLocator());
                            }

                            String repeat = attributes.getValue("bkg-repeat");
                            if (repeat != null) {
                                bkg.setRepeat(repeat);
                            }
                            bkg.setHoriz(XMLUtil.getAttributeAsInt(attributes,
                                    "bkg-horz-offset", 0));
                            bkg.setVertical(XMLUtil.getAttributeAsInt(attributes,
                                    "bkg-vert-offset", 0));
                        }
                        area.addTrait(trait, bkg);
                    } else if (cl == BorderProps.class) {
                        area.addTrait(trait, BorderProps.valueOf(this.userAgent, value));
                    }
                } else {
                    if (Trait.FONT.equals(trait)) {
                        String fontName = attributes.getValue("font-name");
                        if (fontName != null) {
                            String fontStyle = attributes.getValue("font-style");
                            int fontWeight = XMLUtil.getAttributeAsInt(
                                    attributes, "font-weight", Font.WEIGHT_NORMAL);
                            area.addTrait(trait,
                                    FontInfo.createFontKey(fontName, fontStyle, fontWeight));
                        }
                    }
                }
            }
        }

        private static CTM getAttributeAsCTM(Attributes attributes, String name) {
            String s = attributes.getValue(name).trim();
            if (s.startsWith("[") && s.endsWith("]")) {
                s = s.substring(1, s.length() - 1);
                double[] values = ConversionUtils.toDoubleArray(s, "\\s");
                if (values.length != 6) {
                    throw new IllegalArgumentException("CTM must consist of 6 double values!");
                }
                return new CTM(values[0], values[1], values[2], values[3], values[4], values[5]);
            } else {
                throw new IllegalArgumentException("CTM must be surrounded by square brackets!");
            }
        }

        private static void transferForeignObjects(Attributes atts, AreaTreeObject ato) {
            for (int i = 0, c = atts.getLength(); i < c; i++) {
                String ns = atts.getURI(i);
                if (ns.length() > 0) {
                    if (XMLConstants.XMLNS_NAMESPACE_URI.equals(ns)) {
                        continue;
                    }
                    QName qname = new QName(ns, atts.getQName(i));
                    ato.setForeignAttribute(qname, atts.getValue(i));
                }
            }
        }

        /** {@inheritDoc} */
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (delegate != null) {
                delegate.characters(ch, start, length);
            } else if (!ignoreCharacters) {
                int maxLength = this.content.capacity() - this.content.position();
                if (maxLength < length) {
                    // allocate a larger buffer and transfer content
                    CharBuffer newContent
                            = CharBuffer.allocate(this.content.position() + length);
                    this.content.flip();
                    newContent.put(this.content);
                    this.content = newContent;
                }
                // make sure the full capacity is used
                this.content.limit(this.content.capacity());
                // add characters to the buffer
                this.content.put(ch, start, length);
                // decrease the limit, if necessary
                if (this.content.position() < this.content.limit()) {
                    this.content.limit(this.content.position());
                }
            }
        }
    }
}
