You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by rm...@apache.org on 2013/10/22 12:06:12 UTC

svn commit: r1534582 - in /xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf: RTFHandler.java RTFPlaceHolderHelper.java rtflib/tools/BuilderContext.java

Author: rmeyer
Date: Tue Oct 22 10:06:12 2013
New Revision: 1534582

URL: http://svn.apache.org/r1534582
Log:
FOP-2104: RTF renderer barfs when fo:table-row is missing inside fo-table-header

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFPlaceHolderHelper.java
Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFHandler.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/rtflib/tools/BuilderContext.java

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFHandler.java?rev=1534582&r1=1534581&r2=1534582&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFHandler.java Tue Oct 22 10:06:12 2013
@@ -157,6 +157,7 @@ public class RTFHandler extends FOEventH
 
     private PercentContext percentManager = new PercentContext();
 
+
     /**
      * Creates a new RTF structure handler.
      * @param userAgent the FOUserAgent for this process
@@ -270,7 +271,7 @@ public class RTFHandler extends FOEventH
 
             return;
         } else {
-            builderContext.popContainer();
+            builderContext.popContainer(RtfSection.class, this);
             this.pagemaster = null;
         }
     }
@@ -377,10 +378,10 @@ public class RTFHandler extends FOEventH
                 //just do nothing
             } else if (regionBefore != null
                     && fl.getFlowName().equals(regionBefore.getRegionName())) {
-                builderContext.popContainer();
+                builderContext.popContainer(RtfBefore.class, this);
             } else if (regionAfter != null
                     && fl.getFlowName().equals(regionAfter.getRegionName())) {
-                builderContext.popContainer();
+                builderContext.popContainer(RtfAfter.class, this);
             }
         } catch (Exception e) {
             log.error("endFlow: " + e.getMessage());
@@ -571,7 +572,7 @@ public class RTFHandler extends FOEventH
 
         nestedTableDepth--;
         builderContext.popTableContext();
-        builderContext.popContainer();
+        builderContext.popContainer(RtfTable.class, this);
     }
 
     /** {@inheritDoc} */
@@ -605,21 +606,25 @@ public class RTFHandler extends FOEventH
 
     /** {@inheritDoc} */
     public void startHeader(TableHeader header) {
+        builderContext.pushPart(header);
         startPart(header);
     }
 
     /** {@inheritDoc} */
     public void endHeader(TableHeader header) {
+        builderContext.popPart(header.getClass(), this);
         endPart(header);
     }
 
     /** {@inheritDoc} */
     public void startFooter(TableFooter footer) {
+        builderContext.pushPart(footer);
         startPart(footer);
     }
 
     /** {@inheritDoc} */
     public void endFooter(TableFooter footer) {
+        builderContext.popPart(footer.getClass(), this);
         endPart(footer);
     }
 
@@ -711,11 +716,13 @@ public class RTFHandler extends FOEventH
      * {@inheritDoc}
      */
     public void startBody(TableBody body) {
+        builderContext.pushPart(body);
         startPart(body);
     }
 
     /** {@inheritDoc} */
     public void endBody(TableBody body) {
+        builderContext.popPart(TableBody.class, this);
         endPart(body);
     }
 
@@ -784,7 +791,7 @@ public class RTFHandler extends FOEventH
         }
 
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfTableRow.class, this);
         builderContext.getTableContext().decreaseRowSpannings();
     }
 
@@ -893,7 +900,7 @@ public class RTFHandler extends FOEventH
             throw new RuntimeException(e.getMessage());
         }
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfTableCell.class, this);
         builderContext.getTableContext().selectNextColumn();
     }
 
@@ -929,7 +936,7 @@ public class RTFHandler extends FOEventH
             return;
         }
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfList.class, this);
     }
 
     /** {@inheritDoc} */
@@ -976,7 +983,7 @@ public class RTFHandler extends FOEventH
             return;
         }
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfListItem.class, this);
     }
 
     /** {@inheritDoc} */
@@ -1005,7 +1012,7 @@ public class RTFHandler extends FOEventH
             return;
         }
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfListItemLabel.class, this);
     }
 
     /** {@inheritDoc} */
@@ -1070,7 +1077,7 @@ public class RTFHandler extends FOEventH
             return;
         }
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfHyperLink.class, this);
     }
 
     /** {@inheritDoc} */
@@ -1306,7 +1313,7 @@ public class RTFHandler extends FOEventH
             return;
         }
 
-        builderContext.popContainer();
+        builderContext.popContainer(RtfFootnote.class, this);
     }
 
     /** {@inheritDoc} */
@@ -1688,6 +1695,19 @@ public class RTFHandler extends FOEventH
     }
 
     /**
+     * Closes any mismatched tags that are detected in the RTF structure.
+     * @param containerClass The class representing the tag to close.
+     * @return Determines whether the tag mismatch has been handled.
+     */
+    public boolean endContainer(Class containerClass) {
+        if (containerClass == RtfTableRow.class) {
+            endRow(null);
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Calls the event handlers for the passed FONode and all its elements.
      *
      * @param foNode FONode object which shall be recursed

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFPlaceHolderHelper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFPlaceHolderHelper.java?rev=1534582&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFPlaceHolderHelper.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/RTFPlaceHolderHelper.java Tue Oct 22 10:06:12 2013
@@ -0,0 +1,72 @@
+/*
+ * 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.rtf;
+
+import org.apache.fop.render.rtf.rtflib.exceptions.RtfException;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfContainer;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
+import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
+
+/**
+ * This class creates objects which are missing from the XSL:FO but are required
+ * by the RTF format.
+ */
+public class RTFPlaceHolderHelper {
+    /** The context object for building the RTF */
+    private BuilderContext builderContext;
+
+    /**
+     * Creates a new instance for the RTF place holder which attempts to resolve
+     * mismatches in structure between XSL:FO and RTF.
+     * @param builderContext The builder context
+     */
+    public RTFPlaceHolderHelper(BuilderContext builderContext) {
+        this.builderContext = builderContext;
+    }
+
+    /**
+     * A method to create an object which is missing and required from the
+     * RTF structure.
+     * @param containerClass The class which is missing
+     * @throws Exception
+     */
+    public void createRTFPlaceholder(Class containerClass) throws RtfException {
+        if (containerClass == RtfTableRow.class) {
+            createRtfTableRow();
+        }
+    }
+
+    private void createRtfTableRow() throws RtfException {
+        try {
+            RtfContainer element = builderContext.getContainer(RtfTable.class, true, null);
+            if (element != null && element instanceof RtfTable) {
+                RtfTable table = (RtfTable)element;
+                RtfAttributes attribs = new RtfAttributes();
+                RtfTableRow newRow = table.newTableRow(attribs);
+                builderContext.pushContainer(newRow);
+                builderContext.getTableContext().selectFirstColumn();
+            }
+        } catch (Exception ex) {
+            throw new RtfException(ex.getMessage());
+        }
+    }
+}

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/rtflib/tools/BuilderContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/rtflib/tools/BuilderContext.java?rev=1534582&r1=1534581&r2=1534582&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/rtflib/tools/BuilderContext.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/rtf/rtflib/tools/BuilderContext.java Tue Oct 22 10:06:12 2013
@@ -21,6 +21,12 @@ package org.apache.fop.render.rtf.rtflib
 
 import java.util.Stack;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.fo.FObj;
+import org.apache.fop.render.rtf.RTFHandler;
+import org.apache.fop.render.rtf.RTFPlaceHolderHelper;
 import org.apache.fop.render.rtf.rtflib.exceptions.RtfException;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfOptions;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfContainer;
@@ -38,6 +44,10 @@ import org.apache.fop.render.rtf.rtflib.
  */
 
 public class BuilderContext {
+
+    /** Static logging instance */
+    protected static final Log LOG = LogFactory.getLog(BuilderContext.class.getName());
+
     /** stack of RtfContainers */
     private final Stack containers = new Stack();
 
@@ -96,17 +106,22 @@ public class BuilderContext {
      * @throws RtfException if not caught
      */
     public RtfContainer getContainer(Class containerClass, boolean required,
-                              Object /*IBuilder*/ forWhichBuilder) throws RtfException {
+            Object forWhichBuilder) throws RtfException {
         // TODO what to do if the desired container is not at the top of the stack?
         // close top-of-stack container?
-        final RtfContainer result = (RtfContainer)getObjectFromStack(containers,
+        RtfContainer result = (RtfContainer)getObjectFromStack(containers,
                 containerClass);
 
         if (result == null && required) {
-            throw new RtfException(
-                "No RtfContainer of class '" + containerClass.getName()
-                + "' available for '" + forWhichBuilder.getClass().getName() + "' builder"
-               );
+            RTFPlaceHolderHelper placeHolderHelper = new RTFPlaceHolderHelper(this);
+            placeHolderHelper.createRTFPlaceholder(containerClass);
+            result = getContainer(containerClass, required, forWhichBuilder);
+            if (result == null) {
+                throw new RtfException(
+                    "No RtfContainer of class '" + containerClass.getName()
+                    + "' available for '" + forWhichBuilder.getClass().getName() + "' builder"
+                   );
+            }
         }
 
         return result;
@@ -121,6 +136,14 @@ public class BuilderContext {
     }
 
     /**
+     * Push a Class representing a non-writeable section of the FO tree
+     * @param part the part
+     */
+    public void pushPart(FObj part) {
+        containers.push(part);
+    }
+
+    /**
      * In some cases an RtfContainer must be replaced by another one on the
      * stack. This happens when handling nested fo:blocks for example: after
      * handling a nested block the enclosing block must switch to a new
@@ -142,8 +165,40 @@ public class BuilderContext {
     }
 
     /** pop the topmost RtfContainer from our stack */
-    public void popContainer() {
-        containers.pop();
+    public void popContainer(Class containerClass, RTFHandler handler) {
+        handlePop(containerClass, handler);
+    }
+
+    /** pop the topmost part class from our stack */
+    public void popPart(Class part, RTFHandler handler) {
+        handlePop(part, handler);
+    }
+
+    /**
+     * This method checks for any tag mismatches between what is being closed
+     * and what exists on the stack. If a mismatch is found, then it will push
+     * the object back onto the stack and attempt to close the given section
+     * before retrying with the current pop task.
+     * @param aClass The class to be popped from the stack
+     * @param handler The RTF handler class to fix any mismatches
+     */
+    private void handlePop(Class aClass, RTFHandler handler) {
+        Object object = containers.pop();
+        if (object.getClass() != aClass) {
+            pushAndClose(aClass, object, handler);
+        }
+    }
+
+    private void pushAndClose(Class aClass, Object object, RTFHandler handler) {
+        containers.push(object);
+        if (handler.endContainer(object.getClass())) {
+            popContainer(aClass, handler);
+        } else {
+            /* This should never happen unless a placeholder is not catered for
+             * in the RTFHandler.endContainer method. */
+            LOG.warn("Unhandled RTF structure tag mismatch detected between " +
+                    aClass.getSimpleName() + " and "+object.getClass().getSimpleName());
+        }
     }
 
     /* push an IBuilder to our stack /



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org