diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2013-04-08 11:51:52 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2013-04-08 11:51:52 +0000 |
commit | ce39d4c2fb899be5d8d705fe72e0153fde21e592 (patch) | |
tree | c16721a9a7f5313aaadafb0529370d278067eaa4 /src/java/org/apache/fop/accessibility | |
parent | e3c9f13598dc3bbcbe1ea34920972910625567c0 (diff) | |
download | xmlgraphics-fop-ce39d4c2fb899be5d8d705fe72e0153fde21e592.tar.gz xmlgraphics-fop-ce39d4c2fb899be5d8d705fe72e0153fde21e592.zip |
FOP #2234: NPE when rendering a document with markers and accessibility is enabled
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1465599 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop/accessibility')
5 files changed, 170 insertions, 21 deletions
diff --git a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java index c63c721e5..be1177635 100644 --- a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java +++ b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java @@ -42,7 +42,7 @@ public final class DummyStructureTreeEventHandler implements StructureTreeEventH } /** {@inheritDoc} */ - public StructureTreeElement startNode(String name, Attributes attributes) { + public StructureTreeElement startNode(String name, Attributes attributes, StructureTreeElement parent) { return null; } @@ -51,12 +51,12 @@ public final class DummyStructureTreeEventHandler implements StructureTreeEventH } /** {@inheritDoc} */ - public StructureTreeElement startImageNode(String name, Attributes attributes) { + public StructureTreeElement startImageNode(String name, Attributes attributes, StructureTreeElement parent) { return null; } /** {@inheritDoc} */ - public StructureTreeElement startReferencedNode(String name, Attributes attributes) { + public StructureTreeElement startReferencedNode(String name, Attributes attributes, StructureTreeElement parent) { return null; } diff --git a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java index 7a375ef20..0b8073e57 100644 --- a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java +++ b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java @@ -87,7 +87,7 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa } /** {@inheritDoc} */ - public StructureTreeElement startNode(String name, Attributes attributes) { + public StructureTreeElement startNode(String name, Attributes attributes, StructureTreeElement parent) { try { if (name.equals("#PCDATA")) { name = "marked-content"; @@ -115,13 +115,13 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa } /** {@inheritDoc} */ - public StructureTreeElement startImageNode(String name, Attributes attributes) { - return startNode(name, attributes); + public StructureTreeElement startImageNode(String name, Attributes attributes, StructureTreeElement parent) { + return startNode(name, attributes, null); } /** {@inheritDoc} */ - public StructureTreeElement startReferencedNode(String name, Attributes attributes) { - return startNode(name, attributes); + public StructureTreeElement startReferencedNode(String name, Attributes attributes, StructureTreeElement parent) { + return startNode(name, attributes, null); } } diff --git a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java index 46b724626..53c27130c 100644 --- a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java +++ b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java @@ -43,9 +43,11 @@ public interface StructureTreeEventHandler { * * @param name the name of the structure tree node * @param attributes the node properties + * @param parent the parent of the node. May be null, in which case the parent node is + * the node corresponding to the previous call to this method * @return the corresponding structure tree element */ - StructureTreeElement startNode(String name, Attributes attributes); + StructureTreeElement startNode(String name, Attributes attributes, StructureTreeElement parent); /** * Ends a structure tree node. @@ -59,9 +61,11 @@ public interface StructureTreeEventHandler { * * @param name the name of the structure tree node * @param attributes the node properties + * @param parent the parent of the node. May be null, in which case the parent node is + * the node corresponding to the previous call to this method * @return the corresponding structure tree element */ - StructureTreeElement startImageNode(String name, Attributes attributes); + StructureTreeElement startImageNode(String name, Attributes attributes, StructureTreeElement parent); /** * Starts a node that can be referenced by other nodes. This is usually a @@ -69,9 +73,11 @@ public interface StructureTreeEventHandler { * * @param name the name of the structure tree node * @param attributes the node properties + * @param parent the parent of the node. May be null, in which case the parent node is + * the node corresponding to the previous call to this method * @return the corresponding structure tree element */ - StructureTreeElement startReferencedNode(String name, Attributes attributes); + StructureTreeElement startReferencedNode(String name, Attributes attributes, StructureTreeElement parent); /** * Ends a page sequence structure tree node. diff --git a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java index aaf112cb5..4614a7005 100644 --- a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java +++ b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java @@ -19,6 +19,8 @@ package org.apache.fop.accessibility.fo; +import java.util.HashMap; +import java.util.Map; import java.util.Stack; import org.xml.sax.SAXException; @@ -29,6 +31,7 @@ import org.apache.fop.fo.DelegatingFOEventHandler; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FOText; import org.apache.fop.fo.extensions.ExternalDocument; +import org.apache.fop.fo.flow.AbstractRetrieveMarker; import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.BlockContainer; @@ -46,6 +49,8 @@ import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.fo.flow.PageNumberCitationLast; +import org.apache.fop.fo.flow.RetrieveMarker; +import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; @@ -70,14 +75,30 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { /** The top of the {@link converters} stack. */ private FOEventHandler converter; - private final Stack<FOEventHandler> converters = new Stack<FOEventHandler>(); + private Stack<FOEventHandler> converters = new Stack<FOEventHandler>(); - private final FOEventHandler structureTreeEventTrigger; + private final StructureTreeEventTrigger structureTreeEventTrigger; /** The descendants of some elements like fo:leader must be ignored. */ private final FOEventHandler eventSwallower = new FOEventHandler() { }; + private final Map<AbstractRetrieveMarker, State> states = new HashMap<AbstractRetrieveMarker, State>(); + + private static final class State { + + private final FOEventHandler converter; + + private final Stack<FOEventHandler> converters; + + @SuppressWarnings("unchecked") + State(FO2StructureTreeConverter o) { + this.converter = o.converter; + this.converters = (Stack<FOEventHandler>) o.converters.clone(); + } + + } + /** * Creates a new instance. * @@ -459,6 +480,57 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { } @Override + public void startRetrieveMarker(RetrieveMarker retrieveMarker) { + converter.startRetrieveMarker(retrieveMarker); + saveState(retrieveMarker); + super.startRetrieveMarker(retrieveMarker); + } + + private void saveState(AbstractRetrieveMarker retrieveMarker) { + states.put(retrieveMarker, new State(this)); + } + + @Override + public void endRetrieveMarker(RetrieveMarker retrieveMarker) { + converter.endRetrieveMarker(retrieveMarker); + super.endRetrieveMarker(retrieveMarker); + } + + @Override + public void restoreState(RetrieveMarker retrieveMarker) { + restoreRetrieveMarkerState(retrieveMarker); + converter.restoreState(retrieveMarker); + super.restoreState(retrieveMarker); + } + + @SuppressWarnings("unchecked") + private void restoreRetrieveMarkerState(AbstractRetrieveMarker retrieveMarker) { + State state = states.get(retrieveMarker); + this.converter = state.converter; + this.converters = (Stack<FOEventHandler>) state.converters.clone(); + } + + @Override + public void startRetrieveTableMarker(RetrieveTableMarker retrieveTableMarker) { + converter.startRetrieveTableMarker(retrieveTableMarker); + saveState(retrieveTableMarker); + super.startRetrieveTableMarker(retrieveTableMarker); + } + + @Override + public void endRetrieveTableMarker(RetrieveTableMarker retrieveTableMarker) { + converter.endRetrieveTableMarker(retrieveTableMarker); + super.endRetrieveTableMarker(retrieveTableMarker); + } + + @Override + public void restoreState(RetrieveTableMarker retrieveTableMarker) { + restoreRetrieveMarkerState(retrieveTableMarker); + converter.restoreState(retrieveTableMarker); + super.restoreState(retrieveTableMarker); + } + + @Override public void character(Character c) { converter.character(c); super.character(c); diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java index 6a763a6f6..1a59bebfb 100644 --- a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java +++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java @@ -19,7 +19,9 @@ package org.apache.fop.accessibility.fo; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.Stack; import javax.xml.XMLConstants; @@ -34,6 +36,7 @@ import org.apache.fop.fo.FOText; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.extensions.InternalElementMapping; import org.apache.fop.fo.flow.AbstractGraphics; +import org.apache.fop.fo.flow.AbstractRetrieveMarker; import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.BlockContainer; @@ -50,6 +53,8 @@ import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.fo.flow.PageNumberCitationLast; +import org.apache.fop.fo.flow.RetrieveMarker; +import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; @@ -76,11 +81,30 @@ class StructureTreeEventTrigger extends FOEventHandler { private LayoutMasterSet layoutMasterSet; - private final Stack<Table> tables = new Stack<Table>(); + private Stack<Table> tables = new Stack<Table>(); - private final Stack<Boolean> inTableHeader = new Stack<Boolean>(); + private Stack<Boolean> inTableHeader = new Stack<Boolean>(); - private final Stack<Locale> locales = new Stack<Locale>(); + private Stack<Locale> locales = new Stack<Locale>(); + + private final Map<AbstractRetrieveMarker, State> states = new HashMap<AbstractRetrieveMarker, State>(); + + private static final class State { + + private final Stack<Table> tables; + + private final Stack<Boolean> inTableHeader; + + private final Stack<Locale> locales; + + @SuppressWarnings("unchecked") + State(StructureTreeEventTrigger o) { + this.tables = (Stack<Table>) o.tables.clone(); + this.inTableHeader = (Stack<Boolean>) o.inTableHeader.clone(); + this.locales = (Stack<Locale>) o.locales.clone(); + } + + } public StructureTreeEventTrigger(StructureTreeEventHandler structureTreeEventHandler) { this.structureTreeEventHandler = structureTreeEventHandler; @@ -415,6 +439,50 @@ class StructureTreeEventTrigger extends FOEventHandler { } @Override + public void startRetrieveMarker(RetrieveMarker retrieveMarker) { + startElementWithID(retrieveMarker); + saveState(retrieveMarker); + } + + void saveState(AbstractRetrieveMarker retrieveMarker) { + states.put(retrieveMarker, new State(this)); + } + + @Override + public void endRetrieveMarker(RetrieveMarker retrieveMarker) { + endElement(retrieveMarker); + } + + @Override + public void restoreState(RetrieveMarker retrieveMarker) { + restoreRetrieveMarkerState(retrieveMarker); + } + + @SuppressWarnings("unchecked") + private void restoreRetrieveMarkerState(AbstractRetrieveMarker retrieveMarker) { + State state = states.get(retrieveMarker); + tables = (Stack<Table>) state.tables.clone(); + inTableHeader = (Stack<Boolean>) state.inTableHeader.clone(); + locales = (Stack<Locale>) state.locales.clone(); + } + + @Override + public void startRetrieveTableMarker(RetrieveTableMarker retrieveTableMarker) { + startElementWithID(retrieveTableMarker); + saveState(retrieveTableMarker); + } + + @Override + public void endRetrieveTableMarker(RetrieveTableMarker retrieveTableMarker) { + endElement(retrieveTableMarker); + } + + @Override + public void restoreState(RetrieveTableMarker retrieveTableMarker) { + restoreRetrieveMarkerState(retrieveTableMarker); + } + + @Override public void character(Character c) { AttributesImpl attributes = createLangAttribute(c.getCommonHyphenation()); startElementWithID(c, attributes); @@ -429,8 +497,8 @@ class StructureTreeEventTrigger extends FOEventHandler { } - private void startElement(FONode node) { - startElement(node, new AttributesImpl()); + private StructureTreeElement startElement(FONode node) { + return startElement(node, new AttributesImpl()); } private void startElementWithID(FONode node) { @@ -443,7 +511,8 @@ class StructureTreeEventTrigger extends FOEventHandler { addRole((CommonAccessibilityHolder) node, attributes); } node.setStructureTreeElement( - structureTreeEventHandler.startReferencedNode(localName, attributes)); + structureTreeEventHandler.startReferencedNode(localName, attributes, + node.getParent().getStructureTreeElement())); } private void startElementWithIDAndAltText(AbstractGraphics node) { @@ -453,7 +522,8 @@ class StructureTreeEventTrigger extends FOEventHandler { addAttribute(attributes, ExtensionElementMapping.URI, "alt-text", ExtensionElementMapping.STANDARD_PREFIX, node.getAltText()); node.setStructureTreeElement( - structureTreeEventHandler.startImageNode(localName, attributes)); + structureTreeEventHandler.startImageNode(localName, attributes, + node.getParent().getStructureTreeElement())); } private StructureTreeElement startElement(FONode node, AttributesImpl attributes) { @@ -461,7 +531,8 @@ class StructureTreeEventTrigger extends FOEventHandler { if (node instanceof CommonAccessibilityHolder) { addRole((CommonAccessibilityHolder) node, attributes); } - return structureTreeEventHandler.startNode(localName, attributes); + return structureTreeEventHandler.startNode(localName, attributes, + node.getParent().getStructureTreeElement()); } private void addNoNamespaceAttribute(AttributesImpl attributes, String name, String value) { |