TextualDocxPart.java

1
package pro.verron.officestamper.core;
2
3
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
4
import org.docx4j.openpackaging.parts.Part;
5
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
6
import org.docx4j.relationships.Relationship;
7
import org.docx4j.wml.*;
8
import pro.verron.officestamper.api.DocxPart;
9
import pro.verron.officestamper.api.Paragraph;
10
11
import java.util.Collection;
12
import java.util.List;
13
import java.util.Objects;
14
import java.util.stream.Stream;
15
16
/**
17
 * Represents a textual part of a DOCX document, encapsulating the content and structure of
18
 * the part while enabling various operations such as accessing paragraphs, runs, and related parts.
19
 * This class functions as a concrete implementation of the {@code DocxPart} interface.
20
 * It manages the association with the XML structure of a DOCX document.
21
 */
22
public final class TextualDocxPart
23
        implements DocxPart {
24
    private final WordprocessingMLPackage document;
25
    private final Part part;
26
    private final ContentAccessor contentAccessor;
27
28
    /**
29
     * Constructs a {@code TextualDocxPart} using the provided {@code document}.
30
     * This constructor initializes the instance with the main document part and content accessor
31
     * derived from the provided {@code WordprocessingMLPackage}.
32
     *
33
     * @param document the WordprocessingMLPackage representing the document to be processed.
34
     */
35
    public TextualDocxPart(WordprocessingMLPackage document) {
36
        this(document, document.getMainDocumentPart(), document.getMainDocumentPart());
37
    }
38
39
    /**
40
     * Constructs a {@code TextualDocxPart} using the specified {@code document}, {@code part},
41
     * and {@code contentAccessor}.
42
     *
43
     * @param document       the WordprocessingMLPackage representing the document to be processed.
44
     * @param part           the specific part of the document being processed.
45
     * @param contentAccessor the content accessor associated with the document part.
46
     */
47
    public TextualDocxPart(WordprocessingMLPackage document, Part part, ContentAccessor contentAccessor) {
48
        this.document = document;
49
        this.part = part;
50
        this.contentAccessor = contentAccessor;
51
    }
52
53
    /**
54
     * Returns the WordprocessingMLPackage instance representing the document
55
     * associated with this part.
56
     *
57
     * @return the WordprocessingMLPackage instance representing the document.
58
     */
59 1 1. document : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::document → KILLED
    public WordprocessingMLPackage document() {return document;}
60
61
    /**
62
     * Streams the parts of the document that match the specified relationship type, converting them
63
     * into instances of {@link TextualDocxPart}.
64
     *
65
     * @param type the type of relationship to filter and stream parts for.
66
     * @return a stream of {@link DocxPart} instances representing the filtered and processed parts
67
     *         of the document.
68
     */
69
    public Stream<DocxPart> streamParts(String type) {
70 1 1. streamParts : replaced return value with Stream.empty for pro/verron/officestamper/core/TextualDocxPart::streamParts → KILLED
        return document.getMainDocumentPart()
71
                       .getRelationshipsPart()
72
                       .getRelationshipsByType(type)
73
                       .stream()
74
                       .map(this::getPart)
75 1 1. lambda$streamParts$0 : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::lambda$streamParts$0 → KILLED
                       .map(p -> new TextualDocxPart(document, p, (ContentAccessor) p));
76
    }
77
78
    /**
79
     * Retrieves the part associated with the specified relationship from the relationships part.
80
     *
81
     * @param r the relationship for which the associated part is to be retrieved.
82
     * @return the part corresponding to the given relationship.
83
     */
84
    public Part getPart(Relationship r) {
85 1 1. getPart : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::getPart → KILLED
        return getRelationshipsPart().getPart(r);
86
    }
87
88
    private RelationshipsPart getRelationshipsPart() {
89 1 1. getRelationshipsPart : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::getRelationshipsPart → KILLED
        return part().getRelationshipsPart();
90
    }
91
92
    @Override
93 1 1. part : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::part → KILLED
    public Part part() {return part;}
94
95
    @Override
96
    public DocxPart from(ContentAccessor accessor) {
97 1 1. from : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::from → NO_COVERAGE
        return new TextualDocxPart(document, part, accessor);
98
    }
99
100
    @Override
101 1 1. content : replaced return value with Collections.emptyList for pro/verron/officestamper/core/TextualDocxPart::content → NO_COVERAGE
    public List<Object> content() {return contentAccessor.getContent();}
102
103
    /**
104
     * Streams all paragraphs contained in the document's main content or structured document tags (SDT).
105
     * The paragraphs are processed and transformed into instances of {@link Paragraph}.
106
     * This method combines paragraphs directly present in the document and paragraphs within SDT runs.
107
     *
108
     * @return a stream of {@link Paragraph} objects representing the paragraphs found within the document.
109
     */
110
    public Stream<Paragraph> streamParagraphs() {
111 1 1. streamParagraphs : replaced return value with Stream.empty for pro/verron/officestamper/core/TextualDocxPart::streamParagraphs → KILLED
        return Stream.concat(DocumentUtil.streamObjectElements(this, P.class)
112 1 1. lambda$streamParagraphs$1 : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::lambda$streamParagraphs$1 → KILLED
                                         .map(p -> StandardParagraph.from(this, p)),
113
                DocumentUtil.streamObjectElements(this, SdtRun.class)
114
                            .map(SdtRun::getSdtContent)
115
                            .filter(CTSdtContentRun.class::isInstance)
116
                            .map(CTSdtContentRun.class::cast)
117 1 1. lambda$streamParagraphs$2 : replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::lambda$streamParagraphs$2 → KILLED
                            .map(paragraph -> StandardParagraph.from(this, paragraph)));
118
    }
119
120
    @Override
121
    public Stream<R> streamRun() {
122 1 1. streamRun : replaced return value with Stream.empty for pro/verron/officestamper/core/TextualDocxPart::streamRun → KILLED
        return DocumentUtil.streamObjectElements(this, P.class)
123
                           .map(P::getContent)
124
                           .flatMap(Collection::stream)
125
                           .filter(R.class::isInstance)
126
                           .map(R.class::cast);
127
    }
128
129
    @Override
130
    public int hashCode() {
131 1 1. hashCode : replaced int return with 0 for pro/verron/officestamper/core/TextualDocxPart::hashCode → NO_COVERAGE
        return Objects.hash(document, part, contentAccessor);
132
    }
133
134
    @Override
135
    public boolean equals(Object obj) {
136 2 1. equals : replaced boolean return with false for pro/verron/officestamper/core/TextualDocxPart::equals → NO_COVERAGE
2. equals : negated conditional → NO_COVERAGE
        if (obj == this) return true;
137 3 1. equals : negated conditional → NO_COVERAGE
2. equals : negated conditional → NO_COVERAGE
3. equals : replaced boolean return with true for pro/verron/officestamper/core/TextualDocxPart::equals → NO_COVERAGE
        if (obj == null || obj.getClass() != this.getClass()) return false;
138
        var that = (TextualDocxPart) obj;
139 4 1. equals : negated conditional → NO_COVERAGE
2. equals : negated conditional → NO_COVERAGE
3. equals : replaced boolean return with true for pro/verron/officestamper/core/TextualDocxPart::equals → NO_COVERAGE
4. equals : negated conditional → NO_COVERAGE
        return Objects.equals(this.document, that.document) && Objects.equals(this.part, that.part) && Objects.equals(
140
                this.contentAccessor,
141
                that.contentAccessor);
142
    }
143
144
    @Override
145
    public String toString() {
146 1 1. toString : replaced return value with "" for pro/verron/officestamper/core/TextualDocxPart::toString → NO_COVERAGE
        return "DocxPart{doc=%s, part=%s}".formatted(document.name(), part.getPartName());
147
    }
148
149
}

Mutations

59

1.1
Location : document
Killed by : pro.verron.officestamper.test.ResolutionTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ResolutionTest]/[test-template:testCustomResolution(java.lang.String, boolean, boolean, boolean, boolean, boolean, java.lang.String, boolean, java.lang.String)]/[test-template-invocation:#29]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::document → KILLED

70

1.1
Location : streamParts
Killed by : pro.verron.officestamper.test.HeaderAndFooterTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.HeaderAndFooterTest]/[test-template:placeholders(pro.verron.officestamper.test.ContextFactory)]/[test-template-invocation:#2]
replaced return value with Stream.empty for pro/verron/officestamper/core/TextualDocxPart::streamParts → KILLED

75

1.1
Location : lambda$streamParts$0
Killed by : pro.verron.officestamper.test.HeaderAndFooterTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.HeaderAndFooterTest]/[test-template:placeholders(pro.verron.officestamper.test.ContextFactory)]/[test-template-invocation:#2]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::lambda$streamParts$0 → KILLED

85

1.1
Location : getPart
Killed by : pro.verron.officestamper.test.HeaderAndFooterTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.HeaderAndFooterTest]/[test-template:placeholders(pro.verron.officestamper.test.ContextFactory)]/[test-template-invocation:#2]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::getPart → KILLED

89

1.1
Location : getRelationshipsPart
Killed by : pro.verron.officestamper.test.HeaderAndFooterTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.HeaderAndFooterTest]/[test-template:placeholders(pro.verron.officestamper.test.ContextFactory)]/[test-template-invocation:#2]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::getRelationshipsPart → KILLED

93

1.1
Location : part
Killed by : pro.verron.officestamper.test.ResolutionTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ResolutionTest]/[test-template:testCustomResolution(java.lang.String, boolean, boolean, boolean, boolean, boolean, java.lang.String, boolean, java.lang.String)]/[test-template-invocation:#29]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::part → KILLED

97

1.1
Location : from
Killed by : none
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::from → NO_COVERAGE

101

1.1
Location : content
Killed by : none
replaced return value with Collections.emptyList for pro/verron/officestamper/core/TextualDocxPart::content → NO_COVERAGE

111

1.1
Location : streamParagraphs
Killed by : pro.verron.officestamper.test.ResolutionTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ResolutionTest]/[test-template:testCustomResolution(java.lang.String, boolean, boolean, boolean, boolean, boolean, java.lang.String, boolean, java.lang.String)]/[test-template-invocation:#29]
replaced return value with Stream.empty for pro/verron/officestamper/core/TextualDocxPart::streamParagraphs → KILLED

112

1.1
Location : lambda$streamParagraphs$1
Killed by : pro.verron.officestamper.test.ResolutionTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ResolutionTest]/[test-template:testCustomResolution(java.lang.String, boolean, boolean, boolean, boolean, boolean, java.lang.String, boolean, java.lang.String)]/[test-template-invocation:#29]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::lambda$streamParagraphs$1 → KILLED

117

1.1
Location : lambda$streamParagraphs$2
Killed by : pro.verron.officestamper.test.DefaultTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DefaultTests]/[test-template:features(java.lang.String, pro.verron.officestamper.api.OfficeStamperConfiguration, java.lang.Object, java.io.InputStream, java.lang.String)]/[test-template-invocation:#36]
replaced return value with null for pro/verron/officestamper/core/TextualDocxPart::lambda$streamParagraphs$2 → KILLED

122

1.1
Location : streamRun
Killed by : pro.verron.officestamper.test.DefaultTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DefaultTests]/[test-template:features(java.lang.String, pro.verron.officestamper.api.OfficeStamperConfiguration, java.lang.Object, java.io.InputStream, java.lang.String)]/[test-template-invocation:#2]
replaced return value with Stream.empty for pro/verron/officestamper/core/TextualDocxPart::streamRun → KILLED

131

1.1
Location : hashCode
Killed by : none
replaced int return with 0 for pro/verron/officestamper/core/TextualDocxPart::hashCode → NO_COVERAGE

136

1.1
Location : equals
Killed by : none
replaced boolean return with false for pro/verron/officestamper/core/TextualDocxPart::equals → NO_COVERAGE

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

137

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

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

3.3
Location : equals
Killed by : none
replaced boolean return with true for pro/verron/officestamper/core/TextualDocxPart::equals → NO_COVERAGE

139

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

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

3.3
Location : equals
Killed by : none
replaced boolean return with true for pro/verron/officestamper/core/TextualDocxPart::equals → NO_COVERAGE

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

146

1.1
Location : toString
Killed by : none
replaced return value with "" for pro/verron/officestamper/core/TextualDocxPart::toString → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.20.0