TableResolver.java

1
package pro.verron.officestamper.preset.processors.table;
2
3
import jakarta.xml.bind.JAXBElement;
4
import org.docx4j.XmlUtils;
5
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
6
import org.docx4j.wml.ContentAccessor;
7
import org.docx4j.wml.Tbl;
8
import org.docx4j.wml.Tc;
9
import org.docx4j.wml.Tr;
10
import org.springframework.lang.Nullable;
11
import pro.verron.officestamper.api.*;
12
import pro.verron.officestamper.core.PlaceholderReplacer;
13
import pro.verron.officestamper.preset.CommentProcessorFactory;
14
import pro.verron.officestamper.preset.StampTable;
15
import pro.verron.officestamper.utils.WmlFactory;
16
17
import java.util.Collections;
18
import java.util.HashMap;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.function.Function;
22
23
import static pro.verron.officestamper.api.OfficeStamperException.throwing;
24
25
/**
26
 * TableResolver class.
27
 *
28
 * @author Joseph Verron
29
 * @version ${version}
30
 * @since 1.6.2
31
 */
32
public class TableResolver
33
        extends AbstractCommentProcessor
34
        implements CommentProcessorFactory.ITableResolver {
35
    private final Map<Tbl, StampTable> cols = new HashMap<>();
36
    private final Function<Tbl, List<Object>> nullSupplier;
37
38
    private TableResolver(
39
            ParagraphPlaceholderReplacer placeholderReplacer, Function<Tbl, List<Object>> nullSupplier
40
    ) {
41
        super(placeholderReplacer);
42
        this.nullSupplier = nullSupplier;
43
    }
44
45
    /**
46
     * Generate a new {@link TableResolver} instance where value is replaced by an empty list when <code>null</code>
47
     *
48
     * @param pr a {@link PlaceholderReplacer} instance
49
     *
50
     * @return a new {@link TableResolver} instance
51
     */
52
    public static CommentProcessor newInstance(ParagraphPlaceholderReplacer pr) {
53 1 1. newInstance : replaced return value with null for pro/verron/officestamper/preset/processors/table/TableResolver::newInstance → KILLED
        return new TableResolver(pr, table -> Collections.emptyList());
54
    }
55
56
    /**
57
     * {@inheritDoc}
58
     */
59
    @Override public void resolveTable(@Nullable StampTable givenTable) {
60
        var tbl = this.getParagraph()
61
                      .parent(Tbl.class)
62
                      .orElseThrow(throwing("Paragraph is not within a table!"));
63
        cols.put(tbl, givenTable);
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    @Override public void commitChanges(DocxPart document) {
70
        for (Map.Entry<Tbl, StampTable> entry : cols.entrySet()) {
71
            Tbl wordTable = entry.getKey();
72
73
            StampTable stampedTable = entry.getValue();
74
75 1 1. commitChanges : negated conditional → KILLED
            if (stampedTable != null) {
76 1 1. commitChanges : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::replaceTableInplace → KILLED
                replaceTableInplace(wordTable, stampedTable);
77
            }
78
            else {
79
                List<Object> tableParentContent = ((ContentAccessor) wordTable.getParent()).getContent();
80
                int tablePosition = tableParentContent.indexOf(wordTable);
81
                List<Object> toInsert = nullSupplier.apply(wordTable);
82
                tableParentContent.set(tablePosition, toInsert);
83
            }
84
        }
85
    }
86
87
    @Override public void commitChanges(WordprocessingMLPackage document) {
88
        throw new OfficeStamperException("Should not be called, since deprecation");
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94
    @Override public void reset() {
95 1 1. reset : removed call to java/util/Map::clear → KILLED
        cols.clear();
96
    }
97
98
    private void replaceTableInplace(Tbl wordTable, StampTable stampedTable) {
99
        var headers = stampedTable.headers();
100
101
        var rows = wordTable.getContent();
102
        var headerRow = (Tr) rows.get(0);
103
        var firstDataRow = (Tr) rows.get(1);
104
105 1 1. replaceTableInplace : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::growAndFillRow → KILLED
        growAndFillRow(headerRow, headers);
106
107 1 1. replaceTableInplace : negated conditional → KILLED
        if (stampedTable.isEmpty()) rows.remove(firstDataRow);
108
        else {
109 1 1. replaceTableInplace : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::growAndFillRow → KILLED
            growAndFillRow(firstDataRow, stampedTable.getFirst());
110
            for (var rowContent : stampedTable.subList(1, stampedTable.size()))
111
                rows.add(copyRowFromTemplate(firstDataRow, rowContent));
112
        }
113
    }
114
115
    private void growAndFillRow(Tr row, List<String> values) {
116
        List<Object> cellRowContent = row.getContent();
117
118
        //Replace text in first cell
119
        JAXBElement<Tc> cell0 = (JAXBElement<Tc>) cellRowContent.getFirst();
120
        Tc cell0tc = cell0.getValue();
121 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());
122
123 2 1. growAndFillRow : changed conditional boundary → SURVIVED
2. growAndFillRow : negated conditional → KILLED
        if (values.size() > 1) {
124
            //Copy the first cell and replace content for each remaining value
125
            for (String cellContent : values.subList(1, values.size())) {
126
                JAXBElement<Tc> xmlCell = XmlUtils.deepCopy(cell0);
127 1 1. growAndFillRow : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED
                setCellText(xmlCell.getValue(), cellContent);
128
                cellRowContent.add(xmlCell);
129
            }
130
        }
131
    }
132
133
    private Tr copyRowFromTemplate(Tr firstDataRow, List<String> rowContent) {
134
        Tr newXmlRow = XmlUtils.deepCopy(firstDataRow);
135
        List<Object> xmlRow = newXmlRow.getContent();
136 2 1. copyRowFromTemplate : negated conditional → KILLED
2. copyRowFromTemplate : changed conditional boundary → KILLED
        for (int i = 0; i < rowContent.size(); i++) {
137
            String cellContent = rowContent.get(i);
138
            Tc xmlCell = ((JAXBElement<Tc>) xmlRow.get(i)).getValue();
139 1 1. copyRowFromTemplate : removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED
            setCellText(xmlCell, cellContent);
140
        }
141 1 1. copyRowFromTemplate : replaced return value with null for pro/verron/officestamper/preset/processors/table/TableResolver::copyRowFromTemplate → KILLED
        return newXmlRow;
142
    }
143
144
    private void setCellText(Tc tableCell, String content) {
145
        var tableCellContent = tableCell.getContent();
146 1 1. setCellText : removed call to java/util/List::clear → KILLED
        tableCellContent.clear();
147
        tableCellContent.add(WmlFactory.newParagraph(new String[]{content}));
148
    }
149
}

Mutations

53

1.1
Location : newInstance
Killed by : pro.verron.officestamper.test.DefaultTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DefaultTests]/[test-template:features(java.lang.String, pro.verron.officestamper.api.OfficeStamperConfiguration, java.lang.Object, java.io.InputStream, java.lang.String)]/[test-template-invocation:#34]
replaced return value with null for pro/verron/officestamper/preset/processors/table/TableResolver::newInstance → KILLED

75

1.1
Location : commitChanges
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
negated conditional → KILLED

76

1.1
Location : commitChanges
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to pro/verron/officestamper/preset/processors/table/TableResolver::replaceTableInplace → KILLED

95

1.1
Location : reset
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to java/util/Map::clear → KILLED

105

1.1
Location : replaceTableInplace
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to pro/verron/officestamper/preset/processors/table/TableResolver::growAndFillRow → KILLED

107

1.1
Location : replaceTableInplace
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
negated conditional → KILLED

109

1.1
Location : replaceTableInplace
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to pro/verron/officestamper/preset/processors/table/TableResolver::growAndFillRow → KILLED

121

1.1
Location : growAndFillRow
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED

2.2
Location : growAndFillRow
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
negated conditional → KILLED

123

1.1
Location : growAndFillRow
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
negated conditional → KILLED

2.2
Location : growAndFillRow
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

127

1.1
Location : growAndFillRow
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED

136

1.1
Location : copyRowFromTemplate
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
negated conditional → KILLED

2.2
Location : copyRowFromTemplate
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
changed conditional boundary → KILLED

139

1.1
Location : copyRowFromTemplate
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to pro/verron/officestamper/preset/processors/table/TableResolver::setCellText → KILLED

141

1.1
Location : copyRowFromTemplate
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
replaced return value with null for pro/verron/officestamper/preset/processors/table/TableResolver::copyRowFromTemplate → KILLED

146

1.1
Location : setCellText
Killed by : pro.verron.officestamper.test.StampTableTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.StampTableTest]/[method:stampTableTest()]
removed call to java/util/List::clear → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.1