Skip to content

Commit

Permalink
Merge pull request #224 from DDS-GmbH/fix/iterable-placeholder-to-string
Browse files Browse the repository at this point in the history
Fix/iterable placeholder to string
  • Loading branch information
alexpartsch committed Aug 9, 2023
2 parents f836817 + 7fb7cf1 commit 8e0120e
Show file tree
Hide file tree
Showing 14 changed files with 125 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.6.3'
version = '1.6.4'

java {
toolchain {
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/docutools/jocument/PlaceholderResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,13 @@ private PlaceholderData format(Locale locale, PlaceholderData original) {

protected abstract Optional<PlaceholderData> doResolve(String placeholderName, Locale locale);

/**
* Overwrite of the {@link Object#toString()} method, forcing any subclass to implement it,
* since its required for resolving {@link com.docutools.jocument.impl.IterablePlaceholderData}
* when no loop-end is present
*
* @return a {@link String}
*/
@Override
public abstract String toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.docutools.jocument.PlaceholderType;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

Expand Down Expand Up @@ -45,4 +46,10 @@ public long count() {
return count;
}

@Override
public String toString() {
return StreamSupport.stream(iterable.spliterator(), false)
.map(Object::toString)
.collect(Collectors.joining(", "));
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/docutools/jocument/impl/JsonResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ protected Optional<PlaceholderData> doResolve(String placeholderName, Locale loc
return Optional.empty();
}

@Override
public String toString() {
return jsonElement.getAsString();
}

private Optional<PlaceholderData> fromObject(String placeholderName, JsonObject jsonObject) {
if (!jsonObject.has(placeholderName)) {
logger.info("Did not find placeholder {} in JSON Object {}", placeholderName, jsonObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,9 @@ private Object resolveNonFinalValue(Object property, String placeholderName)
}
return resolvedProperty;
}

@Override
public String toString() {
return bean.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
import com.docutools.jocument.impl.ParsingUtils;
import com.docutools.jocument.impl.excel.interfaces.ExcelWriter;
import com.docutools.jocument.impl.excel.util.ExcelUtils;
import com.docutools.jocument.impl.word.WordUtilities;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;


/**
Expand Down Expand Up @@ -165,12 +168,27 @@ private boolean isLoopStart(Row row) {
if (ExcelUtils.getNumberOfNonEmptyCells(row) == 1) {
var cell = row.getCell(row.getFirstCellNum());
if (cell.getCellType() == CellType.STRING) {
return resolver.resolve(
ParsingUtils.stripBrackets(
cell.getStringCellValue()
)).map(PlaceholderData::getType)
.map(type -> type == PlaceholderType.SET)
.orElse(false);
var placeholderName = ParsingUtils.stripBrackets(
cell.getStringCellValue()
);
return resolver.resolve(placeholderName)
.filter(placeholderData -> placeholderData.getType() == PlaceholderType.SET)
.map(placeholderData -> {
var endLoopMarkers = ParsingUtils.getMatchingLoopEnds(placeholderName);
// Since ExcelGenerator only takes an Iterator of the remaining elements, we can't
// do a lookahead from that. So we access the sheet from the current row and create
// a new iterator dropping everything before the current row.
return StreamSupport.stream(row.getSheet().spliterator(), false)
// since we only get the physical row index we need to manually probe till we
// reach the current iterator state
.dropWhile(nextRow -> !nextRow.equals(row))
.skip(1)
.filter(nextRow -> ExcelUtils.getNumberOfNonEmptyCells(nextRow) == 1)
.map(nextRow -> nextRow.getCell(nextRow.getFirstCellNum()))
.filter(nextCell -> nextCell.getCellType() == CellType.STRING)
.map(Cell::getStringCellValue)
.anyMatch(text -> endLoopMarkers.contains(text.strip()));
}).orElse(false);
}
}
return false;
Expand Down
27 changes: 18 additions & 9 deletions src/main/java/com/docutools/jocument/impl/word/WordGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private void transform(IBodyElement element, List<IBodyElement> remaining) {
if (isCustomPlaceholder(element)) {
resolver.resolve(WordUtilities.extractPlaceholderName((XWPFParagraph) element))
.ifPresent(placeholderData -> placeholderData.transform(element, locale, options));
} else if (isLoopStart(element)) {
} else if (isLoopStart(element, remaining)) {
unrollLoop((XWPFParagraph) element, remaining);
} else if (element instanceof XWPFParagraph xwpfParagraph) {
transform(xwpfParagraph);
Expand Down Expand Up @@ -121,14 +121,23 @@ private List<IBodyElement> getLoopBody(String placeholderName, List<IBodyElement
.toList();
}

private boolean isLoopStart(IBodyElement element) {
return element instanceof XWPFParagraph xwpfParagraph
&& resolver.resolve(
ParsingUtils.stripBrackets(
WordUtilities.toString(xwpfParagraph)
)).map(PlaceholderData::getType)
.map(type -> type == PlaceholderType.SET)
.orElse(false);
private boolean isLoopStart(IBodyElement element, List<IBodyElement> remaining) {
if (element instanceof XWPFParagraph xwpfParagraph) {
var placeholderName = ParsingUtils.stripBrackets(
WordUtilities.toString(xwpfParagraph)
);
return resolver.resolve(placeholderName)
.filter(placeholderData -> placeholderData.getType() == PlaceholderType.SET)
.map(placeholderData -> {
var endLoopMarkers = ParsingUtils.getMatchingLoopEnds(placeholderName);
return remaining.stream()
.filter(bodyElement -> bodyElement instanceof XWPFParagraph)
.map(bodyElement -> (XWPFParagraph)bodyElement)
.map(XWPFParagraph::getText)
.anyMatch(text -> endLoopMarkers.contains(text.strip()));
}).orElse(false);
}
return false;
}

private boolean isCustomPlaceholder(IBodyElement element) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
Expand All @@ -17,6 +18,7 @@
import com.docutools.jocument.sample.placeholders.QuotesBlockPlaceholder;
import com.docutools.poipath.PoiPath;
import com.docutools.poipath.xssf.XSSFWorkbookWrapper;
import com.docutools.poipath.xwpf.XWPFDocumentWrapper;
import java.io.IOException;
import java.time.LocalDate;
import java.time.Period;
Expand Down Expand Up @@ -268,4 +270,23 @@ void evaluatesLargeDocument() throws InterruptedException {
assertThat(document.completed(), is(true));

}

@Test
@DisplayName("Resolve IterablePlaceholder with toString when there's no closing placeholder.")
void shouldResolveIPWithToStringWhenNoLoop() throws InterruptedException, IOException {
// Assemble
Template template = Template.fromClassPath("/templates/excel/IterablePlaceholderWithoutLoop.xlsx")
.orElseThrow();
var resolver = new ReflectionResolver(SampleModelData.PICARD);

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

// Assert
assertThat(document.completed(), is(true));
workbook = TestUtils.getXSSFWorkbookFromDocument(document);
var documentWrapper = new XSSFWorkbookWrapper(workbook);
assertThat(documentWrapper.sheet(0).row(0).cell(0).text(), containsString(SampleModelData.PICARD.getOfficer().toString()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -451,4 +451,23 @@ void shouldFormatInstant() throws IOException, InterruptedException {
var documentWrapper = new XWPFDocumentWrapper(xwpfDocument);
assertThat(documentWrapper.bodyElement(0).asParagraph().text(), containsString(SampleModelData.PICARD_PERSON.getEntryDate().toString()));
}

@Test
@DisplayName("Resolve IterablePlaceholder with toString when there's no closing placeholder.")
void shouldResolveIPWithToStringWhenNoLoop() throws InterruptedException, IOException {
// Assemble
Template template = Template.fromClassPath("/templates/word/IterablePlaceholderWithoutLoop.docx")
.orElseThrow();
var 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);
var documentWrapper = new XWPFDocumentWrapper(xwpfDocument);
assertThat(documentWrapper.bodyElement(0).asParagraph().text(), containsString(SampleModelData.PICARD.getOfficer().toString()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;

public class SamplePlaceholderResolver extends PlaceholderResolver {

Expand All @@ -26,4 +27,9 @@ protected Optional<PlaceholderData> doResolve(String placeholderName, Locale loc
}
}

@Override
public String toString() {
return services.stream().map(PlaceholderResolver::toString).collect(Collectors.joining(", "));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ protected Optional<PlaceholderData> doResolve(String placeholderName, Locale loc
}
}

@Override
public String toString() {
return name;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public int getRank() {
public Uniform getUniform() {
return uniform;
}

@Override
public String toString() {
return name;
}
}
Binary file not shown.
Binary file not shown.

0 comments on commit 8e0120e

Please sign in to comment.