diff options
author | Jeremias Maerki <jeremias@apache.org> | 2006-01-19 09:46:44 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2006-01-19 09:46:44 +0000 |
commit | b9d21be592b59117d843b62b694a6d2ee87fb648 (patch) | |
tree | 3907bc9e4de41ff8adbbaf4a09e21026b7e74f2d | |
parent | 9904a3e4e8726a6e21ca4190b83a2f57349f9e8e (diff) | |
download | xmlgraphics-fop-b9d21be592b59117d843b62b694a6d2ee87fb648.tar.gz xmlgraphics-fop-b9d21be592b59117d843b62b694a6d2ee87fb648.zip |
New interface XMLizable (copied from Apache Excalibur) to mark classes that can serialize themselves to XML (SAX stream).
New interface ContentHandlerFactory (plus associated Factory with Service discovery) for sub-document parsing plug-ins. Used by the area tree but could be used independently.
ExtensionAttachments are now part of the area tree and are written by XMLRenderer and parsed by AreaTreeParser.
The PS Extensions are extended to support serialization to and deserialization from XML.
Added a test case that tests the PS Extension WRT the handling in the area tree XML.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@370452 13f79535-47bb-0310-9956-ffa450edef68
11 files changed, 564 insertions, 8 deletions
diff --git a/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory b/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory new file mode 100644 index 000000000..d7533c599 --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory @@ -0,0 +1 @@ +org.apache.fop.render.ps.extensions.PSExtensionHandlerFactory
\ No newline at end of file diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 32e2bce1e..ad1017505 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -51,11 +51,14 @@ import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.ElementMappingRegistry; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.image.FopImage; import org.apache.fop.image.ImageFactory; import org.apache.fop.traits.BorderProps; +import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.ContentHandlerFactoryRegistry; import org.apache.fop.util.DefaultErrorListener; import org.w3c.dom.DOMImplementation; @@ -182,6 +185,7 @@ public class AreaTreeParser { 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(); @@ -196,6 +200,7 @@ public class AreaTreeParser { ((ForeignObject)parent).setDocument(doc); //activate delegate for nested foreign document + domImplementation = null; //Not needed anymore now this.delegate = handler; delegateStack.push(qName); delegate.startDocument(); @@ -405,15 +410,31 @@ public class AreaTreeParser { setTraits(attributes, foreign); getCurrentViewport().setContent(foreign); areaStack.push(foreign); + } else if ("extension-attachments".equals(localName)) { + //TODO implement me } else { handled = false; } } else { - handled = false; + ContentHandlerFactory factory + = ContentHandlerFactoryRegistry.getInstance().getFactory(uri); + if (factory != null) { + delegate = factory.createContentHandler(); + delegateStack.push(qName); + delegate.startDocument(); + delegate.startElement(uri, localName, qName, attributes); + } else { + handled = false; + } } if (!handled) { - throw new SAXException("Unhandled element " + localName - + " in namespace: " + uri); + if (uri == null || uri.length() == 0) { + throw new SAXException("Unhandled element " + localName + + " in namespace: " + uri); + } else { + log.warn("Unhandled element " + localName + + " in namespace: " + uri); + } } } } @@ -438,6 +459,25 @@ public class AreaTreeParser { } } + /** + * 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 { + log.warn("Don't know how to handle externally generated object: " + obj); + } + } + /** @see org.xml.sax.helpers.DefaultHandler */ public void endElement(String uri, String localName, String qName) throws SAXException { if (delegate != null) { @@ -445,8 +485,11 @@ public class AreaTreeParser { delegateStack.pop(); if (delegateStack.size() == 0) { delegate.endDocument(); - delegate = null; - domImplementation = null; + 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)) { diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index b516b3446..fedc4284f 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -32,6 +32,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.pagination.SimplePageMaster; /** @@ -492,6 +493,17 @@ public class PageViewport implements Resolvable, Cloneable { return this.simplePageMasterName; } + /** + * Adds a new ExtensionAttachment instance to this page. + * @param attachment the ExtensionAttachment + */ + public void addExtensionAttachment(ExtensionAttachment attachment) { + if (this.extensionAttachments == null) { + this.extensionAttachments = new java.util.ArrayList(); + } + extensionAttachments.add(attachment); + } + /** @return the list of extension attachments for this page */ public List getExtensionAttachments() { return this.extensionAttachments; diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java new file mode 100644 index 000000000..e22951236 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java @@ -0,0 +1,88 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.area.AreaTreeParser; +import org.apache.fop.util.ContentHandlerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * ContentHandler (parser) for restoring PSExtension objects from XML. + */ +public class PSExtensionHandler extends DefaultHandler + implements ContentHandlerFactory.ObjectSource { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(PSExtensionHandler.class); + + private StringBuffer content = new StringBuffer(); + private Attributes lastAttributes; + + private PSSetupCode returnedObject; + + /** @see org.xml.sax.helpers.DefaultHandler */ + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + boolean handled = false; + if (PSSetupCode.CATEGORY.equals(uri)) { + lastAttributes = attributes; + handled = true; + if ("ps-setup-code".equals(localName)) { + //handled in endElement + } else { + handled = false; + } + } + if (!handled) { + if (PSSetupCode.CATEGORY.equals(uri)) { + throw new SAXException("Unhandled element " + localName + + " in namespace: " + uri); + } else { + log.warn("Unhandled element " + localName + + " in namespace: " + uri); + } + } + } + + /** @see org.xml.sax.helpers.DefaultHandler */ + public void endElement(String uri, String localName, String qName) throws SAXException { + if (PSSetupCode.CATEGORY.equals(uri)) { + if ("ps-setup-code".equals(localName)) { + String name = lastAttributes.getValue("name"); + this.returnedObject = new PSSetupCode(name, content.toString()); + } + } + content.setLength(0); //Reset text buffer (see characters()) + } + + /** @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) */ + public void characters(char[] ch, int start, int length) throws SAXException { + content.append(ch, start, length); + } + + /** @see org.apache.fop.area.AreaTreeParser.ObjectSource#getObject() */ + public Object getObject() { + return returnedObject; + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java new file mode 100644 index 000000000..e2b85adbf --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.fop.util.ContentHandlerFactory; +import org.xml.sax.ContentHandler; + +/** + * Factory for the ContentHandler that handles serialized PSSetupCode instances. + */ +public class PSExtensionHandlerFactory implements ContentHandlerFactory { + + private static final String[] NAMESPACES = new String[] {PSSetupCode.CATEGORY}; + + /** @see org.apache.fop.util.ContentHandlerFactory#getSupportedNamespaces() */ + public String[] getSupportedNamespaces() { + return NAMESPACES; + } + + /** @see org.apache.fop.util.ContentHandlerFactory#createContentHandler() */ + public ContentHandler createContentHandler() { + return new PSExtensionHandler(); + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java index 846946f99..49cb22979 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 The Apache Software Foundation. + * Copyright 2005-2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,11 +21,15 @@ package org.apache.fop.render.ps.extensions; import java.io.Serializable; import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.util.XMLizable; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; /** * This is the pass-through value object for the PostScript extension. */ -public class PSSetupCode implements ExtensionAttachment, Serializable { +public class PSSetupCode implements ExtensionAttachment, Serializable, XMLizable { /** The category URI for this extension attachment. */ public static final String CATEGORY = "apache:fop:extensions:postscript"; @@ -81,9 +85,26 @@ public class PSSetupCode implements ExtensionAttachment, Serializable { return CATEGORY; } - /** @see java.lang.Object#toString() */ public String toString() { return "PSSetupCode(name=" + getName() + ")"; } + + private static final String ATT_NAME = "name"; + private static final String ELEMENT = "ps-setup-code"; + + /** @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + if (name != null && name.length() > 0) { + atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); + } + handler.startElement(CATEGORY, ELEMENT, ELEMENT, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, ELEMENT, ELEMENT); + } + } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 1b9afc566..982d138bc 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -43,6 +43,7 @@ import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.XMLHandler; +import org.apache.fop.util.XMLizable; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.MimeConstants; @@ -56,6 +57,8 @@ import org.apache.fop.area.NormalFlow; import org.apache.fop.area.Footnote; import org.apache.fop.area.LineArea; import org.apache.fop.area.MainReference; +import org.apache.fop.area.OffDocumentExtensionAttachment; +import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; @@ -75,6 +78,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; @@ -114,6 +118,9 @@ public class XMLRenderer extends PrintRenderer { /** The OutputStream to write the generated XML to. */ protected OutputStream out; + + /** A list of ExtensionAttachements received through processOffDocumentItem() */ + protected List extensionAttachments; /** * Creates a new XML renderer. @@ -357,6 +364,28 @@ public class XMLRenderer extends PrintRenderer { + (int) rect.getWidth() + " " + (int) rect.getHeight(); } + private void handleDocumentExtensionAttachments() { + if (extensionAttachments != null && extensionAttachments.size() > 0) { + handleExtensionAttachments(extensionAttachments); + extensionAttachments.clear(); + } + } + + /** @see org.apache.fop.render.AbstractRenderer#processOffDocumentItem() */ + public void processOffDocumentItem(OffDocumentItem oDI) { + 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; + comment("WARNING: " + warn); + log.warn(warn); + } + } + /** * @see org.apache.fop.render.Renderer#startRenderer(OutputStream) */ @@ -416,15 +445,45 @@ public class XMLRenderer extends PrintRenderer { addAttribute("nr", page.getPageNumberString()); startElement("pageViewport", atts); startElement("page"); + + handlePageExtensionAttachments(page); super.renderPage(page); + endElement("page"); endElement("pageViewport"); } + private void handleExtensionAttachments(List attachments) { + if (attachments != null && attachments.size() > 0) { + startElement("extension-attachments"); + Iterator i = attachments.iterator(); + while (i.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment)i.next(); + if (attachment instanceof XMLizable) { + try { + ((XMLizable)attachment).toSAX(this.handler); + } catch (SAXException e) { + log.error("Error while serializing Extension Attachment", e); + } + } else { + String warn = "Ignoring non-XMLizable ExtensionAttachment: " + attachment; + comment("WARNING: " + warn); + log.warn(warn); + } + } + endElement("extension-attachments"); + } + } + + private void handlePageExtensionAttachments(PageViewport page) { + handleExtensionAttachments(page.getExtensionAttachments()); + } + /** * @see org.apache.fop.render.Renderer#startPageSequence(LineArea) */ public void startPageSequence(LineArea seqTitle) { + handleDocumentExtensionAttachments(); if (startedSequence) { endElement("pageSequence"); } diff --git a/src/java/org/apache/fop/util/ContentHandlerFactory.java b/src/java/org/apache/fop/util/ContentHandlerFactory.java new file mode 100644 index 000000000..da615cc54 --- /dev/null +++ b/src/java/org/apache/fop/util/ContentHandlerFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.util; + +import org.xml.sax.ContentHandler; + +/** + * Factory interface implemented by classes that can instantiate ContentHandler subclasses which + * parse a SAX stream into Java objects. + */ +public interface ContentHandlerFactory { + + /** + * @return an array of supported namespaces. + */ + String[] getSupportedNamespaces(); + + /** + * @return a new ContentHandler to handle a SAX stream + */ + ContentHandler createContentHandler(); + + /** + * Interface that ContentHandler implementations that parse Java objects from XML can implement + * to return these objects. + */ + public interface ObjectSource { + + /** + * @return the object parsed from the SAX stream (call valid after parsing) + */ + Object getObject(); + + } + +} diff --git a/src/java/org/apache/fop/util/ContentHandlerFactoryRegistry.java b/src/java/org/apache/fop/util/ContentHandlerFactoryRegistry.java new file mode 100644 index 000000000..68e215b45 --- /dev/null +++ b/src/java/org/apache/fop/util/ContentHandlerFactoryRegistry.java @@ -0,0 +1,129 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.util; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.util.Service; + +/** + * This class holds references to various XML handlers used by FOP. It also + * supports automatic discovery of additional XML handlers available through + * the class path. + */ +public class ContentHandlerFactoryRegistry { + + /** the logger */ + private static Log log = LogFactory.getLog(ContentHandlerFactoryRegistry.class); + + private static ContentHandlerFactoryRegistry instance; + + /** Map from namespace URIs to ContentHandlerFactories */ + private Map factories = new java.util.HashMap(); + + /** + * @return a singleton instance of the ContentHandlerFactoryRegistry. + */ + public static ContentHandlerFactoryRegistry getInstance() { + if (instance == null) { + instance = new ContentHandlerFactoryRegistry(); + } + return instance; + } + + /** + * Default constructor. + */ + public ContentHandlerFactoryRegistry() { + discover(); + } + + /** + * Add an XML handler. The handler itself is inspected to find out what it supports. + * @param classname the fully qualified class name + */ + public void addContentHandlerFactory(String classname) { + try { + ContentHandlerFactory factory + = (ContentHandlerFactory)Class.forName(classname).newInstance(); + addContentHandlerFactory(factory); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + + classname); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Could not instantiate " + + classname); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Could not access " + + classname); + } catch (ClassCastException e) { + throw new IllegalArgumentException(classname + + " is not an " + + ContentHandlerFactory.class.getName()); + } + } + + /** + * Add an ContentHandlerFactory. The instance is inspected to find out what it supports. + * @param factory the ContentHandlerFactory instance + */ + public void addContentHandlerFactory(ContentHandlerFactory factory) { + String[] ns = factory.getSupportedNamespaces(); + for (int i = 0; i < ns.length; i++) { + factories.put(ns[i], factory); + } + } + + /** + * Retrieves a ContentHandlerFactory instance of a given namespace URI. + * @param namespaceURI the namespace to be handled. + * @return the ContentHandlerFactory or null, if no suitable instance is available. + */ + public ContentHandlerFactory getFactory(String namespaceURI) { + ContentHandlerFactory factory = (ContentHandlerFactory)factories.get(namespaceURI); + return factory; + } + + /** + * Discovers ContentHandlerFactory implementations through the classpath and dynamically + * registers them. + */ + private void discover() { + // add mappings from available services + Iterator providers = Service.providers(ContentHandlerFactory.class); + if (providers != null) { + while (providers.hasNext()) { + String str = (String)providers.next(); + try { + if (log.isDebugEnabled()) { + log.debug("Dynamically adding ContentHandlerFactory: " + str); + } + addContentHandlerFactory(str); + } catch (IllegalArgumentException e) { + log.error("Error while adding ContentHandlerFactory", e); + } + + } + } + } +} diff --git a/src/java/org/apache/fop/util/XMLizable.java b/src/java/org/apache/fop/util/XMLizable.java new file mode 100644 index 000000000..ea02963ef --- /dev/null +++ b/src/java/org/apache/fop/util/XMLizable.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2004 The Apache Software Foundation. + * + * Licensed 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.util; + +/* + * Copied from Apache Excalibur: + * https://svn.apache.org/repos/asf/excalibur/trunk/components/xmlutil/ + * src/java/org/apache/excalibur/xml/sax/XMLizable.java + */ + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * This interface can be implemented by classes willing to provide an XML representation + * of their current state as SAX events. + */ +public interface XMLizable { + + /** + * Generates SAX events representing the object's state. + * @param handler ContentHandler instance to send the SAX events to + * @throws SAXException if there's a problem generating the SAX events + */ + void toSAX(ContentHandler handler) throws SAXException; + +} diff --git a/test/layoutengine/standard-testcases/ps-extension_1.xml b/test/layoutengine/standard-testcases/ps-extension_1.xml new file mode 100644 index 000000000..beadbef00 --- /dev/null +++ b/test/layoutengine/standard-testcases/ps-extension_1.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2006 The Apache Software Foundation + + Licensed 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$ --> +<testcase> + <info> + <p> + This test checks the PostScript extension for custom setup code. The extension attachments need to show + up in the area tree XML so the AreaTreeParser can fully restore the area tree. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ps="http://xmlgraphics.apache.org/fop/postscript"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in"> + <fo:region-body/> + <ps:ps-page-setup-code name="media-dict">%FOPTestPSPageSetupCode: MediaDict!</ps:ps-page-setup-code> + <ps:ps-page-setup-code name="bla">%FOPTestPSPageSetupCode: Blah blah!</ps:ps-page-setup-code> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:declarations> + <ps:ps-setup-code>%FOPTestPSSetupCode: General setup code here!</ps:ps-setup-code> + <ps:ps-setup-code name="multi-line"> +%FOPTestPSSetupCode: Line 1 +%FOPTestPSSetupCode: Line 2 + </ps:ps-setup-code> + </fo:declarations> + <fo:page-sequence master-reference="normal"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Text on page <fo:page-number/>.</fo:block> + <fo:block break-before="page">Text on page <fo:page-number/>.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="2" xpath="count(/areaTree/extension-attachments/child::*)"/> + <eval expected="%FOPTestPSSetupCode: General setup code here!" xpath="/areaTree/extension-attachments/child::*[1]"/> + <true xpath="contains(/areaTree/extension-attachments/child::*[2], '%FOPTestPSSetupCode: Line 1')"/> + <eval expected="multi-line" xpath="/areaTree/extension-attachments/child::*[2]/@name"/> + + <eval expected="2" xpath="count(/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*)"/> + <eval expected="media-dict" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[1]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: MediaDict!" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[1]"/> + <eval expected="bla" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[2]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: Blah blah!" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[2]"/> + + <eval expected="2" xpath="count(/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*)"/> + <eval expected="media-dict" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[1]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: MediaDict!" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[1]"/> + <eval expected="bla" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[2]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: Blah blah!" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[2]"/> + </checks> +</testcase> |