]> source.dussan.org Git - poi.git/commitdiff
60337: XWPFTableRow.isRepeatHeader throws NullPointerException, setRepeatHeader does...
authorMark Murphy <jmarkmurphy@apache.org>
Sat, 5 Nov 2016 06:12:24 +0000 (06:12 +0000)
committerMark Murphy <jmarkmurphy@apache.org>
Sat, 5 Nov 2016 06:12:24 +0000 (06:12 +0000)
Task-Url: https://bz.apache.org/bugzilla/show_bug.cgi?id=60337

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1768153 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xwpf/model/WMLHelper.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java
src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java
src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableRow.java
test-data/document/Bug60337.docx [new file with mode: 0644]

diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/WMLHelper.java b/src/ooxml/java/org/apache/poi/xwpf/model/WMLHelper.java
new file mode 100644 (file)
index 0000000..7c30d21
--- /dev/null
@@ -0,0 +1,33 @@
+/* ====================================================================
+   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.
+==================================================================== */
+package org.apache.poi.xwpf.model;
+
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
+
+public final class WMLHelper {
+    
+    public static boolean STOnOffToBoolean (STOnOff.Enum value) {
+        if (value == STOnOff.TRUE || value == STOnOff.ON || value == STOnOff.X_1) {
+            return true;
+        }
+        return false;
+    }
+    
+    public static STOnOff.Enum BooleanToSTOnOff (boolean value) {
+        return (value ? STOnOff.TRUE : STOnOff.FALSE);
+    }
+}
index eb1ec777533a452f4de372d9a08e72126aebd5a5..3f530df7659b12faca9b4a3dd84361704113bbeb 100644 (file)
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.poi.util.Internal;
+import org.apache.poi.xwpf.model.WMLHelper;
 import org.apache.xmlbeans.XmlCursor;
 import org.apache.xmlbeans.XmlObject;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHeight;
@@ -190,57 +191,76 @@ public class XWPFTableRow {
      *\r
      * @return true if rows can't be split, false otherwise.\r
      */\r
-    public boolean isCantSplitRow() {\r
-        boolean isCant = false;\r
-        CTTrPr trpr = getTrPr();\r
-        if (trpr.sizeOfCantSplitArray() > 0) {\r
-            CTOnOff onoff = trpr.getCantSplitArray(0);\r
-            isCant = onoff.getVal().equals(STOnOff.ON);\r
-        }\r
-        return isCant;\r
+    public boolean isCantSplitRow() {
+        boolean isCant = false;
+        if (ctRow.isSetTrPr()) {
+            CTTrPr trpr = getTrPr();
+            if (trpr.sizeOfCantSplitArray() > 0) {
+                CTOnOff onoff = trpr.getCantSplitArray(0);
+                isCant = (onoff.isSetVal() ? WMLHelper.STOnOffToBoolean(onoff.getVal()) : true);
+            }
+        }
+        return isCant;
     }\r
 \r
     /**\r
-     * This attribute controls whether to allow table rows to split across pages.\r
+     * Controls whether to allow this table row to split across pages.\r
      * The logic for this attribute is a little unusual: a true value means\r
      * DON'T allow rows to split, false means allow rows to split.\r
      *\r
-     * @param split - if true, don't allow rows to be split. If false, allow\r
-     *              rows to be split.\r
+     * @param split - if true, don't allow row to be split. If false, allow\r
+     *              row to be split.\r
      */\r
     public void setCantSplitRow(boolean split) {\r
         CTTrPr trpr = getTrPr();\r
-        CTOnOff onoff = trpr.addNewCantSplit();\r
-        onoff.setVal(split ? STOnOff.ON : STOnOff.OFF);\r
+        CTOnOff onoff = (trpr.sizeOfCantSplitArray() > 0 ? trpr.getCantSplitArray(0) : trpr.addNewCantSplit());\r
+        onoff.setVal(WMLHelper.BooleanToSTOnOff(split));\r
     }\r
 \r
     /**\r
      * Return true if a table's header row should be repeated at the top of a\r
-     * table split across pages.\r
+     * table split across pages. NOTE - Word will not repeat a table row unless
+     * all preceding rows of the table are also repeated. This function returns
+     * false if the row will not be repeated even if the repeat tag is present
+     * for this row. \r
      *\r
      * @return true if table's header row should be repeated at the top of each\r
      * page of table, false otherwise.\r
      */\r
     public boolean isRepeatHeader() {\r
-        boolean repeat = false;\r
-        CTTrPr trpr = getTrPr();\r
-        if (trpr.sizeOfTblHeaderArray() > 0) {\r
-            CTOnOff rpt = trpr.getTblHeaderArray(0);\r
-            repeat = rpt.getVal().equals(STOnOff.ON);\r
+        boolean repeat = false;
+        for (XWPFTableRow row : table.getRows()) {
+            repeat = row.getRepeat();
+            if (row == this || !repeat) {
+                break;
+            }
         }\r
         return repeat;\r
+    }
+    
+    private boolean getRepeat() {
+        boolean repeat = false;
+        if (ctRow.isSetTrPr()) {
+            CTTrPr trpr = getTrPr();
+            if (trpr.sizeOfTblHeaderArray() > 0) {
+                CTOnOff rpt = trpr.getTblHeaderArray(0);
+                repeat = (rpt.isSetVal() ? WMLHelper.STOnOffToBoolean(rpt.getVal()) : true);
+            }
+        }
+        return repeat;
     }\r
 \r
     /**\r
      * This attribute controls whether to repeat a table's header row at the top\r
-     * of a table split across pages.\r
+     * of a table split across pages. NOTE - for a row to be repeated, all preceding
+     * rows in the table must also be repeated.\r
      *\r
      * @param repeat - if TRUE, repeat header row at the top of each page of table;\r
      *               if FALSE, don't repeat header row.\r
      */\r
     public void setRepeatHeader(boolean repeat) {\r
         CTTrPr trpr = getTrPr();\r
-        CTOnOff onoff = trpr.addNewTblHeader();\r
-        onoff.setVal(repeat ? STOnOff.ON : STOnOff.OFF);\r
+        CTOnOff onoff = (trpr.sizeOfTblHeaderArray() > 0 ? trpr.getTblHeaderArray(0) : trpr.addNewTblHeader());\r
+        onoff.setVal(WMLHelper.BooleanToSTOnOff(repeat));\r
     }\r
 }\r
index 0f625fbd9089bceb602c3d5f5ac3e5868c3de0f7..c9d12bddce493ac12b6a1339ad57467915dd6ca4 100644 (file)
 
 package org.apache.poi.xwpf.usermodel;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
-import junit.framework.TestCase;
 import org.apache.poi.xwpf.XWPFTestDataSamples;
+import org.junit.Ignore;
+import org.junit.Test;
 
-public final class TestXWPFSDT extends TestCase {
+public final class TestXWPFSDT {
 
     /**
      * Test simple tag and title extraction from SDT
      *
      * @throws Exception
      */
+    @Test
     public void testTagTitle() throws Exception {
         XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54849.docx");
         String tag = null;
@@ -51,7 +56,7 @@ public final class TestXWPFSDT extends TestCase {
         assertEquals("title", "MyTitle", title);
     }
 
-
+    @Test
     public void testGetSDTs() throws Exception {
         String[] contents = new String[]{
                 "header_rich_text",
@@ -83,6 +88,7 @@ public final class TestXWPFSDT extends TestCase {
     /**
      * POI-54771 and TIKA-1317
      */
+    @Test
     public void testSDTAsCell() throws Exception {
         //Bug54771a.docx and Bug54771b.docx test slightly 
         //different recursion patterns. Keep both!
@@ -110,6 +116,7 @@ public final class TestXWPFSDT extends TestCase {
     /**
      * POI-55142 and Tika 1130
      */
+    @Test
     public void testNewLinesBetweenRuns() throws Exception {
         XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug55142.docx");
         List<AbstractXWPFSDT> sdts = extractAllSDTs(doc);
@@ -132,6 +139,7 @@ public final class TestXWPFSDT extends TestCase {
         }
     }
 
+    @Ignore
     public void test60341() throws IOException {
         //handle sdtbody without an sdtpr
         XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug60341.docx");
index b22f1a0cb77a87c7da79e26dbeac8b5691f0da4d..57ed435320368c27a9719d56c7f923876f9cf9df 100644 (file)
 
 package org.apache.poi.xwpf.usermodel;
 
-import junit.framework.TestCase;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-public class TestXWPFTableRow extends TestCase {
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
+import java.io.IOException;
 
-    public void testCreateRow() throws Exception {
-        CTRow ctRow = CTRow.Factory.newInstance();
-        assertNotNull(ctRow);
-    }
+import org.apache.poi.xwpf.XWPFTestDataSamples;
+import org.junit.Test;
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+public class TestXWPFTableRow {
+
+    @Test
+    public void testCreateRow() throws IOException {
+        XWPFDocument doc = new XWPFDocument();
+        XWPFTable table = doc.createTable(1, 1);
+        XWPFTableRow tr = table.createRow();
+        assertNotNull(tr);
+        doc.close();
     }
 
-    public void testSetGetCantSplitRow() {
+    @Test
+    public void testSetGetCantSplitRow() throws IOException {
         // create a table
         XWPFDocument doc = new XWPFDocument();
-        CTTbl ctTable = CTTbl.Factory.newInstance();
-        XWPFTable table = new XWPFTable(ctTable, doc);
+        XWPFTable table = doc.createTable(1, 1);
         // table has a single row by default; grab it
         XWPFTableRow tr = table.getRow(0);
         assertNotNull(tr);
 
+        // Assert the repeat header is false by default
+        boolean isCantSplit = tr.isCantSplitRow();
+        assertFalse(isCantSplit);
+        
+        // Repeat the header
         tr.setCantSplitRow(true);
-        boolean isCant = tr.isCantSplitRow();
-        assert (isCant);
+        isCantSplit = tr.isCantSplitRow();
+        assertTrue(isCantSplit);
+
+        // Make the header no longer repeating
+        tr.setCantSplitRow(false);
+        isCantSplit = tr.isCantSplitRow();
+        assertFalse(isCantSplit);
+        
+        doc.close();
     }
 
-    public void testSetGetRepeatHeader() {
+    @Test
+    public void testSetGetRepeatHeader() throws IOException {
         // create a table
         XWPFDocument doc = new XWPFDocument();
-        CTTbl ctTable = CTTbl.Factory.newInstance();
-        XWPFTable table = new XWPFTable(ctTable, doc);
+        XWPFTable table = doc.createTable(3, 1);
         // table has a single row by default; grab it
         XWPFTableRow tr = table.getRow(0);
         assertNotNull(tr);
+        
+        // Assert the repeat header is false by default
+        boolean isRpt = tr.isRepeatHeader();
+        assertFalse(isRpt);
+        
+        // Repeat the header
+        tr.setRepeatHeader(true);
+        isRpt = tr.isRepeatHeader();
+        assertTrue(isRpt);
 
+        // Make the header no longer repeating
+        tr.setRepeatHeader(false);
+        isRpt = tr.isRepeatHeader();
+        assertFalse(isRpt);
+        
+        // If the third row is set to repeat, but not the second,
+        // isRepeatHeader should report false because Word will
+        // ignore it.
+        tr = table.getRow(2);
         tr.setRepeatHeader(true);
+        isRpt = tr.isRepeatHeader();
+        assertFalse(isRpt);
+        
+        doc.close();
+    }
+    
+    // Test that validates the table header value can be parsed from a document
+    // generated in Word
+    @Test
+    public void testIsRepeatHeader() throws Exception {
+        XWPFDocument doc = XWPFTestDataSamples
+                .openSampleDocument("Bug60337.docx");
+        XWPFTable table = doc.getTables().get(0);
+        XWPFTableRow tr = table.getRow(0);
         boolean isRpt = tr.isRepeatHeader();
-        assert (isRpt);
+        assertTrue(isRpt);
+        
+        tr = table.getRow(1);
+        isRpt = tr.isRepeatHeader();
+        assertFalse(isRpt);
+        
+        tr = table.getRow(2);
+        isRpt = tr.isRepeatHeader();
+        assertFalse(isRpt);
+    }
+    
+    
+    // Test that validates the table header value can be parsed from a document
+    // generated in Word
+    @Test
+    public void testIsCantSplit() throws Exception {
+        XWPFDocument doc = XWPFTestDataSamples
+                .openSampleDocument("Bug60337.docx");
+        XWPFTable table = doc.getTables().get(0);
+        XWPFTableRow tr = table.getRow(0);
+        boolean isCantSplit = tr.isCantSplitRow();
+        assertFalse(isCantSplit);
+        
+        tr = table.getRow(1);
+        isCantSplit = tr.isCantSplitRow();
+        assertFalse(isCantSplit);
+
+        tr = table.getRow(2);
+        isCantSplit = tr.isCantSplitRow();
+        assertTrue(isCantSplit);
     }
 }
diff --git a/test-data/document/Bug60337.docx b/test-data/document/Bug60337.docx
new file mode 100644 (file)
index 0000000..06d0339
Binary files /dev/null and b/test-data/document/Bug60337.docx differ