Skip to content

Commit

Permalink
sc-6127 Enhance poipath for insertion to generat templates dynamically
Browse files Browse the repository at this point in the history
By extending poipath for insertion, it could be made possible to generate templates for generator tests dynamically.
  • Loading branch information
amp authored and AntonOellerer committed Jan 18, 2023
1 parent 77cb2b1 commit 07937c0
Show file tree
Hide file tree
Showing 10 changed files with 622 additions and 3 deletions.
72 changes: 71 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,74 @@ class TestReports {
}
```

## Defining XWPF/XSSF Datastructures

With version `2.0.0` one can now also define XWPF and XSSF data structures:

```java
package myreportingapp;

import static com.docutools.poipath.xssf.XSSFWorkbookWrapper.wrap;
import static com.docutools.poipath.xssf.XSSFBuilder.buildWorkbook;
import static com.docutools.poipath.xwpf.XWPFDocumentWrapper.wrap;
import static com.docutools.poipath.xwpf.XWPFBuilder.buildDocument;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import java.util.Objects;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class CreateTestDocuments {

@Test
@DisplayName("Modify XSSF cell")
void modifyCell() {
// Arrange
var red = IndexedColors.RED.getIndex();

// Act
var workbook = buildWorkbook()
.sheet()
.row(0)
.cell(0)
.value("Hello, World!", String.class)
.modify(cell -> {
var cellStyle = cell.getCellStyle();
if(cellStyle == null)
cellStyle = cell.getSheet().getWorkbook().createCellStyle();
cellStyle.setFillForegroundColor(red);
cell.setCellStyle(cellStyle);
})
.build();

// Assert
assertThat(wrap(workbook).sheet(0).row(0).cell(0).cellStyle().getFillForegroundColor(), is(red));
}

@Test
@DisplayName("Modify XWPF paragraph.")
void modifyParagraph() {
// Act
var document = buildDocument()
.paragraph()
.run("Hello, World!")
.modify(paragraph -> {
paragraph.setAlignment(ParagraphAlignment.CENTER);
})
.end()
.build();

// Assert
assertThat(Objects.requireNonNull(wrap(document).bodyElement(0).asParagraph()).paragraph().getAlignment(), is(ParagraphAlignment.CENTER));
}

}

```

## Feature Overview

### XSSF
Expand All @@ -55,6 +123,7 @@ class TestReports {
- [ ] Pictures or diagrams
- [ ] Header/footer
- [ ] Document/page settings
- [x] Define XSSF Datastructures

### XWPF

Expand All @@ -65,4 +134,5 @@ class TestReports {
- [ ] Header/footer
- [ ] Document/page settings
- [ ] Footer notes
- [ ] Table of contents
- [ ] Table of contents
- [x] Define XWPF Datastructures
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.1.6'
version = '2.0.0'
sourceCompatibility = 17
targetCompatibility = 17

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/docutools/poipath/xssf/CellWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;

Expand Down Expand Up @@ -67,4 +68,8 @@ public ZonedDateTime zonedDateTime() {
var date = cell.getDateCellValue();
return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}

public CellStyle cellStyle() {
return cell.getCellStyle();
}
}
128 changes: 128 additions & 0 deletions src/main/java/com/docutools/poipath/xssf/XSSFBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.docutools.poipath.xssf;

import java.lang.reflect.InvocationTargetException;
import java.util.function.Consumer;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
* Provides a simple builder pattern for defining XSSF data structures.
*
* @param <T> the XSSF type {@link XSSFWorkbook}, {@link XSSFSheet}, {@link XSSFRow}, ...
*/
public record XSSFBuilder<T>(XSSFBuilder<?> parent, T bodyElement) {

/**
* Gets the final {@link XSSFWorkbook}.
*
* @return {@link XSSFWorkbook}
*/
public XSSFWorkbook build() {
if (bodyElement instanceof XSSFWorkbook workbook) {
return workbook;
} else if (bodyElement instanceof XSSFSheet sheet) {
return sheet.getWorkbook();
} else if (bodyElement instanceof XSSFRow row) {
return row.getSheet().getWorkbook();
} else if (bodyElement instanceof XSSFCell cell) {
return cell.getSheet().getWorkbook();
}
throw new UnsupportedOperationException("Cannot get XSSFWorkbook from <%s>, call .end() to hit an upper hierarchy.".formatted(bodyElement));
}

/**
* Initializes a new {@link XSSFBuilder} for an empty {@link XSSFWorkbook}.
*
* @return {@link XSSFBuilder}
*/
public static XSSFBuilder<XSSFWorkbook> buildWorkbook() {
var workbook = new XSSFWorkbook();
return new XSSFBuilder<>(null, workbook);
}

/**
* Returns the {@link XSSFBuilder} for the XSSF element a hierarchy level above.
*
* @return {@link XSSFBuilder} or {@code null} when it's a {@link XSSFWorkbook}
*/
public XSSFBuilder<?> end() {
return parent;
}

/**
* Applies a given function on the XSSF element.
*
* @return {@code this}
*/
public XSSFBuilder<T> modify(Consumer<T> consumer) {
consumer.accept(bodyElement);
return this;
}

/**
* Creates a new {@link XSSFSheet} in the {@link XSSFWorkbook}.
*
* @return {@link XSSFBuilder} for {@link XSSFSheet}
*/
public XSSFBuilder<XSSFSheet> sheet() {
if (bodyElement instanceof XSSFWorkbook workbook) {
return new XSSFBuilder<>(this, workbook.createSheet());
}
throw isUnsupported(XSSFSheet.class);
}

/**
* Creates a new {@link XSSFRow}.
*
* @param number the row number, starting at 0
* @return the {@link XSSFBuilder} for {@link XSSFRow}
*/
public XSSFBuilder<XSSFRow> row(int number) {
if (bodyElement instanceof XSSFSheet sheet) {
return new XSSFBuilder<>(this, sheet.createRow(number));
}
throw isUnsupported(XSSFRow.class);
}

/**
* Creates a new {@link XSSFCell}.
*
* @param index the cell index, starting at 0
* @return the {@link XSSFBuilder} for {@link XSSFCell}
*/
public XSSFBuilder<XSSFCell> cell(int index) {
if (bodyElement instanceof XSSFRow row) {
return new XSSFBuilder<>(this, row.createCell(index));
}
throw isUnsupported(XSSFCell.class);
}

/**
* Tries to insert the given value into the {@link XSSFCell}.
*
* @param content the cell value
* @param clazz cell value Java type
* @param <V> cell value java type
* @return {@code this}
*/
public <V> XSSFBuilder<T> value(V content, Class<V> clazz) {
if (bodyElement instanceof XSSFCell cell) {
try {
var method = XSSFCell.class.getMethod("setCellValue", clazz);
method.invoke(cell, content);
return this;
} catch (NoSuchMethodException ignored) {
throw isUnsupported(clazz);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new UnsupportedOperationException("Ran into Exception when calling setCellValue(%s)".formatted(clazz), e);
}
}
throw isUnsupported(String.class);
}

private RuntimeException isUnsupported(Class<?> unsupportedType) {
return new UnsupportedOperationException("Cannot add <%s> to <%s>".formatted(unsupportedType.getName(), bodyElement.getClass().getName()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ public int numberOfSheets() {
return workbook.getNumberOfSheets();
}

public static XSSFWorkbookWrapper wrap(XSSFWorkbook workbook) {
return new XSSFWorkbookWrapper(workbook);
}

}
Loading

0 comments on commit 07937c0

Please sign in to comment.