| 1 | package pro.verron.officestamper.preset.processors.table; | |
| 2 | ||
| 3 | import jakarta.xml.bind.JAXBElement; | |
| 4 | import org.docx4j.XmlUtils; | |
| 5 | import org.docx4j.wml.ContentAccessor; | |
| 6 | import org.docx4j.wml.Tbl; | |
| 7 | import org.docx4j.wml.Tc; | |
| 8 | import org.docx4j.wml.Tr; | |
| 9 | import org.jspecify.annotations.Nullable; | |
| 10 | import pro.verron.officestamper.api.CommentProcessor; | |
| 11 | import pro.verron.officestamper.api.ProcessorContext; | |
| 12 | import pro.verron.officestamper.preset.CommentProcessorFactory; | |
| 13 | import pro.verron.officestamper.preset.StampTable; | |
| 14 | import pro.verron.officestamper.utils.wml.WmlFactory; | |
| 15 | ||
| 16 | import java.util.List; | |
| 17 | ||
| 18 | import static pro.verron.officestamper.api.OfficeStamperException.throwing; | |
| 19 | ||
| 20 | /// TableResolver class. | |
| 21 | /// | |
| 22 | /// @author Joseph Verron | |
| 23 | /// @version ${version} | |
| 24 | /// @since 1.6.2 | |
| 25 | public class TableResolver | |
| 26 | extends CommentProcessor | |
| 27 | implements CommentProcessorFactory.ITableResolver { | |
| 28 | ||
| 29 | /// Constructs a new TableResolver with the given processor context. | |
| 30 | /// | |
| 31 | /// @param processorContext the context in which this processor operates | |
| 32 | public TableResolver(ProcessorContext processorContext) { | |
| 33 | super(processorContext); | |
| 34 | } | |
| 35 | ||
| 36 | @Override | |
| 37 | public void resolveTable(@Nullable StampTable givenTable) { | |
| 38 | var tbl = paragraph().parent(Tbl.class) | |
| 39 | .orElseThrow(throwing("Paragraph is not within a table!")); | |
| 40 |
1
1. resolveTable : negated conditional → KILLED |
if (givenTable != null) { |
| 41 |
1
1. resolveTable : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::replaceTableInplace → KILLED |
replaceTableInplace(tbl, givenTable); |
| 42 | } | |
| 43 | else { | |
| 44 | List<Object> tableParentContent = ((ContentAccessor) tbl.getParent()).getContent(); | |
| 45 | tableParentContent.remove(tbl); | |
| 46 | } | |
| 47 | } | |
| 48 | ||
| 49 | private void replaceTableInplace(Tbl wordTable, StampTable stampedTable) { | |
| 50 | var headers = stampedTable.headers(); | |
| 51 | ||
| 52 | var rows = wordTable.getContent(); | |
| 53 | var headerRow = (Tr) rows.get(0); | |
| 54 | var firstDataRow = (Tr) rows.get(1); | |
| 55 | ||
| 56 |
1
1. replaceTableInplace : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::growAndFillRow → KILLED |
growAndFillRow(headerRow, headers); |
| 57 | ||
| 58 |
1
1. replaceTableInplace : negated conditional → KILLED |
if (stampedTable.isEmpty()) rows.remove(firstDataRow); |
| 59 | else { | |
| 60 |
1
1. replaceTableInplace : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::growAndFillRow → KILLED |
growAndFillRow(firstDataRow, stampedTable.getFirst()); |
| 61 | for (var rowContent : stampedTable.subList(1, stampedTable.size())) | |
| 62 | rows.add(copyRowFromTemplate(firstDataRow, rowContent)); | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 66 | private void growAndFillRow(Tr row, List<String> values) { | |
| 67 | List<Object> cellRowContent = row.getContent(); | |
| 68 | ||
| 69 | //Replace text in first cell | |
| 70 | JAXBElement<Tc> cell0 = (JAXBElement<Tc>) cellRowContent.getFirst(); | |
| 71 | Tc cell0tc = cell0.getValue(); | |
| 72 |
2
1. growAndFillRow : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED 2. growAndFillRow : negated conditional → KILLED |
setCellText(cell0tc, values.isEmpty() ? "" : values.getFirst()); |
| 73 | ||
| 74 |
2
1. growAndFillRow : changed conditional boundary → SURVIVED 2. growAndFillRow : negated conditional → KILLED |
if (values.size() > 1) { |
| 75 | //Copy the first cell and replace content for each remaining value | |
| 76 | for (String cellContent : values.subList(1, values.size())) { | |
| 77 | JAXBElement<Tc> xmlCell = XmlUtils.deepCopy(cell0); | |
| 78 |
1
1. growAndFillRow : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED |
setCellText(xmlCell.getValue(), cellContent); |
| 79 | cellRowContent.add(xmlCell); | |
| 80 | } | |
| 81 | } | |
| 82 | } | |
| 83 | ||
| 84 | private Tr copyRowFromTemplate(Tr firstDataRow, List<String> rowContent) { | |
| 85 | Tr newXmlRow = XmlUtils.deepCopy(firstDataRow); | |
| 86 | List<Object> xmlRow = newXmlRow.getContent(); | |
| 87 |
2
1. copyRowFromTemplate : negated conditional → KILLED 2. copyRowFromTemplate : changed conditional boundary → KILLED |
for (int i = 0; i < rowContent.size(); i++) { |
| 88 | String cellContent = rowContent.get(i); | |
| 89 | Tc xmlCell = ((JAXBElement<Tc>) xmlRow.get(i)).getValue(); | |
| 90 |
1
1. copyRowFromTemplate : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED |
setCellText(xmlCell, cellContent); |
| 91 | } | |
| 92 |
1
1. copyRowFromTemplate : replaced return value with null for pro/verron/officestamper/preset/processors/table/TableResolver::copyRowFromTemplate → KILLED |
return newXmlRow; |
| 93 | } | |
| 94 | ||
| 95 | private void setCellText(Tc tableCell, String content) { | |
| 96 | var tableCellContent = tableCell.getContent(); | |
| 97 |
1
1. setCellText : removed call to java/util/List::clear → KILLED |
tableCellContent.clear(); |
| 98 | tableCellContent.add(WmlFactory.newParagraph(content)); | |
| 99 | } | |
| 100 | } | |
Mutations | ||
| 40 |
1.1 |
|
| 41 |
1.1 |
|
| 56 |
1.1 |
|
| 58 |
1.1 |
|
| 60 |
1.1 |
|
| 72 |
1.1 2.2 |
|
| 74 |
1.1 2.2 |
|
| 78 |
1.1 |
|
| 87 |
1.1 2.2 |
|
| 90 |
1.1 |
|
| 92 |
1.1 |
|
| 97 |
1.1 |