From 9272cde24f670d832d30e389a8ad517e58660164 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 30 Nov 2024 14:28:47 +0000 Subject: [PATCH] Read default for complex field checkboxes --- .../internal/docx/StatefulBodyXmlReader.java | 22 ++++-- .../mammoth/tests/docx/BodyXmlTests.java | 74 +++++++++++++++++++ .../mammoth/tests/docx/DocumentMatchers.java | 9 ++- 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java index c8a4d9b..8519192 100644 --- a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java +++ b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java @@ -5,10 +5,7 @@ import org.zwobble.mammoth.internal.documents.*; import org.zwobble.mammoth.internal.results.InternalResult; import org.zwobble.mammoth.internal.util.*; -import org.zwobble.mammoth.internal.xml.XmlElement; -import org.zwobble.mammoth.internal.xml.XmlElementLike; -import org.zwobble.mammoth.internal.xml.XmlElementList; -import org.zwobble.mammoth.internal.xml.XmlNode; +import org.zwobble.mammoth.internal.xml.*; import java.util.*; import java.util.function.Function; @@ -335,10 +332,15 @@ private ReadResult readFieldChar(XmlElement element) { private ComplexField parseCurrentInstrText(ComplexField complexField) { String instrText = currentInstrText.toString(); - return parseInstrText(instrText, complexField); + + XmlElementLike fldChar = complexField instanceof BeginComplexField + ? ((BeginComplexField) complexField).fldChar + : NullXmlElement.INSTANCE; + + return parseInstrText(instrText, fldChar); } - private ComplexField parseInstrText(String instrText, ComplexField complexField) { + private ComplexField parseInstrText(String instrText, XmlElementLike fldChar) { Pattern externalLinkPattern = Pattern.compile("\\s*HYPERLINK \"(.*)\""); Matcher externalLinkMatcher = externalLinkPattern.matcher(instrText); if (externalLinkMatcher.lookingAt()) { @@ -356,7 +358,13 @@ private ComplexField parseInstrText(String instrText, ComplexField complexField) Pattern checkboxPattern = Pattern.compile("\\s*FORMCHECKBOX\\s*"); Matcher checkboxMatcher = checkboxPattern.matcher(instrText); if (checkboxMatcher.lookingAt()) { - return ComplexField.checkbox(false); + XmlElementLike checkboxElement = fldChar + .findChildOrEmpty("w:ffData") + .findChildOrEmpty("w:checkBox"); + + boolean checked = readBooleanElement(checkboxElement, "w:default"); + + return ComplexField.checkbox(checked); } return ComplexField.UNKNOWN; diff --git a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java index c859be4..0336bf3 100644 --- a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java +++ b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java @@ -626,6 +626,80 @@ public void complexFieldCheckboxWithSeparateIsRead() { )) ))); } + + @Test + public void complexFieldCheckboxWithoutDefaultNorCheckedIsUnchecked() { + XmlElement element = complexFieldCheckboxParagraph(list( + element("w:checkBox") + )); + + DocumentElement paragraph = readSuccess(bodyReader(), element); + + assertThat(paragraph, isParagraph(hasChildren( + isEmptyRun(), + isEmptyRun(), + isRun(hasChildren( + isCheckbox(false) + )) + ))); + } + + @Test + public void complexFieldCheckboxWithDefault0AndWithoutCheckedIsUnchecked() { + XmlElement element = complexFieldCheckboxParagraph(list( + element("w:checkBox", list( + element("w:default", map("w:val", "0")) + )) + )); + + DocumentElement paragraph = readSuccess(bodyReader(), element); + + assertThat(paragraph, isParagraph(hasChildren( + isEmptyRun(), + isEmptyRun(), + isRun(hasChildren( + isCheckbox(false) + )) + ))); + } + + @Test + public void complexFieldCheckboxWithDefault1AndWithoutCheckedIsChecked() { + XmlElement element = complexFieldCheckboxParagraph(list( + element("w:checkBox", list( + element("w:default", map("w:val", "1")) + )) + )); + + DocumentElement paragraph = readSuccess(bodyReader(), element); + + assertThat(paragraph, isParagraph(hasChildren( + isEmptyRun(), + isEmptyRun(), + isRun(hasChildren( + isCheckbox(true) + )) + ))); + } + + private XmlElement complexFieldCheckboxParagraph(List ffDataChildren) { + return element("w:p", list( + element("w:r", list( + element("w:fldChar", map("w:fldCharType", "begin"), list( + element("w:ffData", ffDataChildren) + )) + )), + element("w:instrText", list( + textXml(" FORMCHECKBOX ") + )), + element("w:r", list( + element("w:fldChar", map("w:fldCharType", "separate")) + )), + element("w:r", list( + element("w:fldChar", map("w:fldCharType", "end")) + )) + )); + } } @Test diff --git a/src/test/java/org/zwobble/mammoth/tests/docx/DocumentMatchers.java b/src/test/java/org/zwobble/mammoth/tests/docx/DocumentMatchers.java index fae84b2..67e15f0 100644 --- a/src/test/java/org/zwobble/mammoth/tests/docx/DocumentMatchers.java +++ b/src/test/java/org/zwobble/mammoth/tests/docx/DocumentMatchers.java @@ -91,9 +91,12 @@ static Matcher isHyperlink(Matcher... matche return cast(Hyperlink.class, allOf(matchers)); } - @SafeVarargs - static Matcher isCheckbox(Matcher... matchers) { - return cast(Checkbox.class, allOf(matchers)); + static Matcher isCheckbox() { + return instanceOf(Checkbox.class); + } + + static Matcher isCheckbox(boolean checked) { + return new DeepReflectionMatcher<>(new Checkbox(checked)); } static Matcher hasHref(String href) {