RemoveMalformedComments.java

1
package pro.verron.officestamper.preset.preprocessors.malformedcomments;
2
3
import org.docx4j.TraversalUtil;
4
import org.docx4j.openpackaging.exceptions.Docx4JException;
5
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
6
import org.docx4j.openpackaging.parts.WordprocessingML.CommentsPart;
7
import org.docx4j.wml.*;
8
import org.jvnet.jaxb2_commons.ppp.Child;
9
import org.slf4j.Logger;
10
import org.slf4j.LoggerFactory;
11
import pro.verron.officestamper.api.OfficeStamperException;
12
import pro.verron.officestamper.api.PreProcessor;
13
import pro.verron.officestamper.utils.WmlUtils;
14
15
import java.math.BigInteger;
16
import java.util.*;
17
18
import static java.util.stream.Collectors.toSet;
19
20
public class RemoveMalformedComments
21
        implements PreProcessor {
22
    private static final Logger log = LoggerFactory.getLogger(RemoveMalformedComments.class);
23
24
    @Override public void process(WordprocessingMLPackage document) {
25
        var commentElements = WmlUtils.extractCommentElements(document);
26
27
        var commentIds = new ArrayList<BigInteger>(commentElements.size());
28
        var openedCommentsIds = new ArrayDeque<BigInteger>();
29
        for (Child commentElement : commentElements) {
30 1 1. process : negated conditional → KILLED
            if (commentElement instanceof CommentRangeStart crs) {
31
                var lastOpenedCommentId = crs.getId();
32
                assert lastOpenedCommentId != null;
33
                log.debug("Comment {} opened.", lastOpenedCommentId);
34
                commentIds.add(lastOpenedCommentId);
35
                openedCommentsIds.add(lastOpenedCommentId);
36
            }
37 1 1. process : negated conditional → KILLED
            else if (commentElement instanceof CommentRangeEnd cre) {
38
                var lastClosedCommentId = cre.getId();
39
                assert lastClosedCommentId != null;
40
                log.debug("Comment {} closed.", lastClosedCommentId);
41
                commentIds.add(lastClosedCommentId);
42
43
                var lastOpenedCommentId = openedCommentsIds.pollLast();
44 1 1. process : negated conditional → KILLED
                if (!lastClosedCommentId.equals(lastOpenedCommentId)) {
45
                    log.debug("Comment {} is closing just after comment {} starts.",
46
                            lastClosedCommentId,
47
                            lastOpenedCommentId);
48
                    throw new OfficeStamperException("Cannot figure which comment contains the other !");
49
                }
50
            }
51 1 1. process : negated conditional → SURVIVED
            else if (commentElement instanceof R.CommentReference cr) {
52
                var commentId = cr.getId();
53
                assert commentId != null;
54
                log.debug("Comment {} referenced.", commentId);
55
                commentIds.add(commentId);
56
            }
57
        }
58
59
        log.debug("These comments have been opened, but never closed: {}", openedCommentsIds);
60
        var malformedCommentIds = new ArrayList<>(openedCommentsIds);
61
62
        var mainDocumentPart = document.getMainDocumentPart();
63
        Set<BigInteger> writtenCommentsId = Optional.ofNullable(mainDocumentPart.getCommentsPart())
64
                                                    .map(RemoveMalformedComments::tryGetCommentsPart)
65
                                                    .map(Comments::getComment)
66
                                                    .orElse(Collections.emptyList())
67
                                                    .stream()
68 2 1. lambda$process$0 : replaced boolean return with true for pro/verron/officestamper/preset/preprocessors/malformedcomments/RemoveMalformedComments::lambda$process$0 → SURVIVED
2. lambda$process$0 : negated conditional → KILLED
                                                    .filter(c -> !isEmpty(c))
69
                                                    .map(CTMarkup::getId)
70
                                                    .collect(toSet());
71
72
        commentIds.removeAll(writtenCommentsId);
73
74
        log.debug("These comments have been referenced in body, but have no related content: {}", commentIds);
75
        malformedCommentIds.addAll(commentIds);
76
77
        var crVisitor = new CommentReferenceRemoverVisitor(malformedCommentIds);
78
        var crsVisitor = new CommentRangeStartRemoverVisitor(malformedCommentIds);
79
        var creVisitor = new CommentRangeEndRemoverVisitor(malformedCommentIds);
80 1 1. process : removed call to org/docx4j/TraversalUtil::visit → SURVIVED
        TraversalUtil.visit(document, true, List.of(crVisitor, crsVisitor, creVisitor));
81 1 1. process : removed call to pro/verron/officestamper/preset/preprocessors/malformedcomments/CommentReferenceRemoverVisitor::run → SURVIVED
        crVisitor.run();
82 1 1. process : removed call to pro/verron/officestamper/preset/preprocessors/malformedcomments/CommentRangeStartRemoverVisitor::run → SURVIVED
        crsVisitor.run();
83 1 1. process : removed call to pro/verron/officestamper/preset/preprocessors/malformedcomments/CommentRangeEndRemoverVisitor::run → SURVIVED
        creVisitor.run();
84
    }
85
86
    private static Comments tryGetCommentsPart(CommentsPart commentsPart) {
87
        try {
88 1 1. tryGetCommentsPart : replaced return value with null for pro/verron/officestamper/preset/preprocessors/malformedcomments/RemoveMalformedComments::tryGetCommentsPart → KILLED
            return commentsPart.getContents();
89
        } catch (Docx4JException e) {
90
            throw new OfficeStamperException(e);
91
        }
92
    }
93
94
    private static boolean isEmpty(Comments.Comment c) {
95
        var content = c.getContent();
96 3 1. isEmpty : negated conditional → KILLED
2. isEmpty : negated conditional → KILLED
3. isEmpty : replaced boolean return with true for pro/verron/officestamper/preset/preprocessors/malformedcomments/RemoveMalformedComments::isEmpty → KILLED
        return content == null || content.isEmpty();
97
    }
98
99
}

Mutations

30

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

37

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

44

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

51

1.1
Location : process
Killed by : none
negated conditional → SURVIVED
Covering tests

68

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

2.2
Location : lambda$process$0
Killed by : none
replaced boolean return with true for pro/verron/officestamper/preset/preprocessors/malformedcomments/RemoveMalformedComments::lambda$process$0 → SURVIVED
Covering tests

80

1.1
Location : process
Killed by : none
removed call to org/docx4j/TraversalUtil::visit → SURVIVED
Covering tests

81

1.1
Location : process
Killed by : none
removed call to pro/verron/officestamper/preset/preprocessors/malformedcomments/CommentReferenceRemoverVisitor::run → SURVIVED
Covering tests

82

1.1
Location : process
Killed by : none
removed call to pro/verron/officestamper/preset/preprocessors/malformedcomments/CommentRangeStartRemoverVisitor::run → SURVIVED
Covering tests

83

1.1
Location : process
Killed by : none
removed call to pro/verron/officestamper/preset/preprocessors/malformedcomments/CommentRangeEndRemoverVisitor::run → SURVIVED
Covering tests

88

1.1
Location : tryGetCommentsPart
Killed by : pro.verron.officestamper.test.FailOnUnresolvedPlaceholderTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.FailOnUnresolvedPlaceholderTest]/[method:fails()]
replaced return value with null for pro/verron/officestamper/preset/preprocessors/malformedcomments/RemoveMalformedComments::tryGetCommentsPart → KILLED

96

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

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

3.3
Location : isEmpty
Killed by : pro.verron.officestamper.test.FailOnUnresolvedPlaceholderTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.FailOnUnresolvedPlaceholderTest]/[method:fails()]
replaced boolean return with true for pro/verron/officestamper/preset/preprocessors/malformedcomments/RemoveMalformedComments::isEmpty → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.1