blob: 497e3c04786330d5cfbc4d35e6e16333a68b0b86 [file] [log] [blame]
/*
* 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.xml;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.apache.fop.area.BookmarkData;
import org.apache.fop.area.OffDocumentExtensionAttachment;
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.render.PrintRenderer;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.util.QName;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
/** Abstract xml renderer base class. */
public abstract class AbstractXMLRenderer extends PrintRenderer {
/** Main namespace in use. */
public static final String NS = "";
/** CDATA type */
public static final String CDATA = "CDATA";
/** An empty Attributes object used when no attributes are needed. */
public static final Attributes EMPTY_ATTS = new AttributesImpl();
/** AttributesImpl instance that can be used during XML generation. */
protected AttributesImpl atts = new AttributesImpl();
/** ContentHandler that the generated XML is written to */
protected ContentHandler handler;
/** The OutputStream to write the generated XML to. */
protected OutputStream out;
/** The renderer context. */
protected RendererContext context;
/** A list of ExtensionAttachements received through processOffDocumentItem() */
protected List extensionAttachments;
/**
* Handles SAXExceptions.
* @param saxe the SAXException to handle
*/
protected void handleSAXException(SAXException saxe) {
throw new RuntimeException(saxe.getMessage());
}
/**
* Handles page extension attachments
* @param page the page viewport
*/
protected void handlePageExtensionAttachments(PageViewport page) {
handleExtensionAttachments(page.getExtensionAttachments());
}
/**
* Writes a comment to the generated XML.
* @param comment the comment
*/
protected void comment(String comment) {
if (handler instanceof LexicalHandler) {
try {
((LexicalHandler) handler).comment(comment.toCharArray(), 0, comment.length());
} catch (SAXException saxe) {
handleSAXException(saxe);
}
}
}
/**
* Starts a new element (without attributes).
* @param tagName tag name of the element
*/
protected void startElement(String tagName) {
startElement(tagName, EMPTY_ATTS);
}
/**
* Starts a new element.
* @param tagName tag name of the element
* @param atts attributes to add
*/
protected void startElement(String tagName, Attributes atts) {
try {
handler.startElement(NS, tagName, tagName, atts);
} catch (SAXException saxe) {
handleSAXException(saxe);
}
}
/**
* Ends an element.
* @param tagName tag name of the element
*/
protected void endElement(String tagName) {
try {
handler.endElement(NS, tagName, tagName);
} catch (SAXException saxe) {
handleSAXException(saxe);
}
}
/**
* Sends plain text to the XML
* @param text the text
*/
protected void characters(String text) {
try {
char[] ca = text.toCharArray();
handler.characters(ca, 0, ca.length);
} catch (SAXException saxe) {
handleSAXException(saxe);
}
}
/**
* Adds a new attribute to the protected member variable "atts".
* @param name name of the attribute
* @param value value of the attribute
*/
protected void addAttribute(String name, String value) {
atts.addAttribute(NS, name, name, CDATA, value);
}
/**
* Adds a new attribute to the protected member variable "atts".
* @param name name of the attribute
* @param value value of the attribute
*/
protected void addAttribute(QName name, String value) {
atts.addAttribute(name.getNamespaceURI(), name.getLocalName(), name.getQName(),
CDATA, value);
}
/**
* Adds a new attribute to the protected member variable "atts".
* @param name name of the attribute
* @param value value of the attribute
*/
protected void addAttribute(String name, int value) {
addAttribute(name, Integer.toString(value));
}
private String createString(Rectangle2D rect) {
return "" + (int) rect.getX() + " " + (int) rect.getY() + " "
+ (int) rect.getWidth() + " " + (int) rect.getHeight();
}
/**
* Adds a new attribute to the protected member variable "atts".
* @param name name of the attribute
* @param rect a Rectangle2D to format and use as attribute value
*/
protected void addAttribute(String name, Rectangle2D rect) {
addAttribute(name, createString(rect));
}
/** {@inheritDoc} */
public void startRenderer(OutputStream outputStream)
throws IOException {
if (this.handler == null) {
SAXTransformerFactory factory
= (SAXTransformerFactory)SAXTransformerFactory.newInstance();
try {
TransformerHandler transformerHandler = factory.newTransformerHandler();
setContentHandler(transformerHandler);
StreamResult res = new StreamResult(outputStream);
transformerHandler.setResult(res);
} catch (TransformerConfigurationException tce) {
throw new RuntimeException(tce.getMessage());
}
this.out = outputStream;
}
try {
handler.startDocument();
} catch (SAXException saxe) {
handleSAXException(saxe);
}
}
/** {@inheritDoc} */
public void stopRenderer() throws IOException {
try {
handler.endDocument();
} catch (SAXException saxe) {
handleSAXException(saxe);
}
if (this.out != null) {
this.out.flush();
}
}
/** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem oDI) {
if (oDI instanceof BookmarkData) {
renderBookmarkTree((BookmarkData) oDI);
} else if (oDI instanceof OffDocumentExtensionAttachment) {
ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment();
if (extensionAttachments == null) {
extensionAttachments = new java.util.ArrayList();
}
extensionAttachments.add(attachment);
} else {
String warn = "Ignoring OffDocumentItem: " + oDI;
log.warn(warn);
}
}
/** Handle document extension attachments. */
protected void handleDocumentExtensionAttachments() {
if (extensionAttachments != null && extensionAttachments.size() > 0) {
handleExtensionAttachments(extensionAttachments);
extensionAttachments.clear();
}
}
/**
* Sets an outside TransformerHandler to use instead of the default one
* create in this class in startRenderer().
* @param handler Overriding TransformerHandler
*/
public void setContentHandler(ContentHandler handler) {
this.handler = handler;
}
/**
* Handles a list of extension attachments
* @param attachments a list of extension attachments
*/
protected abstract void handleExtensionAttachments(List attachments);
/**
* Renders a bookmark tree
* @param odi the bookmark data
*/
protected abstract void renderBookmarkTree(BookmarkData odi);
}