2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 package org.apache.fop.render.intermediate.extensions;
22 import java.awt.Point;
23 import java.util.Stack;
25 import org.xml.sax.Attributes;
26 import org.xml.sax.ContentHandler;
27 import org.xml.sax.SAXException;
28 import org.xml.sax.helpers.DefaultHandler;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
33 import org.apache.fop.render.ps.extensions.PSExtensionAttachment;
34 import org.apache.fop.util.ContentHandlerFactory;
35 import org.apache.fop.util.XMLUtil;
38 * Factory for the ContentHandler that handles the IF document navigation namespace.
40 public class DocumentNavigationExtensionHandlerFactory
41 implements ContentHandlerFactory, DocumentNavigationExtensionConstants {
43 /** Logger instance */
44 protected static Log log = LogFactory.getLog(DocumentNavigationExtensionHandlerFactory.class);
47 public String[] getSupportedNamespaces() {
48 return new String[] {NAMESPACE};
52 public ContentHandler createContentHandler() {
56 private static class Handler extends DefaultHandler
57 implements ContentHandlerFactory.ObjectSource {
59 private StringBuffer content = new StringBuffer();
60 private Stack objectStack = new Stack();
62 private Object objectBuilt;
63 private ObjectBuiltListener listener;
66 public void startElement(String uri, String localName, String qName, Attributes attributes)
68 boolean handled = false;
69 if (NAMESPACE.equals(uri)) {
70 if (BOOKMARK_TREE.getLocalName().equals(localName)) {
71 if (!objectStack.isEmpty()) {
72 throw new SAXException(localName + " must be the root element!");
74 BookmarkTree bookmarkTree = new BookmarkTree();
75 objectStack.push(bookmarkTree);
76 } else if (BOOKMARK.getLocalName().equals(localName)) {
77 String title = attributes.getValue("title");
78 String s = attributes.getValue("starting-state");
79 boolean show = !"hide".equals(s);
80 Bookmark b = new Bookmark(title, show, null);
81 Object o = objectStack.peek();
82 if (o instanceof AbstractAction) {
83 AbstractAction action = (AbstractAction)objectStack.pop();
84 o = objectStack.peek();
85 ((Bookmark)o).setAction(action);
87 if (o instanceof BookmarkTree) {
88 ((BookmarkTree)o).addBookmark(b);
90 ((Bookmark)o).addChildBookmark(b);
93 } else if (NAMED_DESTINATION.getLocalName().equals(localName)) {
94 if (!objectStack.isEmpty()) {
95 throw new SAXException(localName + " must be the root element!");
97 String name = attributes.getValue("name");
98 NamedDestination dest = new NamedDestination(name, null);
99 objectStack.push(dest);
100 } else if (GOTO_XY.getLocalName().equals(localName)) {
101 String id = attributes.getValue("id");
102 int pageIndex = XMLUtil.getAttributeAsInt(attributes, "page-index");
103 int x = XMLUtil.getAttributeAsInt(attributes, "x");
104 int y = XMLUtil.getAttributeAsInt(attributes, "y");
105 GoToXYAction action = new GoToXYAction(id, pageIndex, new Point(x, y));
106 objectStack.push(action);
107 } else if (GOTO_URI.getLocalName().equals(localName)) {
108 String gotoURI = attributes.getValue("uri");
109 String showDestination = attributes.getValue("show-destination");
110 boolean newWindow = "new".equals(showDestination);
111 URIAction action = new URIAction(gotoURI, newWindow);
112 objectStack.push(action);
114 throw new SAXException(
115 "Invalid element " + localName + " in namespace: " + uri);
120 if (PSExtensionAttachment.CATEGORY.equals(uri)) {
121 throw new SAXException("Unhandled element " + localName + " in namespace: "
124 log.warn("Unhandled element " + localName + " in namespace: " + uri);
130 public void endElement(String uri, String localName, String qName) throws SAXException {
131 if (NAMESPACE.equals(uri)) {
132 if (BOOKMARK_TREE.getLocalName().equals(localName)) {
134 } else if (BOOKMARK.getLocalName().equals(localName)) {
135 if (objectStack.peek() instanceof AbstractAction) {
136 AbstractAction action = (AbstractAction)objectStack.pop();
137 Bookmark b = (Bookmark)objectStack.pop();
142 } else if (NAMED_DESTINATION.getLocalName().equals(localName)) {
143 AbstractAction action = (AbstractAction)objectStack.pop();
144 NamedDestination dest = (NamedDestination)objectStack.peek();
145 dest.setAction(action);
148 content.setLength(0); // Reset text buffer (see characters())
152 public void characters(char[] ch, int start, int length) throws SAXException {
153 content.append(ch, start, length);
157 public void endDocument() throws SAXException {
158 this.objectBuilt = objectStack.pop();
159 assert objectStack.isEmpty();
160 if (listener != null) {
161 listener.notifyObjectBuilt(this.objectBuilt);
166 public Object getObject() {
171 public void setObjectBuiltListener(ObjectBuiltListener listener) {
172 this.listener = listener;