WmlUtils.java

1
package pro.verron.officestamper.utils.wml;
2
3
import jakarta.xml.bind.JAXBElement;
4
import org.docx4j.TraversalUtil;
5
import org.docx4j.finders.CommentFinder;
6
import org.docx4j.model.structure.HeaderFooterPolicy;
7
import org.docx4j.model.structure.SectionWrapper;
8
import org.docx4j.model.styles.StyleUtil;
9
import org.docx4j.openpackaging.exceptions.Docx4JException;
10
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
11
import org.docx4j.openpackaging.parts.JaxbXmlPart;
12
import org.docx4j.openpackaging.parts.WordprocessingML.CommentsPart;
13
import org.docx4j.utils.TraversalUtilVisitor;
14
import org.docx4j.vml.CTShadow;
15
import org.docx4j.vml.CTTextbox;
16
import org.docx4j.vml.VmlShapeElements;
17
import org.docx4j.wml.*;
18
import org.docx4j.wml.Comments.Comment;
19
import org.jspecify.annotations.Nullable;
20
import org.jvnet.jaxb2_commons.ppp.Child;
21
import org.slf4j.Logger;
22
import org.slf4j.LoggerFactory;
23
import pro.verron.officestamper.utils.UtilsException;
24
import pro.verron.officestamper.utils.openpackaging.OpenpackagingFactory;
25
26
import java.math.BigInteger;
27
import java.util.*;
28
import java.util.function.Consumer;
29
import java.util.function.Predicate;
30
import java.util.stream.Stream;
31
32
import static java.util.Collections.emptyList;
33
import static java.util.Optional.empty;
34
import static java.util.Optional.ofNullable;
35
import static java.util.stream.Collectors.joining;
36
import static org.docx4j.XmlUtils.unwrap;
37
import static pro.verron.officestamper.utils.wml.WmlFactory.*;
38
39
/// Utility class with methods to help in the interaction with [WordprocessingMLPackage] documents and their elements,
40
/// such as comments, parents, and child elements.
41
public final class WmlUtils {
42
43
    private static final String PRESERVE = "preserve";
44
    private static final Logger log = LoggerFactory.getLogger(WmlUtils.class);
45
46
    private WmlUtils() {
47
        throw new UtilsException("Utility class shouldn't be instantiated");
48
    }
49
50
    /// Attempts to find the first parent of a given child element that is an instance of the specified class within the
51
    /// defined search depth.
52
    ///
53
    /// @param child the [Child] element from which the search for a parent begins.
54
    /// @param clazz the [Class] type to match for the parent
55
    /// @param depth the maximum amount levels to traverse up the parent hierarchy
56
    /// @param <T> the type of the parent class to search for
57
    ///
58
    /// @return an [Optional] containing the first parent matching the specified class, or an empty [Optional] if no
59
    ///         match found.
60
    public static <T> Optional<T> getFirstParentWithClass(Child child, Class<T> clazz, int depth) {
61
        var parent = child.getParent();
62
        var currentDepth = 0;
63 2 1. getFirstParentWithClass : changed conditional boundary → NO_COVERAGE
2. getFirstParentWithClass : negated conditional → NO_COVERAGE
        while (currentDepth <= depth) {
64 1 1. getFirstParentWithClass : Changed increment from 1 to -1 → NO_COVERAGE
            currentDepth++;
65 1 1. getFirstParentWithClass : negated conditional → NO_COVERAGE
            if (parent == null) return empty();
66 2 1. getFirstParentWithClass : replaced return value with Optional.empty for pro/verron/officestamper/utils/wml/WmlUtils::getFirstParentWithClass → NO_COVERAGE
2. getFirstParentWithClass : negated conditional → NO_COVERAGE
            if (clazz.isInstance(parent)) return Optional.of(clazz.cast(parent));
67 1 1. getFirstParentWithClass : negated conditional → NO_COVERAGE
            if (parent instanceof Child next) parent = next.getParent();
68
        }
69
        return empty();
70
    }
71
72
    /// Extracts a list of comment elements from the specified [WordprocessingMLPackage] document.
73
    ///
74
    /// @param document the [WordprocessingMLPackage] document from which to extract comment elements
75
    ///
76
    /// @return a list of [Child] objects representing the extracted comment elements
77
    public static List<Child> extractCommentElements(WordprocessingMLPackage document) {
78
        var commentFinder = new CommentFinder();
79 1 1. extractCommentElements : removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE
        TraversalUtil.visit(document, true, commentFinder);
80 1 1. extractCommentElements : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::extractCommentElements → NO_COVERAGE
        return commentFinder.getCommentElements();
81
    }
82
83
    /// Finds a comment with the given ID in the specified [WordprocessingMLPackage] document.
84
    ///
85
    /// @param document the [WordprocessingMLPackage] document to search for the comment
86
    /// @param id the ID of the comment to find
87
    ///
88
    /// @return an [Optional] containing the [Comment] if found, or an empty [Optional] if not found.
89
    public static Optional<Comment> findComment(WordprocessingMLPackage document, BigInteger id) {
90
        var name = OpenpackagingFactory.newPartName("/word/comments.xml");
91
        var parts = document.getParts();
92
        var wordComments = (CommentsPart) parts.get(name);
93
        var comments = getComments(wordComments);
94 1 1. findComment : replaced return value with Optional.empty for pro/verron/officestamper/utils/wml/WmlUtils::findComment → NO_COVERAGE
        return comments.getComment()
95
                       .stream()
96
                       .filter(idEqual(id))
97
                       .findFirst();
98
    }
99
100
    private static Comments getComments(CommentsPart wordComments) {
101
        try {
102 1 1. getComments : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::getComments → NO_COVERAGE
            return wordComments.getContents();
103
        } catch (Docx4JException e) {
104
            throw new UtilsException(e);
105
        }
106
    }
107
108
    private static Predicate<Comment> idEqual(BigInteger id) {
109 1 1. idEqual : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::idEqual → NO_COVERAGE
        return comment -> {
110
            var commentId = comment.getId();
111 2 1. lambda$idEqual$0 : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$idEqual$0 → NO_COVERAGE
2. lambda$idEqual$0 : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$idEqual$0 → NO_COVERAGE
            return commentId.equals(id);
112
        };
113
    }
114
115
116
    /// Removes the specified child element from its parent container. Depending on the type of the parent element, the
117
    /// removal process is delegated to the appropriate helper method. If the child is contained within a table cell and
118
    /// the cell is empty after removal, an empty paragraph is added to the cell.
119
    ///
120
    /// @param child the [Child] element to be removed
121
    ///
122
    /// @throws UtilsException if the parent of the child element is of an unexpected type
123
    public static void remove(Child child) {
124
        switch (child.getParent()) {
125 1 1. remove : removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE
            case ContentAccessor parent -> remove(parent, child);
126 1 1. remove : removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE
            case CTFootnotes parent -> remove(parent, child);
127 1 1. remove : removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE
            case CTEndnotes parent -> remove(parent, child);
128 1 1. remove : removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE
            case SdtRun parent -> remove(parent, child);
129
            default -> throw new UtilsException("Unexpected value: " + child.getParent());
130
        }
131 2 1. remove : negated conditional → NO_COVERAGE
2. remove : removed call to pro/verron/officestamper/utils/wml/WmlUtils::ensureValidity → NO_COVERAGE
        if (child.getParent() instanceof Tc cell) ensureValidity(cell);
132
    }
133
134
    private static void remove(ContentAccessor parent, Child child) {
135
        var siblings = parent.getContent();
136
        var iterator = siblings.listIterator();
137 1 1. remove : negated conditional → NO_COVERAGE
        while (iterator.hasNext()) {
138 1 1. remove : negated conditional → NO_COVERAGE
            if (equals(iterator.next(), child)) {
139 1 1. remove : removed call to java/util/ListIterator::remove → NO_COVERAGE
                iterator.remove();
140
                break;
141
            }
142
        }
143
    }
144
145
    @SuppressWarnings("SuspiciousMethodCalls")
146
    private static void remove(CTFootnotes parent, Child child) {
147
        parent.getFootnote()
148
              .remove(child);
149
    }
150
151
    @SuppressWarnings("SuspiciousMethodCalls")
152
    private static void remove(CTEndnotes parent, Child child) {
153
        parent.getEndnote()
154
              .remove(child);
155
    }
156
157
    private static void remove(SdtRun parent, Child child) {
158
        parent.getSdtContent()
159
              .getContent()
160
              .remove(child);
161
    }
162
163
    /// Utility method to ensure the validity of a table cell by adding an empty paragraph if necessary.
164
    ///
165
    /// @param cell the [Tc] to be checked and updated.
166
    public static void ensureValidity(Tc cell) {
167 1 1. ensureValidity : negated conditional → NO_COVERAGE
        if (!containsAnElementOfAnyClasses(cell.getContent(), P.class, Tbl.class)) {
168 1 1. ensureValidity : removed call to pro/verron/officestamper/utils/wml/WmlUtils::addEmptyParagraph → NO_COVERAGE
            addEmptyParagraph(cell);
169
        }
170
    }
171
172
    private static boolean equals(Object o1, Object o2) {
173 1 1. equals : negated conditional → NO_COVERAGE
        if (o1 instanceof JAXBElement<?> e1) o1 = e1.getValue();
174 1 1. equals : negated conditional → NO_COVERAGE
        if (o2 instanceof JAXBElement<?> e2) o2 = e2.getValue();
175 2 1. equals : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::equals → NO_COVERAGE
2. equals : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::equals → NO_COVERAGE
        return Objects.equals(o1, o2);
176
    }
177
178
    private static boolean containsAnElementOfAnyClasses(Collection<Object> collection, Class<?>... classes) {
179 2 1. containsAnElementOfAnyClasses : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::containsAnElementOfAnyClasses → NO_COVERAGE
2. containsAnElementOfAnyClasses : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::containsAnElementOfAnyClasses → NO_COVERAGE
        return collection.stream()
180 2 1. lambda$containsAnElementOfAnyClasses$0 : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$containsAnElementOfAnyClasses$0 → NO_COVERAGE
2. lambda$containsAnElementOfAnyClasses$0 : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$containsAnElementOfAnyClasses$0 → NO_COVERAGE
                         .anyMatch(element -> isAnElementOfAnyClasses(element, classes));
181
    }
182
183
    private static void addEmptyParagraph(Tc cell) {
184
        var emptyParagraph = WmlFactory.newParagraph();
185
        var cellContent = cell.getContent();
186
        cellContent.add(emptyParagraph);
187
    }
188
189
    private static boolean isAnElementOfAnyClasses(Object element, Class<?>... classes) {
190
        for (var clazz : classes) {
191 2 1. isAnElementOfAnyClasses : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::isAnElementOfAnyClasses → NO_COVERAGE
2. isAnElementOfAnyClasses : negated conditional → NO_COVERAGE
            if (clazz.isInstance(unwrapJAXBElement(element))) return true;
192
        }
193 1 1. isAnElementOfAnyClasses : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::isAnElementOfAnyClasses → NO_COVERAGE
        return false;
194
    }
195
196
    private static Object unwrapJAXBElement(Object element) {
197 2 1. unwrapJAXBElement : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::unwrapJAXBElement → NO_COVERAGE
2. unwrapJAXBElement : negated conditional → NO_COVERAGE
        return element instanceof JAXBElement<?> jaxbElement ? jaxbElement.getValue() : element;
198
    }
199
200
    /// Extracts textual content from a given object, handling various object types, such as runs, text elements, and
201
    /// other specific constructs. The method accounts for different cases, such as run breaks, hyphens, and other
202
    /// document-specific constructs, and converts them into corresponding string representations.
203
    ///
204
    /// @param content the object from which text content is to be extracted. This could be of various types
205
    ///         such as [R], [JAXBElement], [Text] or specific document elements.
206
    ///
207
    /// @return a string representation of the extracted textual content. If the object's type is not handled, an empty
208
    ///         string is returned.
209
    public static String asString(Object content) {
210 1 1. asString : replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils::asString → NO_COVERAGE
        return switch (content) {
211
            case P paragraph -> asString(paragraph.getContent());
212
            case R run -> asString(run.getContent());
213
            case JAXBElement<?> jaxbElement when jaxbElement.getName()
214
                                                            .getLocalPart()
215 1 1. asString : negated conditional → NO_COVERAGE
                                                            .equals("instrText") -> "<instrText>";
216
            case JAXBElement<?> jaxbElement when !jaxbElement.getName()
217
                                                             .getLocalPart()
218 1 1. asString : negated conditional → NO_COVERAGE
                                                             .equals("instrText") -> asString(jaxbElement.getValue());
219
            case Text text -> asString(text);
220
            case R.Tab _ -> "\t";
221
            case R.Cr _ -> "\n";
222 1 1. asString : negated conditional → NO_COVERAGE
            case Br br when br.getType() == null -> "\n";
223 1 1. asString : negated conditional → NO_COVERAGE
            case Br br when br.getType() == STBrType.PAGE -> "\n";
224 1 1. asString : negated conditional → NO_COVERAGE
            case Br br when br.getType() == STBrType.COLUMN -> "\n";
225 1 1. asString : negated conditional → NO_COVERAGE
            case Br br when br.getType() == STBrType.TEXT_WRAPPING -> "\n";
226
227
            case R.NoBreakHyphen _ -> "‑";
228
            case R.SoftHyphen _ -> "\u00AD";
229 4 1. asString : negated conditional → NO_COVERAGE
2. asString : negated conditional → NO_COVERAGE
3. asString : negated conditional → NO_COVERAGE
4. asString : negated conditional → NO_COVERAGE
            case R.LastRenderedPageBreak _, R.AnnotationRef _, R.CommentReference _, Drawing _ -> "";
230
            case FldChar _ -> "<fldchar>";
231
            case CTFtnEdnRef ref -> "<ref(%s)>".formatted(ref.getId());
232
            case R.Sym sym -> "<sym(%s, %s)>".formatted(sym.getFont(), sym.getChar());
233
            case List<?> list -> list.stream()
234
                                     .map(WmlUtils::asString)
235
                                     .collect(joining());
236 2 1. asString : negated conditional → NO_COVERAGE
2. asString : negated conditional → NO_COVERAGE
            case ProofErr _, CTShadow _ -> "";
237
            case SdtRun sdtRun -> asString(sdtRun.getSdtContent());
238
            case ContentAccessor contentAccessor -> asString(contentAccessor.getContent());
239
            case Pict pict -> asString(pict.getAnyAndAny());
240
            case VmlShapeElements vmlShapeElements -> asString(vmlShapeElements.getEGShapeElements());
241
            case CTTextbox textbox -> asString(textbox.getTxbxContent());
242 2 1. asString : negated conditional → NO_COVERAGE
2. asString : negated conditional → NO_COVERAGE
            case CommentRangeStart _, CommentRangeEnd _ -> "";
243
            default -> {
244
                log.debug("Unhandled object type: {}", content.getClass());
245
                yield "";
246
            }
247
        };
248
    }
249
250
    private static String asString(Text text) {
251
        // According to specs, the 'space' value can be empty or 'preserve'.
252
        // In the first case, we are supposed to ignore spaces around the 'text' value.
253
        var value = text.getValue();
254
        var space = text.getSpace();
255 2 1. asString : negated conditional → NO_COVERAGE
2. asString : replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils::asString → NO_COVERAGE
        return Objects.equals(space, PRESERVE) ? value : value.trim();
256
    }
257
258
    /// Inserts a smart tag with the specified element type into the given paragraph at the position of the expression.
259
    ///
260
    /// @param element the element type for the smart tag
261
    /// @param paragraph the [P] paragraph to insert the smart tag into
262
    /// @param expression the expression to replace with the smart tag
263
    /// @param start the start index of the expression
264
    /// @param end the end index of the expression
265
    ///
266
    /// @return a list of [Object] representing the updated content
267
    public static List<Object> insertSmartTag(String element, P paragraph, String expression, int start, int end) {
268
        var run = newRun(expression);
269
        var smartTag = newSmartTag("officestamper", newCtAttr("type", element), run);
270 1 1. insertSmartTag : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        findFirstAffectedRunPr(paragraph, start, end).ifPresent(run::setRPr);
271 1 1. insertSmartTag : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::insertSmartTag → NO_COVERAGE
        return replace(paragraph, List.of(smartTag), start, end);
272
    }
273
274
    /// Finds the first affected run properties within the specified range.
275
    ///
276
    /// @param contentAccessor the [ContentAccessor] to search in
277
    /// @param start the start index of the range
278
    /// @param end the end index of the range
279
    ///
280
    /// @return an [Optional] containing the [RPr] if found, or an empty [Optional] if not found
281
    public static Optional<RPr> findFirstAffectedRunPr(ContentAccessor contentAccessor, int start, int end) {
282
        var iterator = new DocxIterator(contentAccessor).selectClass(R.class);
283
        var runs = StandardRun.wrap(iterator);
284
285
        var affectedRuns = runs.stream()
286 2 1. lambda$findFirstAffectedRunPr$0 : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$findFirstAffectedRunPr$0 → NO_COVERAGE
2. lambda$findFirstAffectedRunPr$0 : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$findFirstAffectedRunPr$0 → NO_COVERAGE
                               .filter(run -> run.isTouchedByRange(start, end))
287
                               .toList();
288
289
        var firstRun = affectedRuns.getFirst();
290
        var firstRunPr = firstRun.getPr();
291 1 1. findFirstAffectedRunPr : replaced return value with Optional.empty for pro/verron/officestamper/utils/wml/WmlUtils::findFirstAffectedRunPr → NO_COVERAGE
        return ofNullable(firstRunPr);
292
    }
293
294
    /// Replaces content within the specified range with the provided insert objects.
295
    ///
296
    /// @param contentAccessor the [ContentAccessor] in which to replace content
297
    /// @param insert the list of objects to insert
298
    /// @param startIndex the start index of the range to replace
299
    /// @param endIndex the end index of the range to replace
300
    ///
301
    /// @return a list of [Object] representing the updated content
302
    public static List<Object> replace(
303
            ContentAccessor contentAccessor,
304
            List<Object> insert,
305
            int startIndex,
306
            int endIndex
307
    ) {
308
        var iterator = new DocxIterator(contentAccessor).selectClass(R.class);
309
        var runs = StandardRun.wrap(iterator);
310
        var affectedRuns = runs.stream()
311 2 1. lambda$replace$0 : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$replace$0 → NO_COVERAGE
2. lambda$replace$0 : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$replace$0 → NO_COVERAGE
                               .filter(run -> run.isTouchedByRange(startIndex, endIndex))
312
                               .toList();
313
314
        var firstRun = affectedRuns.getFirst();
315
        var firstR = firstRun.run();
316
        var firstSiblings = ((ContentAccessor) firstR.getParent()).getContent();
317
        var firstIndex = firstSiblings.indexOf(firstRun.run());
318
319 1 1. replace : negated conditional → NO_COVERAGE
        boolean singleRun = affectedRuns.size() == 1;
320 1 1. replace : negated conditional → NO_COVERAGE
        if (singleRun) {
321 2 1. replace : Replaced integer subtraction with addition → NO_COVERAGE
2. replace : negated conditional → NO_COVERAGE
            boolean expressionSpansCompleteRun = endIndex - startIndex == firstRun.length();
322 1 1. replace : negated conditional → NO_COVERAGE
            boolean expressionAtStartOfRun = startIndex == firstRun.startIndex();
323 1 1. replace : negated conditional → NO_COVERAGE
            boolean expressionAtEndOfRun = endIndex == firstRun.endIndex();
324 4 1. replace : changed conditional boundary → NO_COVERAGE
2. replace : negated conditional → NO_COVERAGE
3. replace : changed conditional boundary → NO_COVERAGE
4. replace : negated conditional → NO_COVERAGE
            boolean expressionWithinRun = startIndex > firstRun.startIndex() && endIndex <= firstRun.endIndex();
325
326 1 1. replace : negated conditional → NO_COVERAGE
            if (expressionSpansCompleteRun) {
327 1 1. replace : removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE
                firstRun.replace(startIndex, endIndex, "");
328
                firstSiblings.addAll(firstIndex, insert);
329
            }
330 1 1. replace : negated conditional → NO_COVERAGE
            else if (expressionAtStartOfRun) {
331 1 1. replace : removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE
                firstRun.replace(startIndex, endIndex, "");
332
                firstSiblings.addAll(firstIndex, insert);
333
            }
334 1 1. replace : negated conditional → NO_COVERAGE
            else if (expressionAtEndOfRun) {
335 1 1. replace : removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE
                firstRun.replace(startIndex, endIndex, "");
336 1 1. replace : Replaced integer addition with subtraction → NO_COVERAGE
                firstSiblings.addAll(firstIndex + 1, insert);
337
            }
338 1 1. replace : negated conditional → NO_COVERAGE
            else if (expressionWithinRun) {
339
                var originalRun = firstRun.run();
340
                var originalRPr = originalRun.getRPr();
341
                var newStartRun = create(firstRun.left(startIndex), originalRPr);
342
                var newEndRun = create(firstRun.right(endIndex), originalRPr);
343
                firstSiblings.remove(firstIndex);
344
                firstSiblings.addAll(firstIndex, wrap(newStartRun, insert, newEndRun));
345
            }
346
        }
347
        else {
348
            StandardRun lastRun = affectedRuns.getLast();
349 1 1. replace : removed call to pro/verron/officestamper/utils/wml/WmlUtils::removeExpression → NO_COVERAGE
            removeExpression(firstSiblings, firstRun, startIndex, endIndex, lastRun, affectedRuns);
350
            // add replacement run between first and last run
351 1 1. replace : Replaced integer addition with subtraction → NO_COVERAGE
            firstSiblings.addAll(firstIndex + 1, insert);
352
        }
353 1 1. replace : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::replace → NO_COVERAGE
        return new ArrayList<>(contentAccessor.getContent());
354
    }
355
356
    /// Creates a new run with the specified text, and the specified run style.
357
    ///
358
    /// @param text the initial text of the [R].
359
    /// @param rPr the [RPr] to apply to the run
360
    ///
361
    /// @return the newly created [R].
362
    public static R create(String text, RPr rPr) {
363
        R newStartRun = newRun(text);
364 1 1. create : removed call to org/docx4j/wml/R::setRPr → NO_COVERAGE
        newStartRun.setRPr(rPr);
365 1 1. create : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::create → NO_COVERAGE
        return newStartRun;
366
    }
367
368
    private static Collection<?> wrap(R prefix, Collection<?> elements, R suffix) {
369
        var merge = new ArrayList<>();
370
        merge.add(prefix);
371
        merge.addAll(elements);
372
        merge.add(suffix);
373 1 1. wrap : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::wrap → NO_COVERAGE
        return merge;
374
    }
375
376
    private static void removeExpression(
377
            List<Object> contents,
378
            StandardRun firstRun,
379
            int matchStartIndex,
380
            int matchEndIndex,
381
            StandardRun lastRun,
382
            List<StandardRun> affectedRuns
383
    ) {
384
        // remove the expression from the first run
385 1 1. removeExpression : removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE
        firstRun.replace(matchStartIndex, matchEndIndex, "");
386
        // remove all runs between first and last
387
        for (StandardRun run : affectedRuns) {
388 2 1. removeExpression : negated conditional → NO_COVERAGE
2. removeExpression : negated conditional → NO_COVERAGE
            if (!Objects.equals(run, firstRun) && !Objects.equals(run, lastRun)) {
389
                contents.remove(run.run());
390
            }
391
        }
392
        // remove the expression from the last run
393 1 1. removeExpression : removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE
        lastRun.replace(matchStartIndex, matchEndIndex, "");
394
    }
395
396
    /// Creates a new run with the specified text and inherits the style of the parent paragraph.
397
    ///
398
    /// @param text the initial text of the [R].
399
    /// @param paragraphPr the [PPr] to apply to the run
400
    ///
401
    /// @return the newly created [R].
402
    public static R create(String text, PPr paragraphPr) {
403
        R run = newRun(text);
404 1 1. create : removed call to pro/verron/officestamper/utils/wml/WmlUtils::applyParagraphStyle → NO_COVERAGE
        applyParagraphStyle(run, paragraphPr);
405 1 1. create : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::create → NO_COVERAGE
        return run;
406
    }
407
408
    /// Applies the style of the given paragraph to the given content object (if the content object is a [R]).
409
    ///
410
    /// @param run the [R] to which the style should be applied.
411
    /// @param paragraphPr the [PPr] containing the style to apply
412
    public static void applyParagraphStyle(R run, @Nullable PPr paragraphPr) {
413 1 1. applyParagraphStyle : negated conditional → NO_COVERAGE
        if (paragraphPr == null) return;
414
        var runPr = paragraphPr.getRPr();
415 1 1. applyParagraphStyle : negated conditional → NO_COVERAGE
        if (runPr == null) return;
416
        RPr runProperties = new RPr();
417
        StyleUtil.apply(runPr, runProperties);
418 1 1. applyParagraphStyle : removed call to org/docx4j/wml/R::setRPr → NO_COVERAGE
        run.setRPr(runProperties);
419
    }
420
421
    /// Sets the text of the given run to the given value.
422
    ///
423
    /// @param run the [R] whose text to change.
424
    /// @param text the text to set.
425
    public static void setText(R run, String text) {
426
        run.getContent()
427 1 1. setText : removed call to java/util/List::clear → NO_COVERAGE
           .clear();
428
        Text textObj = newText(text);
429
        run.getContent()
430
           .add(textObj);
431
    }
432
433
    /// Replaces all occurrences of the specified expression with the provided run objects.
434
    ///
435
    /// @param contentAccessor the [ContentAccessor] in which to replace the expression
436
    /// @param expression the expression to replace
437
    /// @param insert the list of objects to insert
438
    /// @param onRPr a consumer to handle [RPr] properties
439
    ///
440
    /// @return a list of [Object] representing the updated content
441
    public static List<Object> replaceExpressionWithRun(
442
            ContentAccessor contentAccessor,
443
            String expression,
444
            List<Object> insert,
445
            Consumer<RPr> onRPr
446
    ) {
447
        var text = asString(contentAccessor);
448
        int matchStartIndex = text.indexOf(expression);
449 2 1. replaceExpressionWithRun : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::replaceExpressionWithRun → NO_COVERAGE
2. replaceExpressionWithRun : negated conditional → NO_COVERAGE
        if (matchStartIndex == -1) /*nothing to replace*/ return contentAccessor.getContent();
450 1 1. replaceExpressionWithRun : Replaced integer addition with subtraction → NO_COVERAGE
        int matchEndIndex = matchStartIndex + expression.length();
451 1 1. replaceExpressionWithRun : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        findFirstAffectedRunPr(contentAccessor, matchStartIndex, matchEndIndex).ifPresent(onRPr);
452 1 1. replaceExpressionWithRun : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::replaceExpressionWithRun → NO_COVERAGE
        return replace(contentAccessor, insert, matchStartIndex, matchEndIndex);
453
    }
454
455
    /// Checks if the given [CTSmartTagRun] contains an element that matches the expected element.
456
    ///
457
    /// @param tag the [CTSmartTagRun] object to be evaluated
458
    /// @param expectedElement the expected element to compare against
459
    ///
460
    /// @return true if the actual element of the given tag matches the expected element, false otherwise
461
    public static boolean isTagElement(CTSmartTagRun tag, String expectedElement) {
462
        var actualElement = tag.getElement();
463 2 1. isTagElement : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::isTagElement → NO_COVERAGE
2. isTagElement : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::isTagElement → NO_COVERAGE
        return Objects.equals(expectedElement, actualElement);
464
    }
465
466
    /// Sets or updates an attribute for the specified smart tag. This method ensures that the provided attribute
467
    /// key-value pair is added to the smart tag's attribute list. If the attribute already exists, its value is
468
    /// updated. If the smart tag or its attribute metadata is null, they are initialized.
469
    ///
470
    /// @param smartTag the smart tag object to modify
471
    /// @param attributeKey the key of the attribute to set or update
472
    /// @param attributeValue the value to assign to the specified attribute key
473
    public static void setTagAttribute(CTSmartTagRun smartTag, String attributeKey, String attributeValue) {
474
        var smartTagPr = smartTag.getSmartTagPr();
475 1 1. setTagAttribute : negated conditional → NO_COVERAGE
        if (smartTagPr == null) {
476
            smartTagPr = new CTSmartTagPr();
477 1 1. setTagAttribute : removed call to org/docx4j/wml/CTSmartTagRun::setSmartTagPr → NO_COVERAGE
            smartTag.setSmartTagPr(smartTagPr);
478
        }
479
        var smartTagPrAttr = smartTagPr.getAttr();
480 1 1. setTagAttribute : negated conditional → NO_COVERAGE
        if (smartTagPrAttr == null) {
481
            smartTagPrAttr = new ArrayList<>();
482 1 1. setTagAttribute : removed call to org/docx4j/wml/CTSmartTagRun::setSmartTagPr → NO_COVERAGE
            smartTag.setSmartTagPr(smartTagPr);
483
        }
484
        for (CTAttr attribute : smartTagPrAttr) {
485 1 1. setTagAttribute : negated conditional → NO_COVERAGE
            if (attributeKey.equals(attribute.getName())) {
486 1 1. setTagAttribute : removed call to org/docx4j/wml/CTAttr::setVal → NO_COVERAGE
                attribute.setVal(attributeValue);
487
                return;
488
            }
489
        }
490
        var ctAttr = newAttribute(attributeKey, attributeValue);
491
        smartTagPrAttr.add(ctAttr);
492
    }
493
494
    /// Creates a new attribute object with the specified key and value.
495
    ///
496
    /// @param attributeKey the key for the new attribute
497
    /// @param attributeValue the value for the new attribute
498
    ///
499
    /// @return a CTAttr object representing the new attribute
500
    public static CTAttr newAttribute(String attributeKey, String attributeValue) {
501 1 1. newAttribute : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::newAttribute → NO_COVERAGE
        return newCtAttr(attributeKey, attributeValue);
502
    }
503
504
    /// Deletes all elements associated with the specified comment from the provided list of items.
505
    ///
506
    /// @param commentId the ID of the comment to be deleted
507
    /// @param items the list of items from which elements associated with the comment will be deleted
508
    public static void deleteCommentFromElements(BigInteger commentId, List<Object> items) {
509
        record DeletableItems(List<Object> container, List<Object> items) {
510
            static List<DeletableItems> findAll(List<Object> items, BigInteger commentId) {
511 2 1. lambda$findAll$0 : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::lambda$findAll$0 → NO_COVERAGE
2. lambda$findAll$0 : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::lambda$findAll$0 → NO_COVERAGE
                Predicate<BigInteger> predicate = bi -> Objects.equals(bi, commentId);
512
                List<DeletableItems> elementsToRemove = new ArrayList<>();
513 1 1. findAll : removed call to java/util/List::forEach → NO_COVERAGE
                items.forEach(item -> {
514
                    Object unwrapped = unwrap(item);
515
                    // Recursively finds deletable items associated with comment ID
516
                    elementsToRemove.addAll(switch (unwrapped) {
517
                        case CTSmartTagRun str when str.getContent()
518
                                                       .stream()
519 1 1. lambda$findAll$1 : negated conditional → NO_COVERAGE
                                                       .anyMatch(i -> i instanceof CommentRangeStart crs
520 3 1. lambda$findAll$2 : negated conditional → NO_COVERAGE
2. lambda$findAll$2 : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::lambda$findAll$2 → NO_COVERAGE
3. lambda$findAll$2 : negated conditional → NO_COVERAGE
                                                                      && predicate.test(crs.getId())) ->
521
                                from(items, item);
522 1 1. lambda$findAll$1 : negated conditional → NO_COVERAGE
                        case CommentRangeStart crs when predicate.test(crs.getId()) -> from(items, item);
523 1 1. lambda$findAll$1 : negated conditional → NO_COVERAGE
                        case CommentRangeEnd cre when predicate.test(cre.getId()) -> from(items, item);
524 1 1. lambda$findAll$1 : negated conditional → NO_COVERAGE
                        case R.CommentReference rcr when predicate.test(rcr.getId()) -> from(items, item);
525
                        case ContentAccessor ca -> findAll(ca, commentId);
526
                        case SdtRun sdtRun -> findAll(sdtRun, commentId);
527
                        default -> emptyList();
528
                    });
529
                });
530 1 1. findAll : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::findAll → NO_COVERAGE
                return elementsToRemove;
531
            }
532
533
            private static Collection<DeletableItems> findAll(SdtRun sdtRun, BigInteger commentId) {
534 1 1. findAll : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::findAll → NO_COVERAGE
                return findAll(sdtRun.getSdtContent(), commentId);
535
            }
536
537
            private static Collection<DeletableItems> findAll(ContentAccessor ca, BigInteger commentId) {
538 1 1. findAll : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::findAll → NO_COVERAGE
                return findAll(ca.getContent(), commentId);
539
            }
540
541
            private static List<DeletableItems> from(List<Object> items, Object item) {
542 1 1. from : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::from → NO_COVERAGE
                return Collections.singletonList(new DeletableItems(items, List.of(item)));
543
            }
544
        }
545
        DeletableItems.findAll(items, commentId)
546 1 1. deleteCommentFromElements : removed call to java/util/List::forEach → NO_COVERAGE
                      .forEach(p -> p.container.removeAll(p.items));
547
    }
548
549
    /// Visits the document's main content, header, footer, footnotes, and endnotes using the specified visitor.
550
    ///
551
    /// @param document the WordprocessingMLPackage representing the document to be visited
552
    /// @param visitor the TraversalUtilVisitor to be applied to each relevant part of the document
553
    public static void visitDocument(WordprocessingMLPackage document, TraversalUtilVisitor<?> visitor) {
554
        var mainDocumentPart = document.getMainDocumentPart();
555 1 1. visitDocument : removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE
        TraversalUtil.visit(mainDocumentPart, visitor);
556
        WmlUtils.streamHeaderFooterPart(document)
557 2 1. lambda$visitDocument$0 : removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE
2. visitDocument : removed call to java/util/stream/Stream::forEach → NO_COVERAGE
                .forEach(f -> TraversalUtil.visit(f, visitor));
558 1 1. visitDocument : removed call to pro/verron/officestamper/utils/wml/WmlUtils::visitPartIfExists → NO_COVERAGE
        WmlUtils.visitPartIfExists(visitor, mainDocumentPart.getFootnotesPart());
559 1 1. visitDocument : removed call to pro/verron/officestamper/utils/wml/WmlUtils::visitPartIfExists → NO_COVERAGE
        WmlUtils.visitPartIfExists(visitor, mainDocumentPart.getEndNotesPart());
560
    }
561
562
    private static Stream<Object> streamHeaderFooterPart(WordprocessingMLPackage document) {
563 1 1. streamHeaderFooterPart : replaced return value with Stream.empty for pro/verron/officestamper/utils/wml/WmlUtils::streamHeaderFooterPart → NO_COVERAGE
        return document.getDocumentModel()
564
                       .getSections()
565
                       .stream()
566
                       .map(SectionWrapper::getHeaderFooterPolicy)
567
                       .flatMap(WmlUtils::extractHeaderFooterParts);
568
    }
569
570
    private static void visitPartIfExists(TraversalUtilVisitor<?> visitor, @Nullable JaxbXmlPart<?> part) {
571
        ofNullable(part).map(WmlUtils::extractContent)
572 2 1. lambda$visitPartIfExists$0 : removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE
2. visitPartIfExists : removed call to java/util/Optional::ifPresent → NO_COVERAGE
                        .ifPresent(c -> TraversalUtil.visit(c, visitor));
573
    }
574
575
    private static Stream<JaxbXmlPart<?>> extractHeaderFooterParts(HeaderFooterPolicy hfp) {
576
        Stream.Builder<JaxbXmlPart<?>> builder = Stream.builder();
577 1 1. extractHeaderFooterParts : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        ofNullable(hfp.getFirstHeader()).ifPresent(builder::add);
578 1 1. extractHeaderFooterParts : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        ofNullable(hfp.getDefaultHeader()).ifPresent(builder::add);
579 1 1. extractHeaderFooterParts : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        ofNullable(hfp.getEvenHeader()).ifPresent(builder::add);
580 1 1. extractHeaderFooterParts : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        ofNullable(hfp.getFirstFooter()).ifPresent(builder::add);
581 1 1. extractHeaderFooterParts : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        ofNullable(hfp.getDefaultFooter()).ifPresent(builder::add);
582 1 1. extractHeaderFooterParts : removed call to java/util/Optional::ifPresent → NO_COVERAGE
        ofNullable(hfp.getEvenFooter()).ifPresent(builder::add);
583 1 1. extractHeaderFooterParts : replaced return value with Stream.empty for pro/verron/officestamper/utils/wml/WmlUtils::extractHeaderFooterParts → NO_COVERAGE
        return builder.build();
584
    }
585
586
    private static Object extractContent(JaxbXmlPart<?> jaxbXmlPart) {
587
        try {
588 1 1. extractContent : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::extractContent → NO_COVERAGE
            return jaxbXmlPart.getContents();
589
        } catch (Docx4JException e) {
590
            throw new UtilsException(e);
591
        }
592
    }
593
594
    public static boolean hasTagAttribute(CTSmartTagRun tag, String attrKey, String attrVal) {
595
        var smartTagPr = tag.getSmartTagPr();
596
        var smartTagPrAttr = smartTagPr.getAttr();
597
        for (CTAttr ctAttr : smartTagPrAttr)
598 3 1. hasTagAttribute : negated conditional → NO_COVERAGE
2. hasTagAttribute : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::hasTagAttribute → NO_COVERAGE
3. hasTagAttribute : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::hasTagAttribute → NO_COVERAGE
            if (Objects.equals(ctAttr.getName(), attrKey)) return Objects.equals(ctAttr.getVal(), attrVal);
599 1 1. hasTagAttribute : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::hasTagAttribute → NO_COVERAGE
        return false;
600
    }
601
602
    /// @param startIndex the start index of the run relative to the containing paragraph.
603
    /// @param run the [R] run itself.
604
    private record StandardRun(int startIndex, R run) {
605
606
        /// Initializes a list of [StandardRun] objects based on the given iterator of [R] objects.
607
        ///
608
        /// @param iterator the iterator of [R] objects to be processed into [StandardRun] instances
609
        ///
610
        /// @return a list of [StandardRun] objects created from the given iterator
611
        public static List<StandardRun> wrap(Iterator<R> iterator) {
612
            var index = 0;
613
            var runList = new ArrayList<StandardRun>();
614 1 1. wrap : negated conditional → NO_COVERAGE
            while (iterator.hasNext()) {
615
                var run = iterator.next();
616
                var currentRun = new StandardRun(index, run);
617
                runList.add(currentRun);
618 1 1. wrap : Replaced integer addition with subtraction → NO_COVERAGE
                index += currentRun.length();
619
            }
620 1 1. wrap : replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::wrap → NO_COVERAGE
            return runList;
621
        }
622
623
        /// Calculates the length of the text content of this run.
624
        ///
625
        /// @return the length of the text in the current run.
626
        public int length() {
627 1 1. length : replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::length → NO_COVERAGE
            return getText().length();
628
        }
629
630
        /// Returns the text string of a run.
631
        ///
632
        /// @return [String] representation of the run.
633
        public String getText() {
634 1 1. getText : replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::getText → NO_COVERAGE
            return asString(run);
635
        }
636
637
        /// Retrieves the properties associated with this run.
638
        ///
639
        /// @return the [RPr] object representing the properties of the run.
640
        public RPr getPr() {
641 1 1. getPr : replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::getPr → NO_COVERAGE
            return run.getRPr();
642
        }
643
644
        /// Determines whether the current run is affected by the specified range of global start and end indices. A run
645
        /// is considered "touched" if any part of it overlaps with the given range.
646
        ///
647
        /// @param globalStartIndex the global start index of the range.
648
        /// @param globalEndIndex the global end index of the range.
649
        ///
650
        /// @return `true` if the current run is touched by the specified range; `false` otherwise.
651
        public boolean isTouchedByRange(int globalStartIndex, int globalEndIndex) {
652 3 1. isTouchedByRange : negated conditional → NO_COVERAGE
2. isTouchedByRange : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::isTouchedByRange → NO_COVERAGE
3. isTouchedByRange : negated conditional → NO_COVERAGE
            return startsInRange(globalStartIndex, globalEndIndex) || endsInRange(globalStartIndex, globalEndIndex)
653 1 1. isTouchedByRange : negated conditional → NO_COVERAGE
                   || englobesRange(globalStartIndex, globalEndIndex);
654
        }
655
656
        private boolean startsInRange(int globalStartIndex, int globalEndIndex) {
657 5 1. startsInRange : negated conditional → NO_COVERAGE
2. startsInRange : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::startsInRange → NO_COVERAGE
3. startsInRange : changed conditional boundary → NO_COVERAGE
4. startsInRange : negated conditional → NO_COVERAGE
5. startsInRange : changed conditional boundary → NO_COVERAGE
            return globalStartIndex < startIndex && startIndex <= globalEndIndex;
658
        }
659
660
        private boolean endsInRange(int globalStartIndex, int globalEndIndex) {
661 5 1. endsInRange : changed conditional boundary → NO_COVERAGE
2. endsInRange : negated conditional → NO_COVERAGE
3. endsInRange : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::endsInRange → NO_COVERAGE
4. endsInRange : negated conditional → NO_COVERAGE
5. endsInRange : changed conditional boundary → NO_COVERAGE
            return globalStartIndex < endIndex() && endIndex() <= globalEndIndex;
662
        }
663
664
        private boolean englobesRange(int globalStartIndex, int globalEndIndex) {
665 5 1. englobesRange : negated conditional → NO_COVERAGE
2. englobesRange : changed conditional boundary → NO_COVERAGE
3. englobesRange : negated conditional → NO_COVERAGE
4. englobesRange : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::englobesRange → NO_COVERAGE
5. englobesRange : changed conditional boundary → NO_COVERAGE
            return startIndex <= globalStartIndex && globalEndIndex <= endIndex();
666
        }
667
668
        /// Calculates the end index of the current run based on its start index and length.
669
        ///
670
        /// @return the end index of the run.
671
        public int endIndex() {
672 2 1. endIndex : Replaced integer addition with subtraction → NO_COVERAGE
2. endIndex : replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::endIndex → NO_COVERAGE
            return startIndex + length();
673
        }
674
675
        /// Replaces the substring starting at the given index with the given replacement string.
676
        ///
677
        /// @param globalStartIndex the global index at which to start the replacement.
678
        /// @param globalEndIndex the global index at which to end the replacement.
679
        /// @param replacement the string to replace the substring at the specified global index.
680
        public void replace(int globalStartIndex, int globalEndIndex, String replacement) {
681
            var text = left(globalStartIndex) + replacement + right(globalEndIndex);
682 1 1. replace : removed call to pro/verron/officestamper/utils/wml/WmlUtils::setText → NO_COVERAGE
            setText(run, text);
683
        }
684
685
        /// Extracts a substring of the run's text, starting from the beginning and extending up to the localized index
686
        /// of the specified global end index.
687
        ///
688
        /// @param globalEndIndex the global end index used to determine the cutoff point for the extracted
689
        ///         substring.
690
        ///
691
        /// @return a substring of the run's text, starting at the beginning and ending at the specified localized
692
        ///         index.
693
        public String left(int globalEndIndex) {
694 1 1. left : replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::left → NO_COVERAGE
            return getText().substring(0, localize(globalEndIndex));
695
        }
696
697
        /// Extracts a substring of the run's text, starting from the localized index of the specified global start
698
        /// index to the end of the run's text.
699
        ///
700
        /// @param globalStartIndex the global index specifying the starting point for the substring in the
701
        ///         run's text.
702
        ///
703
        /// @return a substring of the run's text starting from the localized index corresponding to the provided global
704
        ///         start index.
705
        public String right(int globalStartIndex) {
706 1 1. right : replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::right → NO_COVERAGE
            return getText().substring(localize(globalStartIndex));
707
        }
708
709
        /// Converts a global index to a local index within the context of this run. (meaning the index relative to
710
        /// multiple aggregated runs)
711
        ///
712
        /// @param globalIndex the global index to convert.
713
        ///
714
        /// @return the local index corresponding to the given global index.
715
        private int localize(int globalIndex) {
716 2 1. localize : changed conditional boundary → NO_COVERAGE
2. localize : negated conditional → NO_COVERAGE
            if (globalIndex < startIndex) return 0;
717 3 1. localize : changed conditional boundary → NO_COVERAGE
2. localize : replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::localize → NO_COVERAGE
3. localize : negated conditional → NO_COVERAGE
            else if (globalIndex > endIndex()) return length();
718 2 1. localize : replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::localize → NO_COVERAGE
2. localize : Replaced integer subtraction with addition → NO_COVERAGE
            else return globalIndex - startIndex;
719
        }
720
721
        /// Gets the start index of this run.
722
        ///
723
        /// @return the start index of the run relative to the containing paragraph.
724
        @Override
725
        public int startIndex() {return startIndex;}
726
727
        /// Gets the underlying run object.
728
        ///
729
        /// @return the [R] run object.
730
        @Override
731
        public R run() {return run;}
732
    }
733
}

Mutations

63

1.1
Location : getFirstParentWithClass
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : getFirstParentWithClass
Killed by : none
negated conditional → NO_COVERAGE

64

1.1
Location : getFirstParentWithClass
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

65

1.1
Location : getFirstParentWithClass
Killed by : none
negated conditional → NO_COVERAGE

66

1.1
Location : getFirstParentWithClass
Killed by : none
replaced return value with Optional.empty for pro/verron/officestamper/utils/wml/WmlUtils::getFirstParentWithClass → NO_COVERAGE

2.2
Location : getFirstParentWithClass
Killed by : none
negated conditional → NO_COVERAGE

67

1.1
Location : getFirstParentWithClass
Killed by : none
negated conditional → NO_COVERAGE

79

1.1
Location : extractCommentElements
Killed by : none
removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE

80

1.1
Location : extractCommentElements
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::extractCommentElements → NO_COVERAGE

94

1.1
Location : findComment
Killed by : none
replaced return value with Optional.empty for pro/verron/officestamper/utils/wml/WmlUtils::findComment → NO_COVERAGE

102

1.1
Location : getComments
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::getComments → NO_COVERAGE

109

1.1
Location : idEqual
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::idEqual → NO_COVERAGE

111

1.1
Location : lambda$idEqual$0
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$idEqual$0 → NO_COVERAGE

2.2
Location : lambda$idEqual$0
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$idEqual$0 → NO_COVERAGE

125

1.1
Location : remove
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE

126

1.1
Location : remove
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE

127

1.1
Location : remove
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE

128

1.1
Location : remove
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::remove → NO_COVERAGE

131

1.1
Location : remove
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : remove
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::ensureValidity → NO_COVERAGE

137

1.1
Location : remove
Killed by : none
negated conditional → NO_COVERAGE

138

1.1
Location : remove
Killed by : none
negated conditional → NO_COVERAGE

139

1.1
Location : remove
Killed by : none
removed call to java/util/ListIterator::remove → NO_COVERAGE

167

1.1
Location : ensureValidity
Killed by : none
negated conditional → NO_COVERAGE

168

1.1
Location : ensureValidity
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::addEmptyParagraph → NO_COVERAGE

173

1.1
Location : equals
Killed by : none
negated conditional → NO_COVERAGE

174

1.1
Location : equals
Killed by : none
negated conditional → NO_COVERAGE

175

1.1
Location : equals
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::equals → NO_COVERAGE

2.2
Location : equals
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::equals → NO_COVERAGE

179

1.1
Location : containsAnElementOfAnyClasses
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::containsAnElementOfAnyClasses → NO_COVERAGE

2.2
Location : containsAnElementOfAnyClasses
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::containsAnElementOfAnyClasses → NO_COVERAGE

180

1.1
Location : lambda$containsAnElementOfAnyClasses$0
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$containsAnElementOfAnyClasses$0 → NO_COVERAGE

2.2
Location : lambda$containsAnElementOfAnyClasses$0
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$containsAnElementOfAnyClasses$0 → NO_COVERAGE

191

1.1
Location : isAnElementOfAnyClasses
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::isAnElementOfAnyClasses → NO_COVERAGE

2.2
Location : isAnElementOfAnyClasses
Killed by : none
negated conditional → NO_COVERAGE

193

1.1
Location : isAnElementOfAnyClasses
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::isAnElementOfAnyClasses → NO_COVERAGE

197

1.1
Location : unwrapJAXBElement
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::unwrapJAXBElement → NO_COVERAGE

2.2
Location : unwrapJAXBElement
Killed by : none
negated conditional → NO_COVERAGE

210

1.1
Location : asString
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils::asString → NO_COVERAGE

215

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

218

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

222

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

223

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

224

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

225

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

229

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

4.4
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

236

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

242

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

255

1.1
Location : asString
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : asString
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils::asString → NO_COVERAGE

270

1.1
Location : insertSmartTag
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

271

1.1
Location : insertSmartTag
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::insertSmartTag → NO_COVERAGE

286

1.1
Location : lambda$findFirstAffectedRunPr$0
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$findFirstAffectedRunPr$0 → NO_COVERAGE

2.2
Location : lambda$findFirstAffectedRunPr$0
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$findFirstAffectedRunPr$0 → NO_COVERAGE

291

1.1
Location : findFirstAffectedRunPr
Killed by : none
replaced return value with Optional.empty for pro/verron/officestamper/utils/wml/WmlUtils::findFirstAffectedRunPr → NO_COVERAGE

311

1.1
Location : lambda$replace$0
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::lambda$replace$0 → NO_COVERAGE

2.2
Location : lambda$replace$0
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::lambda$replace$0 → NO_COVERAGE

319

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

320

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

321

1.1
Location : replace
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

2.2
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

322

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

323

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

324

1.1
Location : replace
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : replace
Killed by : none
changed conditional boundary → NO_COVERAGE

4.4
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

326

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

327

1.1
Location : replace
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE

330

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

331

1.1
Location : replace
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE

334

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

335

1.1
Location : replace
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE

336

1.1
Location : replace
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

338

1.1
Location : replace
Killed by : none
negated conditional → NO_COVERAGE

349

1.1
Location : replace
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::removeExpression → NO_COVERAGE

351

1.1
Location : replace
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

353

1.1
Location : replace
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::replace → NO_COVERAGE

364

1.1
Location : create
Killed by : none
removed call to org/docx4j/wml/R::setRPr → NO_COVERAGE

365

1.1
Location : create
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::create → NO_COVERAGE

373

1.1
Location : wrap
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::wrap → NO_COVERAGE

385

1.1
Location : removeExpression
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE

388

1.1
Location : removeExpression
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : removeExpression
Killed by : none
negated conditional → NO_COVERAGE

393

1.1
Location : removeExpression
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::replace → NO_COVERAGE

404

1.1
Location : create
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::applyParagraphStyle → NO_COVERAGE

405

1.1
Location : create
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::create → NO_COVERAGE

413

1.1
Location : applyParagraphStyle
Killed by : none
negated conditional → NO_COVERAGE

415

1.1
Location : applyParagraphStyle
Killed by : none
negated conditional → NO_COVERAGE

418

1.1
Location : applyParagraphStyle
Killed by : none
removed call to org/docx4j/wml/R::setRPr → NO_COVERAGE

427

1.1
Location : setText
Killed by : none
removed call to java/util/List::clear → NO_COVERAGE

449

1.1
Location : replaceExpressionWithRun
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::replaceExpressionWithRun → NO_COVERAGE

2.2
Location : replaceExpressionWithRun
Killed by : none
negated conditional → NO_COVERAGE

450

1.1
Location : replaceExpressionWithRun
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

451

1.1
Location : replaceExpressionWithRun
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

452

1.1
Location : replaceExpressionWithRun
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils::replaceExpressionWithRun → NO_COVERAGE

463

1.1
Location : isTagElement
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::isTagElement → NO_COVERAGE

2.2
Location : isTagElement
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::isTagElement → NO_COVERAGE

475

1.1
Location : setTagAttribute
Killed by : none
negated conditional → NO_COVERAGE

477

1.1
Location : setTagAttribute
Killed by : none
removed call to org/docx4j/wml/CTSmartTagRun::setSmartTagPr → NO_COVERAGE

480

1.1
Location : setTagAttribute
Killed by : none
negated conditional → NO_COVERAGE

482

1.1
Location : setTagAttribute
Killed by : none
removed call to org/docx4j/wml/CTSmartTagRun::setSmartTagPr → NO_COVERAGE

485

1.1
Location : setTagAttribute
Killed by : none
negated conditional → NO_COVERAGE

486

1.1
Location : setTagAttribute
Killed by : none
removed call to org/docx4j/wml/CTAttr::setVal → NO_COVERAGE

501

1.1
Location : newAttribute
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::newAttribute → NO_COVERAGE

511

1.1
Location : lambda$findAll$0
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::lambda$findAll$0 → NO_COVERAGE

2.2
Location : lambda$findAll$0
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::lambda$findAll$0 → NO_COVERAGE

513

1.1
Location : findAll
Killed by : none
removed call to java/util/List::forEach → NO_COVERAGE

519

1.1
Location : lambda$findAll$1
Killed by : none
negated conditional → NO_COVERAGE

520

1.1
Location : lambda$findAll$2
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : lambda$findAll$2
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::lambda$findAll$2 → NO_COVERAGE

3.3
Location : lambda$findAll$2
Killed by : none
negated conditional → NO_COVERAGE

522

1.1
Location : lambda$findAll$1
Killed by : none
negated conditional → NO_COVERAGE

523

1.1
Location : lambda$findAll$1
Killed by : none
negated conditional → NO_COVERAGE

524

1.1
Location : lambda$findAll$1
Killed by : none
negated conditional → NO_COVERAGE

530

1.1
Location : findAll
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::findAll → NO_COVERAGE

534

1.1
Location : findAll
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::findAll → NO_COVERAGE

538

1.1
Location : findAll
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::findAll → NO_COVERAGE

542

1.1
Location : from
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$1DeletableItems::from → NO_COVERAGE

546

1.1
Location : deleteCommentFromElements
Killed by : none
removed call to java/util/List::forEach → NO_COVERAGE

555

1.1
Location : visitDocument
Killed by : none
removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE

557

1.1
Location : lambda$visitDocument$0
Killed by : none
removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE

2.2
Location : visitDocument
Killed by : none
removed call to java/util/stream/Stream::forEach → NO_COVERAGE

558

1.1
Location : visitDocument
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::visitPartIfExists → NO_COVERAGE

559

1.1
Location : visitDocument
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::visitPartIfExists → NO_COVERAGE

563

1.1
Location : streamHeaderFooterPart
Killed by : none
replaced return value with Stream.empty for pro/verron/officestamper/utils/wml/WmlUtils::streamHeaderFooterPart → NO_COVERAGE

572

1.1
Location : lambda$visitPartIfExists$0
Killed by : none
removed call to org/docx4j/TraversalUtil::visit → NO_COVERAGE

2.2
Location : visitPartIfExists
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

577

1.1
Location : extractHeaderFooterParts
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

578

1.1
Location : extractHeaderFooterParts
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

579

1.1
Location : extractHeaderFooterParts
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

580

1.1
Location : extractHeaderFooterParts
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

581

1.1
Location : extractHeaderFooterParts
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

582

1.1
Location : extractHeaderFooterParts
Killed by : none
removed call to java/util/Optional::ifPresent → NO_COVERAGE

583

1.1
Location : extractHeaderFooterParts
Killed by : none
replaced return value with Stream.empty for pro/verron/officestamper/utils/wml/WmlUtils::extractHeaderFooterParts → NO_COVERAGE

588

1.1
Location : extractContent
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils::extractContent → NO_COVERAGE

598

1.1
Location : hasTagAttribute
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : hasTagAttribute
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::hasTagAttribute → NO_COVERAGE

3.3
Location : hasTagAttribute
Killed by : none
replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlUtils::hasTagAttribute → NO_COVERAGE

599

1.1
Location : hasTagAttribute
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils::hasTagAttribute → NO_COVERAGE

614

1.1
Location : wrap
Killed by : none
negated conditional → NO_COVERAGE

618

1.1
Location : wrap
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

620

1.1
Location : wrap
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::wrap → NO_COVERAGE

627

1.1
Location : length
Killed by : none
replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::length → NO_COVERAGE

634

1.1
Location : getText
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::getText → NO_COVERAGE

641

1.1
Location : getPr
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::getPr → NO_COVERAGE

652

1.1
Location : isTouchedByRange
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : isTouchedByRange
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::isTouchedByRange → NO_COVERAGE

3.3
Location : isTouchedByRange
Killed by : none
negated conditional → NO_COVERAGE

653

1.1
Location : isTouchedByRange
Killed by : none
negated conditional → NO_COVERAGE

657

1.1
Location : startsInRange
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : startsInRange
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::startsInRange → NO_COVERAGE

3.3
Location : startsInRange
Killed by : none
changed conditional boundary → NO_COVERAGE

4.4
Location : startsInRange
Killed by : none
negated conditional → NO_COVERAGE

5.5
Location : startsInRange
Killed by : none
changed conditional boundary → NO_COVERAGE

661

1.1
Location : endsInRange
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : endsInRange
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : endsInRange
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::endsInRange → NO_COVERAGE

4.4
Location : endsInRange
Killed by : none
negated conditional → NO_COVERAGE

5.5
Location : endsInRange
Killed by : none
changed conditional boundary → NO_COVERAGE

665

1.1
Location : englobesRange
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : englobesRange
Killed by : none
changed conditional boundary → NO_COVERAGE

3.3
Location : englobesRange
Killed by : none
negated conditional → NO_COVERAGE

4.4
Location : englobesRange
Killed by : none
replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::englobesRange → NO_COVERAGE

5.5
Location : englobesRange
Killed by : none
changed conditional boundary → NO_COVERAGE

672

1.1
Location : endIndex
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

2.2
Location : endIndex
Killed by : none
replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::endIndex → NO_COVERAGE

682

1.1
Location : replace
Killed by : none
removed call to pro/verron/officestamper/utils/wml/WmlUtils::setText → NO_COVERAGE

694

1.1
Location : left
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::left → NO_COVERAGE

706

1.1
Location : right
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::right → NO_COVERAGE

716

1.1
Location : localize
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : localize
Killed by : none
negated conditional → NO_COVERAGE

717

1.1
Location : localize
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : localize
Killed by : none
replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::localize → NO_COVERAGE

3.3
Location : localize
Killed by : none
negated conditional → NO_COVERAGE

718

1.1
Location : localize
Killed by : none
replaced int return with 0 for pro/verron/officestamper/utils/wml/WmlUtils$StandardRun::localize → NO_COVERAGE

2.2
Location : localize
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.22.0