1 | package pro.verron.officestamper.preset.processors.repeat; | |
2 | ||
3 | import org.docx4j.TraversalUtil; | |
4 | import org.docx4j.XmlUtils; | |
5 | import org.docx4j.finders.ClassFinder; | |
6 | import org.docx4j.openpackaging.packages.WordprocessingMLPackage; | |
7 | import org.docx4j.wml.Comments; | |
8 | import org.docx4j.wml.P; | |
9 | import org.docx4j.wml.Tbl; | |
10 | import org.docx4j.wml.Tr; | |
11 | import org.springframework.lang.Nullable; | |
12 | import pro.verron.officestamper.api.*; | |
13 | import pro.verron.officestamper.core.CommentUtil; | |
14 | import pro.verron.officestamper.core.StandardParagraph; | |
15 | import pro.verron.officestamper.preset.CommentProcessorFactory; | |
16 | ||
17 | import java.math.BigInteger; | |
18 | import java.util.ArrayList; | |
19 | import java.util.HashMap; | |
20 | import java.util.List; | |
21 | import java.util.Map; | |
22 | import java.util.function.BiFunction; | |
23 | ||
24 | import static java.util.Collections.emptyList; | |
25 | import static java.util.Objects.requireNonNull; | |
26 | ||
27 | /** | |
28 | * Repeats a table row for each element in a list. | |
29 | * | |
30 | * @author Joseph Verron | |
31 | * @author Tom Hombergs | |
32 | * @version ${version} | |
33 | * @since 1.0.0 | |
34 | */ | |
35 | public class RepeatProcessor | |
36 | extends AbstractCommentProcessor | |
37 | implements CommentProcessorFactory.IRepeatProcessor { | |
38 | ||
39 | private final BiFunction<WordprocessingMLPackage, Tr, List<Tr>> nullSupplier; | |
40 | private Map<Tr, Iterable<Object>> tableRowsToRepeat = new HashMap<>(); | |
41 | private Map<Tr, Comment> tableRowsCommentsToRemove = new HashMap<>(); | |
42 | ||
43 | private RepeatProcessor( | |
44 | ParagraphPlaceholderReplacer placeholderReplacer, | |
45 | BiFunction<WordprocessingMLPackage, Tr, List<Tr>> nullSupplier1 | |
46 | ) { | |
47 | super(placeholderReplacer); | |
48 | nullSupplier = nullSupplier1; | |
49 | } | |
50 | ||
51 | /** | |
52 | * Creates a new RepeatProcessor. | |
53 | * | |
54 | * @param pr The PlaceholderReplacer to use. | |
55 | * | |
56 | * @return A new RepeatProcessor. | |
57 | */ | |
58 | public static CommentProcessor newInstance(ParagraphPlaceholderReplacer pr) { | |
59 |
1
1. newInstance : replaced return value with null for pro/verron/officestamper/preset/processors/repeat/RepeatProcessor::newInstance → KILLED |
return new RepeatProcessor(pr, (document, row) -> emptyList()); |
60 | } | |
61 | ||
62 | /** {@inheritDoc} */ | |
63 | @Override public void commitChanges(DocxPart source) { | |
64 |
1
1. commitChanges : removed call to pro/verron/officestamper/preset/processors/repeat/RepeatProcessor::repeatRows → KILLED |
repeatRows(source); |
65 | } | |
66 | ||
67 | private void repeatRows(DocxPart source) { | |
68 | for (Map.Entry<Tr, Iterable<Object>> entry : tableRowsToRepeat.entrySet()) { | |
69 | Tr row = entry.getKey(); | |
70 | Iterable<Object> expressionContexts = entry.getValue(); | |
71 | ||
72 | Tbl table = (Tbl) XmlUtils.unwrap(row.getParent()); | |
73 | var content = table.getContent(); | |
74 | int index = content.indexOf(row); | |
75 | content.remove(row); | |
76 | ||
77 | List<Tr> changes; | |
78 |
1
1. repeatRows : negated conditional → KILLED |
if (expressionContexts == null) { |
79 | changes = nullSupplier.apply(source.document(), row); | |
80 | } | |
81 | else { | |
82 | changes = new ArrayList<>(); | |
83 | for (Object expressionContext : expressionContexts) { | |
84 | Tr rowClone = XmlUtils.deepCopy(row); | |
85 | Comment commentWrapper = requireNonNull(tableRowsCommentsToRemove.get(row)); | |
86 | Comments.Comment comment = requireNonNull(commentWrapper.getComment()); | |
87 | BigInteger commentId = comment.getId(); | |
88 |
1
1. repeatRows : removed call to pro/verron/officestamper/core/CommentUtil::deleteCommentFromElements → KILLED |
CommentUtil.deleteCommentFromElements(rowClone.getContent(), commentId); |
89 | var classFinder = new ClassFinder(P.class); | |
90 |
1
1. repeatRows : removed call to org/docx4j/TraversalUtil::visit → KILLED |
TraversalUtil.visit(rowClone, classFinder); |
91 | var objects = classFinder.results; | |
92 | for (Object object : objects) { | |
93 | P result = (P) object; | |
94 | StandardParagraph paragraph = StandardParagraph.from(source, result); | |
95 |
1
1. repeatRows : removed call to pro/verron/officestamper/api/ParagraphPlaceholderReplacer::resolveExpressionsForParagraph → KILLED |
placeholderReplacer.resolveExpressionsForParagraph(source, paragraph, expressionContext); |
96 | } | |
97 | changes.add(rowClone); | |
98 | } | |
99 | } | |
100 | content.addAll(index, changes); | |
101 | } | |
102 | } | |
103 | ||
104 | /** {@inheritDoc} */ | |
105 | @Override public void reset() { | |
106 | this.tableRowsToRepeat = new HashMap<>(); | |
107 | this.tableRowsCommentsToRemove = new HashMap<>(); | |
108 | } | |
109 | ||
110 | /** {@inheritDoc} */ | |
111 | @Override public void repeatTableRow(@Nullable Iterable<Object> objects) { | |
112 | var tr = this.getParagraph() | |
113 | .parent(Tr.class) | |
114 | .orElseThrow(OfficeStamperException.throwing("This paragraph is not in a table row.")); | |
115 | tableRowsToRepeat.put(tr, objects); | |
116 | tableRowsCommentsToRemove.put(tr, getCurrentCommentWrapper()); | |
117 | } | |
118 | ||
119 | } | |
Mutations | ||
59 |
1.1 |
|
64 |
1.1 |
|
78 |
1.1 |
|
88 |
1.1 |
|
90 |
1.1 |
|
95 |
1.1 |