| /* |
| * 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.intermediate; |
| |
| import java.awt.Color; |
| import java.awt.Dimension; |
| import java.awt.Paint; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.geom.AffineTransform; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.w3c.dom.Document; |
| |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.AttributesImpl; |
| |
| import org.apache.xmlgraphics.util.QName; |
| import org.apache.xmlgraphics.util.XMLizable; |
| |
| import org.apache.fop.fonts.FontInfo; |
| import org.apache.fop.render.PrintRendererConfigurator; |
| import org.apache.fop.render.RenderingContext; |
| import org.apache.fop.render.intermediate.extensions.AbstractAction; |
| import org.apache.fop.render.intermediate.extensions.Bookmark; |
| import org.apache.fop.render.intermediate.extensions.BookmarkTree; |
| import org.apache.fop.render.intermediate.extensions.DocumentNavigationExtensionConstants; |
| import org.apache.fop.render.intermediate.extensions.Link; |
| import org.apache.fop.render.intermediate.extensions.NamedDestination; |
| import org.apache.fop.traits.BorderProps; |
| import org.apache.fop.traits.RuleStyle; |
| import org.apache.fop.util.ColorUtil; |
| import org.apache.fop.util.DOM2SAX; |
| import org.apache.fop.util.XMLConstants; |
| import org.apache.fop.util.XMLUtil; |
| |
| /** |
| * IFPainter implementation that serializes the intermediate format to XML. |
| */ |
| public class IFSerializer extends AbstractXMLWritingIFDocumentHandler |
| implements IFConstants, IFPainter, IFDocumentNavigationHandler { |
| |
| private IFDocumentHandler mimicHandler; |
| |
| /** Holds the intermediate format state */ |
| private IFState state; |
| |
| /** |
| * Default constructor. |
| */ |
| public IFSerializer() { |
| } |
| |
| /** {@inheritDoc} */ |
| protected String getMainNamespace() { |
| return NAMESPACE; |
| } |
| |
| /** {@inheritDoc} */ |
| public boolean supportsPagesOutOfOrder() { |
| return false; |
| //Theoretically supported but disabled to improve performance when |
| //rendering the IF to the final format later on |
| } |
| |
| /** {@inheritDoc} */ |
| public String getMimeType() { |
| return MIME_TYPE; |
| } |
| |
| /** {@inheritDoc} */ |
| public IFDocumentHandlerConfigurator getConfigurator() { |
| if (this.mimicHandler != null) { |
| return getMimickedDocumentHandler().getConfigurator(); |
| } else { |
| return new PrintRendererConfigurator(getUserAgent()); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public IFDocumentNavigationHandler getDocumentNavigationHandler() { |
| return this; |
| } |
| |
| /** |
| * Tells this serializer to mimic the given document handler (mostly applies to the font set |
| * that is used during layout). |
| * @param targetHandler the document handler to mimic |
| */ |
| public void mimicDocumentHandler(IFDocumentHandler targetHandler) { |
| this.mimicHandler = targetHandler; |
| } |
| |
| /** |
| * Returns the document handler that is being mimicked by this serializer. |
| * @return the mimicked document handler or null if no such document handler has been set |
| */ |
| public IFDocumentHandler getMimickedDocumentHandler() { |
| return this.mimicHandler; |
| } |
| |
| /** {@inheritDoc} */ |
| public FontInfo getFontInfo() { |
| if (this.mimicHandler != null) { |
| return this.mimicHandler.getFontInfo(); |
| } else { |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void setFontInfo(FontInfo fontInfo) { |
| if (this.mimicHandler != null) { |
| this.mimicHandler.setFontInfo(fontInfo); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void setDefaultFontInfo(FontInfo fontInfo) { |
| if (this.mimicHandler != null) { |
| this.mimicHandler.setDefaultFontInfo(fontInfo); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startDocument() throws IFException { |
| super.startDocument(); |
| try { |
| handler.startDocument(); |
| handler.startPrefixMapping("", NAMESPACE); |
| handler.startPrefixMapping(XLINK_PREFIX, XLINK_NAMESPACE); |
| handler.startPrefixMapping(DocumentNavigationExtensionConstants.PREFIX, |
| DocumentNavigationExtensionConstants.NAMESPACE); |
| handler.startElement(EL_DOCUMENT); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startDocument()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startDocumentHeader() throws IFException { |
| try { |
| handler.startElement(EL_HEADER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startDocumentHeader()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endDocumentHeader() throws IFException { |
| try { |
| handler.endElement(EL_HEADER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startDocumentHeader()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startDocumentTrailer() throws IFException { |
| try { |
| handler.startElement(EL_TRAILER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startDocumentTrailer()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endDocumentTrailer() throws IFException { |
| try { |
| handler.endElement(EL_TRAILER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endDocumentTrailer()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endDocument() throws IFException { |
| try { |
| handler.endElement(EL_DOCUMENT); |
| handler.endDocument(); |
| finishDocumentNavigation(); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endDocument()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startPageSequence(String id) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| if (id != null) { |
| atts.addAttribute(XML_NAMESPACE, "id", "xml:id", XMLUtil.CDATA, id); |
| } |
| addForeignAttributes(atts); |
| handler.startElement(EL_PAGE_SEQUENCE, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startPageSequence()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endPageSequence() throws IFException { |
| try { |
| handler.endElement(EL_PAGE_SEQUENCE); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endPageSequence()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startPage(int index, String name, String pageMasterName, Dimension size) |
| throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, "index", Integer.toString(index)); |
| addAttribute(atts, "name", name); |
| addAttribute(atts, "page-master-name", pageMasterName); |
| addAttribute(atts, "width", Integer.toString(size.width)); |
| addAttribute(atts, "height", Integer.toString(size.height)); |
| addForeignAttributes(atts); |
| handler.startElement(EL_PAGE, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startPage()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startPageHeader() throws IFException { |
| try { |
| handler.startElement(EL_PAGE_HEADER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startPageHeader()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endPageHeader() throws IFException { |
| try { |
| handler.endElement(EL_PAGE_HEADER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endPageHeader()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public IFPainter startPageContent() throws IFException { |
| try { |
| handler.startElement(EL_PAGE_CONTENT); |
| this.state = IFState.create(); |
| return this; |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startPageContent()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endPageContent() throws IFException { |
| try { |
| this.state = null; |
| handler.endElement(EL_PAGE_CONTENT); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endPageContent()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startPageTrailer() throws IFException { |
| try { |
| handler.startElement(EL_PAGE_TRAILER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startPageTrailer()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endPageTrailer() throws IFException { |
| try { |
| commitNavigation(); |
| handler.endElement(EL_PAGE_TRAILER); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endPageTrailer()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endPage() throws IFException { |
| try { |
| handler.endElement(EL_PAGE); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endPage()", e); |
| } |
| } |
| |
| //---=== IFPainter ===--- |
| |
| /** {@inheritDoc} */ |
| public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect) |
| throws IFException { |
| startViewport(IFUtil.toString(transform), size, clipRect); |
| } |
| |
| /** {@inheritDoc} */ |
| public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect) |
| throws IFException { |
| startViewport(IFUtil.toString(transforms), size, clipRect); |
| } |
| |
| private void startViewport(String transform, Dimension size, Rectangle clipRect) |
| throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| if (transform != null && transform.length() > 0) { |
| addAttribute(atts, "transform", transform); |
| } |
| addAttribute(atts, "width", Integer.toString(size.width)); |
| addAttribute(atts, "height", Integer.toString(size.height)); |
| if (clipRect != null) { |
| addAttribute(atts, "clip-rect", IFUtil.toString(clipRect)); |
| } |
| handler.startElement(EL_VIEWPORT, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startViewport()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endViewport() throws IFException { |
| try { |
| handler.endElement(EL_VIEWPORT); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endViewport()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startGroup(AffineTransform[] transforms) throws IFException { |
| startGroup(IFUtil.toString(transforms)); |
| } |
| |
| /** {@inheritDoc} */ |
| public void startGroup(AffineTransform transform) throws IFException { |
| startGroup(IFUtil.toString(transform)); |
| } |
| |
| private void startGroup(String transform) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| if (transform != null && transform.length() > 0) { |
| addAttribute(atts, "transform", transform); |
| } |
| handler.startElement(EL_GROUP, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startGroup()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endGroup() throws IFException { |
| try { |
| handler.endElement(EL_GROUP); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in endGroup()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void drawImage(String uri, Rectangle rect) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, XLINK_HREF, uri); |
| addAttribute(atts, "x", Integer.toString(rect.x)); |
| addAttribute(atts, "y", Integer.toString(rect.y)); |
| addAttribute(atts, "width", Integer.toString(rect.width)); |
| addAttribute(atts, "height", Integer.toString(rect.height)); |
| addForeignAttributes(atts); |
| handler.element(EL_IMAGE, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startGroup()", e); |
| } |
| } |
| |
| private void addForeignAttributes(AttributesImpl atts) { |
| Map foreignAttributes = getContext().getForeignAttributes(); |
| if (!foreignAttributes.isEmpty()) { |
| Iterator iter = foreignAttributes.entrySet().iterator(); |
| while (iter.hasNext()) { |
| Map.Entry entry = (Map.Entry)iter.next(); |
| addAttribute(atts, (QName)entry.getKey(), entry.getValue().toString()); |
| } |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void drawImage(Document doc, Rectangle rect) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, "x", Integer.toString(rect.x)); |
| addAttribute(atts, "y", Integer.toString(rect.y)); |
| addAttribute(atts, "width", Integer.toString(rect.width)); |
| addAttribute(atts, "height", Integer.toString(rect.height)); |
| addForeignAttributes(atts); |
| handler.startElement(EL_IMAGE, atts); |
| new DOM2SAX(handler).writeDocument(doc, true); |
| handler.endElement(EL_IMAGE); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in startGroup()", e); |
| } |
| } |
| |
| private static String toString(Paint paint) { |
| if (paint instanceof Color) { |
| return ColorUtil.colorToString((Color)paint); |
| } else { |
| throw new UnsupportedOperationException("Paint not supported: " + paint); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void clipRect(Rectangle rect) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, "x", Integer.toString(rect.x)); |
| addAttribute(atts, "y", Integer.toString(rect.y)); |
| addAttribute(atts, "width", Integer.toString(rect.width)); |
| addAttribute(atts, "height", Integer.toString(rect.height)); |
| handler.element(EL_CLIP_RECT, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in clipRect()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void fillRect(Rectangle rect, Paint fill) throws IFException { |
| if (fill == null) { |
| return; |
| } |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, "x", Integer.toString(rect.x)); |
| addAttribute(atts, "y", Integer.toString(rect.y)); |
| addAttribute(atts, "width", Integer.toString(rect.width)); |
| addAttribute(atts, "height", Integer.toString(rect.height)); |
| addAttribute(atts, "fill", toString(fill)); |
| handler.element(EL_RECT, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in fillRect()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, |
| BorderProps start, BorderProps end) throws IFException { |
| if (before == null && after == null && start == null && end == null) { |
| return; |
| } |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, "x", Integer.toString(rect.x)); |
| addAttribute(atts, "y", Integer.toString(rect.y)); |
| addAttribute(atts, "width", Integer.toString(rect.width)); |
| addAttribute(atts, "height", Integer.toString(rect.height)); |
| if (before != null) { |
| addAttribute(atts, "before", before.toString()); |
| } |
| if (after != null) { |
| addAttribute(atts, "after", after.toString()); |
| } |
| if (start != null) { |
| addAttribute(atts, "start", start.toString()); |
| } |
| if (end != null) { |
| addAttribute(atts, "end", end.toString()); |
| } |
| handler.element(EL_BORDER_RECT, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in drawBorderRect()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void drawLine(Point start, Point end, int width, Color color, RuleStyle style) |
| throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| addAttribute(atts, "x1", Integer.toString(start.x)); |
| addAttribute(atts, "y1", Integer.toString(start.y)); |
| addAttribute(atts, "x2", Integer.toString(end.x)); |
| addAttribute(atts, "y2", Integer.toString(end.y)); |
| addAttribute(atts, "stroke-width", Integer.toString(width)); |
| addAttribute(atts, "color", ColorUtil.colorToString(color)); |
| addAttribute(atts, "style", style.getName()); |
| handler.element(EL_LINE, atts); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in drawLine()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void drawText(int x, int y, int letterSpacing, int wordSpacing, |
| int[] dx, String text) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve"); |
| addAttribute(atts, "x", Integer.toString(x)); |
| addAttribute(atts, "y", Integer.toString(y)); |
| if (letterSpacing != 0) { |
| addAttribute(atts, "letter-spacing", Integer.toString(letterSpacing)); |
| } |
| if (wordSpacing != 0) { |
| addAttribute(atts, "word-spacing", Integer.toString(wordSpacing)); |
| } |
| if (dx != null) { |
| addAttribute(atts, "dx", IFUtil.toString(dx)); |
| } |
| handler.startElement(EL_TEXT, atts); |
| char[] chars = text.toCharArray(); |
| handler.characters(chars, 0, chars.length); |
| handler.endElement(EL_TEXT); |
| } catch (SAXException e) { |
| throw new IFException("SAX error in setFont()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void setFont(String family, String style, Integer weight, String variant, Integer size, |
| Color color) throws IFException { |
| try { |
| AttributesImpl atts = new AttributesImpl(); |
| boolean changed; |
| if (family != null) { |
| changed = !family.equals(state.getFontFamily()); |
| if (changed) { |
| state.setFontFamily(family); |
| addAttribute(atts, "family", family); |
| } |
| } |
| if (style != null) { |
| changed = !style.equals(state.getFontStyle()); |
| if (changed) { |
| state.setFontStyle(style); |
| addAttribute(atts, "style", style); |
| } |
| } |
| if (weight != null) { |
| changed = (weight.intValue() != state.getFontWeight()); |
| if (changed) { |
| state.setFontWeight(weight.intValue()); |
| addAttribute(atts, "weight", weight.toString()); |
| } |
| } |
| if (variant != null) { |
| changed = !variant.equals(state.getFontVariant()); |
| if (changed) { |
| state.setFontVariant(variant); |
| addAttribute(atts, "variant", variant); |
| } |
| } |
| if (size != null) { |
| changed = (size.intValue() != state.getFontSize()); |
| if (changed) { |
| state.setFontSize(size.intValue()); |
| addAttribute(atts, "size", size.toString()); |
| } |
| } |
| if (color != null) { |
| changed = !color.equals(state.getTextColor()); |
| if (changed) { |
| state.setTextColor(color); |
| addAttribute(atts, "color", toString(color)); |
| } |
| } |
| if (atts.getLength() > 0) { |
| handler.element(EL_FONT, atts); |
| } |
| } catch (SAXException e) { |
| throw new IFException("SAX error in setFont()", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void handleExtensionObject(Object extension) throws IFException { |
| if (extension instanceof XMLizable) { |
| try { |
| ((XMLizable)extension).toSAX(this.handler); |
| } catch (SAXException e) { |
| throw new IFException("SAX error while handling extension object", e); |
| } |
| } else { |
| throw new UnsupportedOperationException( |
| "Extension must implement XMLizable: " |
| + extension + " (" + extension.getClass().getName() + ")"); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| protected RenderingContext createRenderingContext() { |
| throw new IllegalStateException("Should never be called!"); |
| } |
| |
| private void addAttribute(AttributesImpl atts, |
| org.apache.xmlgraphics.util.QName attribute, String value) { |
| XMLUtil.addAttribute(atts, attribute, value); |
| } |
| |
| private void addAttribute(AttributesImpl atts, String localName, String value) { |
| XMLUtil.addAttribute(atts, localName, value); |
| } |
| |
| // ---=== IFDocumentNavigationHandler ===--- |
| |
| private Map incompleteActions = new java.util.HashMap(); |
| private List completeActions = new java.util.LinkedList(); |
| |
| private void noteAction(AbstractAction action) { |
| if (action == null) { |
| throw new NullPointerException("action must not be null"); |
| } |
| if (!action.isComplete()) { |
| assert action.hasID(); |
| incompleteActions.put(action.getID(), action); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void renderNamedDestination(NamedDestination destination) throws IFException { |
| noteAction(destination.getAction()); |
| |
| AttributesImpl atts = new AttributesImpl(); |
| atts.addAttribute(null, "name", "name", XMLConstants.CDATA, destination.getName()); |
| try { |
| handler.startElement(DocumentNavigationExtensionConstants.NAMED_DESTINATION, atts); |
| serializeXMLizable(destination.getAction()); |
| handler.endElement(DocumentNavigationExtensionConstants.NAMED_DESTINATION); |
| } catch (SAXException e) { |
| throw new IFException("SAX error serializing named destination", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void renderBookmarkTree(BookmarkTree tree) throws IFException { |
| AttributesImpl atts = new AttributesImpl(); |
| try { |
| handler.startElement(DocumentNavigationExtensionConstants.BOOKMARK_TREE, atts); |
| Iterator iter = tree.getBookmarks().iterator(); |
| while (iter.hasNext()) { |
| Bookmark b = (Bookmark)iter.next(); |
| serializeBookmark(b); |
| } |
| handler.endElement(DocumentNavigationExtensionConstants.BOOKMARK_TREE); |
| } catch (SAXException e) { |
| throw new IFException("SAX error serializing bookmark tree", e); |
| } |
| } |
| |
| private void serializeBookmark(Bookmark bookmark) throws SAXException, IFException { |
| noteAction(bookmark.getAction()); |
| |
| AttributesImpl atts = new AttributesImpl(); |
| atts.addAttribute(null, "title", "title", XMLUtil.CDATA, bookmark.getTitle()); |
| atts.addAttribute(null, "starting-state", "starting-state", |
| XMLUtil.CDATA, bookmark.isShown() ? "show" : "hide"); |
| handler.startElement(DocumentNavigationExtensionConstants.BOOKMARK, atts); |
| serializeXMLizable(bookmark.getAction()); |
| Iterator iter = bookmark.getChildBookmarks().iterator(); |
| while (iter.hasNext()) { |
| Bookmark b = (Bookmark)iter.next(); |
| serializeBookmark(b); |
| } |
| handler.endElement(DocumentNavigationExtensionConstants.BOOKMARK); |
| |
| } |
| |
| /** {@inheritDoc} */ |
| public void renderLink(Link link) throws IFException { |
| noteAction(link.getAction()); |
| |
| AttributesImpl atts = new AttributesImpl(); |
| atts.addAttribute(null, "rect", "rect", |
| XMLConstants.CDATA, IFUtil.toString(link.getTargetRect())); |
| try { |
| handler.startElement(DocumentNavigationExtensionConstants.LINK, atts); |
| serializeXMLizable(link.getAction()); |
| handler.endElement(DocumentNavigationExtensionConstants.LINK); |
| } catch (SAXException e) { |
| throw new IFException("SAX error serializing link", e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void addResolvedAction(AbstractAction action) throws IFException { |
| assert action.isComplete(); |
| assert action.hasID(); |
| AbstractAction noted = (AbstractAction)incompleteActions.remove(action.getID()); |
| if (noted != null) { |
| completeActions.add(action); |
| } else { |
| //ignore as it was already complete when it was first used. |
| } |
| } |
| |
| private void commitNavigation() throws IFException { |
| Iterator iter = this.completeActions.iterator(); |
| while (iter.hasNext()) { |
| AbstractAction action = (AbstractAction)iter.next(); |
| iter.remove(); |
| serializeXMLizable(action); |
| } |
| assert this.completeActions.size() == 0; |
| } |
| |
| private void finishDocumentNavigation() { |
| assert this.incompleteActions.size() == 0 : "Still holding incomplete actions!"; |
| } |
| |
| private void serializeXMLizable(XMLizable object) throws IFException { |
| try { |
| object.toSAX(handler); |
| } catch (SAXException e) { |
| throw new IFException("SAX error serializing object", e); |
| } |
| } |
| |
| } |