This is an automated email from the ASF dual-hosted git repository.
fanningpj pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git
The following commit(s) were added to refs/heads/trunk by this push:
new 6d8f1901dc Allow null values in XWPFParagraph.get/setAlignment().
(#829)
6d8f1901dc is described below
commit 6d8f1901dcf6cd5f6261e93c293b4383858e1b1d
Author: Jacobo Aragunde Pérez <[email protected]>
AuthorDate: Wed Jul 9 21:00:14 2025 +0200
Allow null values in XWPFParagraph.get/setAlignment(). (#829)
* Allow null values in XWPFParagraph.get/setAlignment().
A null value in this field would indicate that the paragraph should
follow the alignment provided by the style hierarchy.
Fixes: https://bz.apache.org/bugzilla/show_bug.cgi?id=69720
* Revert getAlignment() and implement isAlignmentSet() instead.
* Replace test case file.
* Implement XWPFParagraph.getTCPPr(create).
It lets the caller choose if a new PPr should be created in case it
doesn't exist.
* use getCTPPr(boolean)
* compile issue
---------
Co-authored-by: PJ Fanning <[email protected]>
---
.../apache/poi/xwpf/usermodel/XWPFParagraph.java | 77 ++++++++++++++++-----
.../java/org/apache/poi/xwpf/TestXWPFBugs.java | 23 +++---
.../poi/xwpf/usermodel/TestXWPFParagraph.java | 7 ++
test-data/document/bug-paragraph-alignment.docx | Bin 0 -> 11916 bytes
4 files changed, 83 insertions(+), 24 deletions(-)
diff --git
a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java
b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java
index 7f3ab37ff6..44bc523096 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java
@@ -482,16 +482,19 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* Returns the paragraph alignment which shall be applied to text in this
* paragraph.
* <p>
- * If this element is not set on a given paragraph, its value is determined
+ * If this element is not set on a given paragraph, this function returns
+ * ParagraphAlignment.LEFT as a placeholder value, and isAlignmentSet()
+ * returns false. In such case, the alignment value must be determined
* by the setting previously set at any level of the style hierarchy (i.e.
* that previous setting remains unchanged). If this setting is never
* specified in the style hierarchy, then no alignment is applied to the
* paragraph.
*
+ * @see #isAlignmentSet()
* @return the paragraph alignment of this paragraph.
*/
public ParagraphAlignment getAlignment() {
- CTPPr pr = getCTPPr();
+ CTPPr pr = getCTPPr(false);
return pr == null || !pr.isSetJc() ? ParagraphAlignment.LEFT
: ParagraphAlignment.valueOf(pr.getJc().getVal().intValue());
}
@@ -506,13 +509,32 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* specified in the style hierarchy, then no alignment is applied to the
* paragraph.
*
- * @param align the paragraph alignment to apply to this paragraph.
+ * @param align the paragraph alignment to apply to this paragraph. It can
+ * be null to unset it and fall back to the style hierarchy.
*/
public void setAlignment(ParagraphAlignment align) {
- CTPPr pr = getCTPPr();
- CTJc jc = pr.isSetJc() ? pr.getJc() : pr.addNewJc();
- STJc.Enum en = STJc.Enum.forInt(align.getValue());
- jc.setVal(en);
+ if (align == null) {
+ CTPPr pr = getCTPPr(false);
+ if (pr != null)
+ pr.unsetJc();
+ } else {
+ CTPPr pr = getCTPPr(true);
+ CTJc jc = pr.isSetJc() ? pr.getJc() : pr.addNewJc();
+ STJc.Enum en = STJc.Enum.forInt(align.getValue());
+ jc.setVal(en);
+ }
+ }
+
+ /**
+ * Returns true if the paragraph has a paragraph alignment value of its own
+ * or false in case it should fall back to the alignment value set by the
+ * paragraph style.
+ *
+ * @return boolean
+ */
+ public boolean isAlignmentSet() {
+ CTPPr pr = getCTPPr(false);
+ return pr != null && pr.isSetJc();
}
/**
@@ -548,7 +570,7 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* @return the vertical alignment of this paragraph.
*/
public TextAlignment getVerticalAlignment() {
- CTPPr pr = getCTPPr();
+ CTPPr pr = getCTPPr(false);
return (pr == null || !pr.isSetTextAlignment()) ? TextAlignment.AUTO
: TextAlignment.valueOf(pr.getTextAlignment().getVal()
.intValue());
@@ -864,7 +886,10 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* @return boolean - if page break is set
*/
public boolean isPageBreak() {
- final CTPPr ppr = getCTPPr();
+ final CTPPr ppr = getCTPPr(false);
+ if (ppr == null) {
+ return false;
+ }
final CTOnOff ctPageBreak = ppr.isSetPageBreakBefore() ?
ppr.getPageBreakBefore() : null;
if (ctPageBreak == null) {
return false;
@@ -1353,7 +1378,8 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
*/
@Override
public boolean isWordWrapped() {
- return getCTPPr().isSetWordWrap() &&
POIXMLUnits.parseOnOff(getCTPPr().getWordWrap());
+ CTPPr ppr = getCTPPr(false);
+ return ppr != null && ppr.isSetWordWrap() &&
POIXMLUnits.parseOnOff(ppr.getWordWrap());
}
/**
@@ -1390,7 +1416,10 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* @return the style of the paragraph
*/
public String getStyle() {
- CTPPr pr = getCTPPr();
+ CTPPr pr = getCTPPr(false);
+ if (pr == null) {
+ return null;
+ }
CTString style = pr.isSetPStyle() ? pr.getPStyle() : null;
return style != null ? style.getVal() : null;
}
@@ -1411,7 +1440,10 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* a new instance.
*/
private CTPBdr getCTPBrd(boolean create) {
- CTPPr pr = getCTPPr();
+ CTPPr pr = getCTPPr(create);
+ if (pr == null) {
+ return null;
+ }
CTPBdr ct = pr.isSetPBdr() ? pr.getPBdr() : null;
if (create && ct == null) {
ct = pr.addNewPBdr();
@@ -1424,7 +1456,7 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* return a new instance.
*/
private CTSpacing getCTSpacing(boolean create) {
- CTPPr pr = getCTPPr();
+ CTPPr pr = getCTPPr(create);
CTSpacing ct = pr.getSpacing();
if (create && ct == null) {
ct = pr.addNewSpacing();
@@ -1437,7 +1469,10 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
* a new instance.
*/
private CTInd getCTInd(boolean create) {
- CTPPr pr = getCTPPr();
+ CTPPr pr = getCTPPr(create);
+ if (pr == null) {
+ return null;
+ }
CTInd ct = pr.getInd();
if (create && ct == null) {
ct = pr.addNewInd();
@@ -1451,8 +1486,18 @@ public class XWPFParagraph implements IBodyElement,
IRunBody, ISDTContents, Para
*/
@Internal
public CTPPr getCTPPr() {
- return paragraph.getPPr() == null ? paragraph.addNewPPr()
- : paragraph.getPPr();
+ return getCTPPr(true);
+ }
+
+ /**
+ * Get a <b>copy</b> of the currently used CTPPr. If none is used, return
+ * a new instance when create is true, or null when create is false.
+ *
+ * @param create create a new instance if none exists.
+ */
+ private CTPPr getCTPPr(final boolean create) {
+ return (paragraph.isSetPPr() || !create) ? paragraph.getPPr()
+ : paragraph.addNewPPr();
}
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xwpf/TestXWPFBugs.java
b/poi-ooxml/src/test/java/org/apache/poi/xwpf/TestXWPFBugs.java
index ecf9d13601..4eefc3517a 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xwpf/TestXWPFBugs.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xwpf/TestXWPFBugs.java
@@ -16,10 +16,7 @@
==================================================================== */
package org.apache.poi.xwpf;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.io.File;
@@ -42,10 +39,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.filesystem.Ole10Native;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFTable;
-import org.apache.poi.xwpf.usermodel.XWPFTableCell;
+import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.junit.jupiter.api.Test;
@@ -241,4 +235,17 @@ class TestXWPFBugs {
XWPFTable xwpfTable = document.insertNewTbl(xmlCursor);
xwpfTable.getRow(0).getCell(0).setText("Hello");
}
+
+ @Test
+ void correctParagraphAlignment() throws IOException {
+ try (XWPFDocument document = new
XWPFDocument(samples.openResourceAsStream("bug-paragraph-alignment.docx"))) {
+ XWPFParagraph centeredParagraph = document.getParagraphArray(0);
+ assertFalse(centeredParagraph.isAlignmentSet());
+ assertEquals(ParagraphAlignment.LEFT,
centeredParagraph.getAlignment()); // LEFT is a fallback value here.
+
+ XWPFParagraph leftParagraph = document.getParagraphArray(1);
+ assertTrue(leftParagraph.isAlignmentSet());
+ assertEquals(ParagraphAlignment.LEFT,
leftParagraph.getAlignment()); // LEFT is the real alignment value.
+ }
+ }
}
diff --git
a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java
b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java
index 518734f4f6..2aaf6b1072 100644
---
a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java
+++
b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java
@@ -132,6 +132,7 @@ public final class TestXWPFParagraph {
XWPFParagraph p = doc.createParagraph();
assertEquals(STJc.LEFT.intValue(), p.getAlignment().getValue());
+ assertFalse(p.isAlignmentSet());
CTP ctp = p.getCTP();
CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr();
@@ -139,9 +140,15 @@ public final class TestXWPFParagraph {
CTJc align = ppr.addNewJc();
align.setVal(STJc.CENTER);
assertEquals(ParagraphAlignment.CENTER, p.getAlignment());
+ assertTrue(p.isAlignmentSet());
p.setAlignment(ParagraphAlignment.BOTH);
assertEquals(STJc.BOTH, ppr.getJc().getVal());
+ assertTrue(p.isAlignmentSet());
+
+ p.setAlignment(null);
+ assertEquals(STJc.LEFT.intValue(), p.getAlignment().getValue());
+ assertFalse(p.isAlignmentSet());
}
}
diff --git a/test-data/document/bug-paragraph-alignment.docx
b/test-data/document/bug-paragraph-alignment.docx
new file mode 100644
index 0000000000..de4a468552
Binary files /dev/null and b/test-data/document/bug-paragraph-alignment.docx
differ
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]