From 8bfc6056c879b8e8459d3d0556dbfd2ca81b4c56 Mon Sep 17 00:00:00 2001 From: Tim Allison Date: Tue, 5 May 2015 01:39:16 +0000 Subject: [PATCH] POI-57889 prevent NPE with on some documents with XWPFParagraph's getNumFmt() and add some other classes to enable calculation of paragraph numbers git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1677723 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xwpf/usermodel/XWPFParagraph.java | 90 +++++++++++++++++- .../poi/xwpf/usermodel/TestXWPFNumbering.java | 34 ++++++- test-data/document/Numbering.docx | Bin 11709 -> 13808 bytes 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java index c98143a5ae..bc0ddf85a0 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java @@ -20,7 +20,6 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; - import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.util.Internal; import org.apache.poi.wp.usermodel.Paragraph; @@ -28,11 +27,14 @@ import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTInd; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumLvl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPBdr; @@ -284,13 +286,97 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para break; } } - if(level != null) + if(level != null && level.getNumFmt() != null + && level.getNumFmt().getVal() != null) return level.getNumFmt().getVal().toString(); } } return null; } + /** + * Returns the text that should be used around the paragraph level numbers. + * + * @return a string (e.g. "%1.") or null if the value is not found. + */ + public String getNumLevelText() { + BigInteger numID = getNumID(); + XWPFNumbering numbering = document.getNumbering(); + if(numID != null && numbering != null) { + XWPFNum num = numbering.getNum(numID); + if(num != null) { + BigInteger ilvl = getNumIlvl(); + CTNum ctNum = num.getCTNum(); + if (ctNum == null) + return null; + + CTDecimalNumber ctDecimalNumber = ctNum.getAbstractNumId(); + if (ctDecimalNumber == null) + return null; + + BigInteger abstractNumId = ctDecimalNumber.getVal(); + if (abstractNumId == null) + return null; + + XWPFAbstractNum xwpfAbstractNum = numbering.getAbstractNum(abstractNumId); + + if (xwpfAbstractNum == null) + return null; + + CTAbstractNum anum = xwpfAbstractNum.getCTAbstractNum(); + + if (anum == null) + return null; + + CTLvl level = null; + for(int i = 0; i < anum.sizeOfLvlArray(); i++) { + CTLvl lvl = anum.getLvlArray(i); + if(lvl != null && lvl.getIlvl() != null && lvl.getIlvl().equals(ilvl)) { + level = lvl; + break; + } + } + if(level != null && level.getLvlText() != null + && level.getLvlText().getVal() != null) + return level.getLvlText().getVal().toString(); + } + } + return null; + } + + + /** + * Gets the numstartOverride for the paragraph numbering for this paragraph. + * @return returns the overridden start number or null if there is no override for this paragraph. + */ + public BigInteger getNumStartOverride() { + BigInteger numID = getNumID(); + XWPFNumbering numbering = document.getNumbering(); + if(numID != null && numbering != null) { + XWPFNum num = numbering.getNum(numID); + + if(num != null) { + CTNum ctNum = num.getCTNum(); + if (ctNum == null) { + return null; + } + BigInteger ilvl = getNumIlvl(); + CTNumLvl level = null; + for(int i = 0; i < ctNum.sizeOfLvlOverrideArray(); i++) { + CTNumLvl ctNumLvl = ctNum.getLvlOverrideArray(i); + if(ctNumLvl != null && ctNumLvl.getIlvl() != null && + ctNumLvl.getIlvl().equals(ilvl)) { + level = ctNumLvl; + break; + } + } + if(level != null && level.getStartOverride() != null) { + return level.getStartOverride().getVal(); + } + } + } + return null; + } /** * setNumID of Paragraph * @param numPos diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java index fce9d18e08..2cae023cf9 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java @@ -26,7 +26,7 @@ import org.apache.poi.xwpf.XWPFTestDataSamples; public class TestXWPFNumbering extends TestCase { - public void testCompareAbstractNum() throws IOException{ + public void testCompareAbstractNum() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); XWPFNumbering numbering = doc.getNumbering(); BigInteger numId = BigInteger.valueOf(1); @@ -74,4 +74,36 @@ public class TestXWPFNumbering extends TestCase { assertEquals("lowerLetter", doc.getParagraphs().get(5).getNumFmt()); assertEquals("lowerRoman", doc.getParagraphs().get(6).getNumFmt()); } + + public void testLvlText() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); + + assertEquals("%1.%2.%3.", doc.getParagraphs().get(12).getNumLevelText()); + + assertEquals("NEW-%1-FORMAT", doc.getParagraphs().get(14).getNumLevelText()); + + XWPFParagraph p = doc.getParagraphs().get(18); + assertEquals("%1.", p.getNumLevelText()); + //test that null doesn't throw NPE + assertNull(p.getNumFmt()); + } + + public void testOverrideList() throws IOException { + //TODO: for now the try/catch block ensures loading/inclusion of CTNumLevel + //for down stream processing. + //Ideally, we should find files that actually use overrides and test against those. + //Use XWPFParagraph's getNumStartOverride() in the actual tests + + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); + XWPFParagraph p = doc.getParagraphs().get(18);XWPFNumbering numbering = doc.getNumbering(); + boolean ex = false; + assertNull(p.getNumStartOverride()); + try { + numbering.getNum(p.getNumID()).getCTNum().getLvlOverrideArray(1); + } catch (IndexOutOfBoundsException e) { + ex = true; + } + assertTrue(ex); + } + } diff --git a/test-data/document/Numbering.docx b/test-data/document/Numbering.docx index da0f32572f358d815dd3dbd89505b6485e16a6a1..d5605c9f7861be2e225c74eec41c68012a233ee1 100644 GIT binary patch literal 13808 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