Skip to content

Commit

Permalink
Extend CustomWordPlaceholderData to insert into header/footer
Browse files Browse the repository at this point in the history
Up until now, the processing flow when inserting a paragraph into
a header or footer lead to a `ClassCastException`, as
jocument assumed that the insertion happened into a
`XWPFDocument`.
To fix this, the abstract method for transforming a placeholder
now expects an `IBody` element instead of a `XWPFDocument`, where
`IBody` is an interface which describes the possible insertion
methods.
This allows jocument to insert paragraphs into any kind of
xwpf part.
  • Loading branch information
AntonOellerer committed May 28, 2024
1 parent 4ca7bd1 commit 22e62ce
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 16 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group 'com.docutools'
version = '1.8.0'
version = '2.0.0'

java {
toolchain {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import java.util.Locale;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.xwpf.usermodel.IBody;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public abstract class CustomWordPlaceholderData implements PlaceholderData {
private static final Logger logger = LogManager.getLogger();
Expand All @@ -19,16 +19,18 @@ public PlaceholderType getType() {

@Override
public void transform(Object placeholder, Locale locale, GenerationOptions options) {
if (!(placeholder instanceof IBodyElement element)) {
if (placeholder instanceof IBodyElement element) {
if (element.getPart() instanceof IBody bodyPart) {
transform(element, bodyPart, locale, options);
} else {
logger.error("Parent of {} is not an instance of IBody", placeholder);
throw new IllegalArgumentException("Only children of IBody objects accepted.");
}
} else {
logger.error("{} is not an instance of IBodyElement", placeholder);
throw new IllegalArgumentException("Only IBodyElements accepted.");
}

var document = element.getBody().getXWPFDocument();

transform(element, document, locale, options);
}

protected abstract void transform(IBodyElement placeholder, XWPFDocument document, Locale locale, GenerationOptions options);

protected abstract void transform(IBodyElement placeholder, IBody part, Locale locale, GenerationOptions options);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import java.util.Locale;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.xwpf.usermodel.IBody;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class ImagePlaceholderData extends CustomWordPlaceholderData {
private static final Logger logger = LogManager.getLogger();
Expand All @@ -31,10 +31,10 @@ public ImagePlaceholderData withMaxWidth(int maxWidth) {
}

@Override
protected void transform(IBodyElement placeholder, XWPFDocument document, Locale locale, GenerationOptions options) {
protected void transform(IBodyElement placeholder, IBody part, Locale locale, GenerationOptions options) {
Path path = applyOptions(options);
try {
var paragraph = document.insertNewParagraph(WordUtilities.openCursor(placeholder).orElseThrow());
var paragraph = part.insertNewParagraph(WordUtilities.openCursor(placeholder).orElseThrow());
WordImageUtils.insertImage(paragraph, path, options.imageStrategy());
WordUtilities.removeIfExists(placeholder);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,4 +512,20 @@ void dynamicAccess() throws InterruptedException, IOException {
assertThat(documentWrapper.bodyElement(0).asParagraph().run(0).text(), equalTo(SampleModelData.ENTERPRISE.name()));
}

@Test
void pictureInHeader() throws InterruptedException, IOException {
// Arrange
Template template = Template.fromClassPath("/templates/word/PictureInHeader.docx")
.orElseThrow();
PlaceholderResolver resolver = new ReflectionResolver(SampleModelData.PICARD);

// Act
Document document = template.startGeneration(resolver);
document.blockUntilCompletion(60000L); // 1 minute

// Assert
assertThat(document.completed(), is(true));
xwpfDocument = TestUtils.getXWPFDocumentFromDocument(document);
assertThat(xwpfDocument.getHeaderArray(0).getAllPictures(), hasSize(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.docutools.jocument.sample.model.SampleModelData;
import java.util.Locale;
import java.util.Optional;
import org.apache.poi.xwpf.usermodel.IBody;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
Expand Down Expand Up @@ -103,7 +104,7 @@ public CustomTranslatedPlaceholder() {
}

@Override
protected void transform(IBodyElement placeholder, XWPFDocument document, Locale locale, GenerationOptions options) {
protected void transform(IBodyElement placeholder, IBody part, Locale locale, GenerationOptions options) {
if (placeholder instanceof XWPFParagraph paragraph) {
var translatedText = options.translate(paragraph.getText(), locale).orElse("");
WordUtilities.replaceText(paragraph, translatedText);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
import com.docutools.jocument.impl.word.CustomWordPlaceholderData;
import com.docutools.jocument.impl.word.WordUtilities;
import java.util.Locale;
import org.apache.poi.xwpf.usermodel.IBody;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class QuotePlaceholder extends CustomWordPlaceholderData {
@Override
protected void transform(IBodyElement placeholder, XWPFDocument document, Locale locale, GenerationOptions options) {
var paragraph = document.insertNewParagraph(WordUtilities.openCursor(placeholder).orElseThrow());
protected void transform(IBodyElement placeholder, IBody part, Locale locale, GenerationOptions options) {
var paragraph = part.insertNewParagraph(WordUtilities.openCursor(placeholder).orElseThrow());
paragraph.createRun().setText("Live your life not celebrating victories, but overcoming defeats.");
WordUtilities.removeIfExists(placeholder);
}
Expand Down
Binary file not shown.

0 comments on commit 22e62ce

Please sign in to comment.