PlaceholderHooker.java

1
package pro.verron.officestamper.api;
2
3
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
4
import org.docx4j.utils.TraversalUtilVisitor;
5
import org.docx4j.wml.P;
6
import pro.verron.officestamper.utils.wml.WmlUtils;
7
8
import java.util.ArrayList;
9
import java.util.List;
10
import java.util.regex.Pattern;
11
12
import static pro.verron.officestamper.utils.wml.WmlUtils.asString;
13
import static pro.verron.officestamper.utils.wml.WmlUtils.insertSmartTag;
14
15
/// The [PlaceholderHooker] class is a pre-processor that prepares inline
16
/// placeholders in a [WordprocessingMLPackage]
17
/// document. It searches for placeholders that match a given pattern and wraps
18
/// them with a specified XML element to
19
/// ensure proper processing by the OfficeStamper engine.
20
///
21
/// This pre-processor is typically used to identify and mark inline expressions
22
/// within paragraphs, making them
23
/// recognizable for subsequent processing steps.
24
public class PlaceholderHooker
25
        implements PreProcessor {
26
27
    private final Pattern pattern;
28
    private final String element;
29
30
31
    /// Constructs a new [PlaceholderHooker] instance with the specified regular
32
    /// expression and XML element
33
    /// name.
34
    ///
35
    /// @param regex   the regular expression pattern used to identify inline
36
    /// placeholders in the document. This
37
    ///         pattern should contain at least two capturing groups where the
38
    /// second group represents the actual
39
    ///         placeholder content.
40
    /// @param element the name of the XML element to wrap around identified
41
    /// placeholders. This element will be
42
    ///         used to mark the placeholders for further processing.
43
    public PlaceholderHooker(String regex, String element) {
44
        this(Pattern.compile(regex, Pattern.DOTALL), element);
45
    }
46
47
48
    /// Constructs a new [PlaceholderHooker] instance with the specified pattern
49
    /// and XML element name.
50
    ///
51
    /// @param pattern the compiled regular expression pattern used to identify
52
    /// inline placeholders in the
53
    ///         document. This pattern should contain at least two capturing
54
    /// groups where the second group represents
55
    ///         the actual placeholder content.
56
    /// @param element the name of the XML element to wrap around identified
57
    /// placeholders. This element will be
58
    ///         used to mark the placeholders for further processing.
59
    public PlaceholderHooker(Pattern pattern, String element) {
60
        this.pattern = pattern;
61
        this.element = element;
62
    }
63
64
    @Override
65
    public void process(WordprocessingMLPackage document) {
66
        var visitor = new ParagraphCollector(pattern);
67 1 1. process : removed call to pro/verron/officestamper/utils/wml/WmlUtils::visitDocument → KILLED
        WmlUtils.visitDocument(document, visitor);
68
        for (var paragraph : visitor.paragraphs()) {
69
            var string = asString(paragraph);
70
            var matcher = pattern.matcher(string);
71
            // Iterates matches; replaces placeholder with a smart tag
72 1 1. process : negated conditional → KILLED
            while (matcher.find()) {
73
                var start = matcher.start(1);
74
                var end = matcher.end(1);
75
                var placeholder = matcher.group(2);
76
                var newContent = insertSmartTag(element,
77
                        paragraph,
78
                        placeholder,
79
                        start,
80
                        end);
81
                var content = paragraph.getContent();
82 1 1. process : removed call to java/util/List::clear → KILLED
                content.clear();
83
                content.addAll(newContent);
84
                string = asString(paragraph);
85
                matcher = pattern.matcher(string);
86
            }
87
        }
88
    }
89
90
    /// A [TraversalUtilVisitor] implementation that collects paragraphs
91
    /// matching a given pattern.
92
    ///
93
    /// This class is used to traverse a document and collect all paragraph
94
    /// elements ([P]) that match a specified
95
    /// regular expression pattern. The collected paragraphs can be retrieved
96
    /// using the [#paragraphs()] method.
97
    public static class ParagraphCollector
98
            extends TraversalUtilVisitor<P> {
99
100
        private final Pattern pattern;
101
        private final List<P> results = new ArrayList<>();
102
103
104
        /// Constructs a new [ParagraphCollector] with the specified pattern.
105
        ///
106
        /// @param pattern the regular expression pattern to match against
107
        /// paragraphs
108
        public ParagraphCollector(Pattern pattern) {
109
            this.pattern = pattern;
110
        }
111
112
        @Override
113
        public void apply(P element) {
114
            var matcher = pattern.asPredicate();
115
            var string = asString(element);
116 1 1. apply : negated conditional → KILLED
            if (matcher.test(string)) {
117
                results.add(element);
118
            }
119
        }
120
121
        /// Returns the list of collected paragraphs that matched the pattern.
122
        ///
123
        /// @return an unmodifiable list of paragraphs matching the specified
124
        ///  pattern
125
        public List<P> paragraphs() {
126 1 1. paragraphs : replaced return value with Collections.emptyList for pro/verron/officestamper/api/PlaceholderHooker$ParagraphCollector::paragraphs → KILLED
            return results;
127
        }
128
    }
129
}

Mutations

67

1.1
Location : process
Killed by : pro.verron.officestamper.test.PlaceholderPreprocessorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.PlaceholderPreprocessorTest]/[method:process()]
removed call to pro/verron/officestamper/utils/wml/WmlUtils::visitDocument → KILLED

72

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

82

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

116

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

126

1.1
Location : paragraphs
Killed by : pro.verron.officestamper.test.PlaceholderPreprocessorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.PlaceholderPreprocessorTest]/[method:process()]
replaced return value with Collections.emptyList for pro/verron/officestamper/api/PlaceholderHooker$ParagraphCollector::paragraphs → KILLED

Active mutators

Tests examined


Report generated by PIT 1.25.5 support