| /* |
| * 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.extensions; |
| |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.util.Stack; |
| |
| import org.xml.sax.Attributes; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import org.apache.fop.render.intermediate.IFDocumentNavigationHandler; |
| import org.apache.fop.render.intermediate.IFException; |
| import org.apache.fop.util.XMLUtil; |
| |
| /** |
| * ContentHandler that handles the IF document navigation namespace. |
| */ |
| public class DocumentNavigationHandler extends DefaultHandler |
| implements DocumentNavigationExtensionConstants { |
| |
| /** Logger instance */ |
| protected static Log log = LogFactory.getLog(DocumentNavigationHandler.class); |
| |
| private StringBuffer content = new StringBuffer(); |
| private Stack objectStack = new Stack(); |
| |
| private IFDocumentNavigationHandler navHandler; |
| |
| private String structurePointer; |
| |
| /** |
| * Main constructor. |
| * @param navHandler the navigation handler that will receive the events |
| */ |
| public DocumentNavigationHandler(IFDocumentNavigationHandler navHandler) { |
| this.navHandler = navHandler; |
| } |
| |
| /** {@inheritDoc} */ |
| public void startElement(String uri, String localName, String qName, Attributes attributes) |
| throws SAXException { |
| boolean handled = false; |
| if (NAMESPACE.equals(uri)) { |
| if (BOOKMARK_TREE.getLocalName().equals(localName)) { |
| if (!objectStack.isEmpty()) { |
| throw new SAXException(localName + " must be the root element!"); |
| } |
| BookmarkTree bookmarkTree = new BookmarkTree(); |
| objectStack.push(bookmarkTree); |
| } else if (BOOKMARK.getLocalName().equals(localName)) { |
| String title = attributes.getValue("title"); |
| String s = attributes.getValue("starting-state"); |
| boolean show = !"hide".equals(s); |
| Bookmark b = new Bookmark(title, show, null); |
| Object o = objectStack.peek(); |
| if (o instanceof AbstractAction) { |
| AbstractAction action = (AbstractAction)objectStack.pop(); |
| o = objectStack.peek(); |
| ((Bookmark)o).setAction(action); |
| } |
| if (o instanceof BookmarkTree) { |
| ((BookmarkTree)o).addBookmark(b); |
| } else { |
| ((Bookmark)o).addChildBookmark(b); |
| } |
| objectStack.push(b); |
| } else if (NAMED_DESTINATION.getLocalName().equals(localName)) { |
| if (!objectStack.isEmpty()) { |
| throw new SAXException(localName + " must be the root element!"); |
| } |
| String name = attributes.getValue("name"); |
| NamedDestination dest = new NamedDestination(name, null); |
| objectStack.push(dest); |
| } else if (LINK.getLocalName().equals(localName)) { |
| if (!objectStack.isEmpty()) { |
| throw new SAXException(localName + " must be the root element!"); |
| } |
| Rectangle targetRect = XMLUtil.getAttributeAsRectangle(attributes, "rect"); |
| structurePointer = attributes.getValue("ptr"); |
| Link link = new Link(null, targetRect); |
| objectStack.push(link); |
| } else if (GOTO_XY.getLocalName().equals(localName)) { |
| String idref = attributes.getValue("idref"); |
| GoToXYAction action; |
| if (idref != null) { |
| action = new GoToXYAction(idref); |
| } else { |
| String id = attributes.getValue("id"); |
| int pageIndex = XMLUtil.getAttributeAsInt(attributes, "page-index"); |
| final Point location; |
| if (pageIndex < 0) { |
| location = null; |
| } else { |
| final int x = XMLUtil |
| .getAttributeAsInt(attributes, "x"); |
| final int y = XMLUtil |
| .getAttributeAsInt(attributes, "y"); |
| location = new Point(x, y); |
| } |
| action = new GoToXYAction(id, pageIndex, location); |
| } |
| if (structurePointer != null) { |
| action.setStructurePointer(structurePointer); |
| } |
| objectStack.push(action); |
| } else if (GOTO_URI.getLocalName().equals(localName)) { |
| String id = attributes.getValue("id"); |
| String gotoURI = attributes.getValue("uri"); |
| String showDestination = attributes.getValue("show-destination"); |
| boolean newWindow = "new".equals(showDestination); |
| URIAction action = new URIAction(gotoURI, newWindow); |
| if (id != null) { |
| action.setID(id); |
| } |
| if (structurePointer != null) { |
| action.setStructurePointer(structurePointer); |
| } |
| objectStack.push(action); |
| } else { |
| throw new SAXException( |
| "Invalid element '" + localName + "' in namespace: " + uri); |
| } |
| handled = true; |
| } |
| if (!handled) { |
| if (NAMESPACE.equals(uri)) { |
| throw new SAXException("Unhandled element '" + localName + "' in namespace: " |
| + uri); |
| } else { |
| log.warn("Unhandled element '" + localName + "' in namespace: " + uri); |
| } |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void endElement(String uri, String localName, String qName) throws SAXException { |
| if (NAMESPACE.equals(uri)) { |
| try { |
| if (BOOKMARK_TREE.getLocalName().equals(localName)) { |
| BookmarkTree tree = (BookmarkTree)objectStack.pop(); |
| if (hasNavigation()) { |
| this.navHandler.renderBookmarkTree(tree); |
| } |
| } else if (BOOKMARK.getLocalName().equals(localName)) { |
| if (objectStack.peek() instanceof AbstractAction) { |
| AbstractAction action = (AbstractAction)objectStack.pop(); |
| Bookmark b = (Bookmark)objectStack.pop(); |
| b.setAction(action); |
| } else { |
| objectStack.pop(); |
| } |
| } else if (NAMED_DESTINATION.getLocalName().equals(localName)) { |
| AbstractAction action = (AbstractAction)objectStack.pop(); |
| NamedDestination dest = (NamedDestination)objectStack.pop(); |
| dest.setAction(action); |
| if (hasNavigation()) { |
| this.navHandler.renderNamedDestination(dest); |
| } |
| } else if (LINK.getLocalName().equals(localName)) { |
| AbstractAction action = (AbstractAction)objectStack.pop(); |
| Link link = (Link)objectStack.pop(); |
| link.setAction(action); |
| if (hasNavigation()) { |
| this.navHandler.renderLink(link); |
| } |
| } else if (localName.startsWith("goto-")) { |
| if (objectStack.size() == 1) { |
| //Stand-alone action |
| AbstractAction action = (AbstractAction)objectStack.pop(); |
| if (hasNavigation()) { |
| this.navHandler.addResolvedAction(action); |
| } |
| } |
| } |
| } catch (IFException ife) { |
| throw new SAXException(ife); |
| } |
| } |
| content.setLength(0); // Reset text buffer (see characters()) |
| } |
| |
| private boolean hasNavigation() { |
| return this.navHandler != null; |
| } |
| |
| /** {@inheritDoc} */ |
| public void characters(char[] ch, int start, int length) throws SAXException { |
| content.append(ch, start, length); |
| } |
| |
| /** {@inheritDoc} */ |
| public void endDocument() throws SAXException { |
| assert objectStack.isEmpty(); |
| } |
| |
| } |