WmlFactory.java

1
package pro.verron.officestamper.utils.wml;
2
3
import jakarta.xml.bind.JAXBElement;
4
import jakarta.xml.bind.JAXBException;
5
import org.docx4j.UnitsOfMeasurement;
6
import org.docx4j.XmlUtils;
7
import org.docx4j.dml.wordprocessingDrawing.Inline;
8
import org.docx4j.model.structure.PageDimensions;
9
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
10
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
11
import org.docx4j.openpackaging.parts.WordprocessingML.CommentsPart;
12
import org.docx4j.relationships.Relationship;
13
import org.docx4j.wml.*;
14
import org.docx4j.wml.Comments.Comment;
15
import pro.verron.officestamper.utils.UtilsException;
16
17
import java.awt.geom.Dimension2D;
18
import java.math.BigInteger;
19
import java.util.*;
20
21
import static java.util.Arrays.asList;
22
import static java.util.stream.Collectors.toCollection;
23
24
/// Utility class for creating and configuring various WordML (WML) elements. Provides static methods to generate
25
/// paragraphs, runs, comments, text, and other WML structures. This is intended for handling Office Open XML documents
26
/// programmatically.
27
public class WmlFactory {
28
    private static final Random RANDOM = new Random();
29
30
    private WmlFactory() {
31
        throw new UtilsException("Utility class shouldn't be instantiated");
32
    }
33
34
    /// Creates a new comment with the provided value.
35
    ///
36
    /// @param id The ID to assign to the comment.
37
    /// @param value The string value to be included in the comment.
38
    ///
39
    /// @return A new [Comment] object containing the provided value.
40
    public static Comment newComment(BigInteger id, String value) {
41
        var comment = new Comment();
42 1 1. newComment : removed call to org/docx4j/wml/Comments$Comment::setId → NO_COVERAGE
        comment.setId(id);
43
        var commentContent = comment.getContent();
44
        commentContent.add(newParagraph(value));
45 1 1. newComment : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newComment → NO_COVERAGE
        return comment;
46
    }
47
48
    /// Creates a new paragraph containing the provided string value.
49
    ///
50
    /// @param value The string value to be added to the new paragraph.
51
    ///
52
    /// @return A new [P] containing the provided string value.
53
    public static P newParagraph(String value) {
54 1 1. newParagraph : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newParagraph → NO_COVERAGE
        return newParagraph(newRun(value));
55
    }
56
57
    /// Creates a new paragraph containing the provided run.
58
    ///
59
    /// @param run The [R] object (run) to be included in the new paragraph.
60
    ///
61
    /// @return A new [P] containing the provided run.
62
    public static P newParagraph(R run) {
63 1 1. newParagraph : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newParagraph → NO_COVERAGE
        return newParagraph(List.of(run));
64
    }
65
66
    /// Creates a new run containing the provided string value.
67
    ///
68
    /// @param value The string value to be included in the new run.
69
    ///
70
    /// @return A new [R] containing the provided string value.
71
    public static R newRun(String value) {
72 1 1. newRun : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newRun → NO_COVERAGE
        return newRun(newText(value));
73
    }
74
75
    /// Creates a new paragraph containing the provided list of values.
76
    ///
77
    /// @param values A list of objects to be added to the new paragraph. These objects populate the content of
78
    ///         the paragraph.
79
    ///
80
    /// @return A new [P] containing the provided values.
81
    public static P newParagraph(List<?> values) {
82
        var paragraph = new P();
83
        var paragraphContent = paragraph.getContent();
84
        paragraphContent.addAll(values);
85 1 1. newParagraph : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newParagraph → NO_COVERAGE
        return paragraph;
86
    }
87
88
    /// Creates a new run containing a single text object.
89
    ///
90
    /// @param value The [Text] object to be included in the new run.
91
    ///
92
    /// @return A new [R] encapsulating the provided text object.
93
    public static R newRun(Text value) {
94 1 1. newRun : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newRun → NO_COVERAGE
        return newRun(List.of(value));
95
    }
96
97
    /// Creates a new [Text] object with the specified value, preserving spaces.
98
    ///
99
    /// @param value The string value to be set in the new [Text] object.
100
    ///
101
    /// @return A new [Text] object containing the provided value with space preserved.
102
    public static Text newText(String value) {
103
        var text = new Text();
104 1 1. newText : removed call to org/docx4j/wml/Text::setValue → NO_COVERAGE
        text.setValue(value);
105 1 1. newText : removed call to org/docx4j/wml/Text::setSpace → NO_COVERAGE
        text.setSpace("preserve");
106 1 1. newText : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newText → NO_COVERAGE
        return text;
107
    }
108
109
    /// Creates a new run containing the provided values deemed worth keeping.
110
    ///
111
    /// @param values A list of objects to be added to the new run. Objects are filtered based on a predefined
112
    ///         criteria to determine if they are worth keeping.
113
    ///
114
    /// @return A new [R] containing the filtered values.
115
    public static R newRun(List<Object> values) {
116
        var run = new R();
117
        var runContent = run.getContent();
118
        runContent.addAll(values.stream()
119
                                .filter(WmlFactory::worthKeeping)
120
                                .collect(toCollection(ArrayList::new)));
121 1 1. newRun : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newRun → NO_COVERAGE
        return run;
122
    }
123
124
    private static boolean worthKeeping(Object o) {
125 3 1. worthKeeping : negated conditional → NO_COVERAGE
2. worthKeeping : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlFactory::worthKeeping → NO_COVERAGE
3. worthKeeping : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlFactory::worthKeeping → NO_COVERAGE
        if (o instanceof Text text) return worthKeeping(text);
126 1 1. worthKeeping : replaced boolean return with false for pro/verron/officestamper/utils/wml/WmlFactory::worthKeeping → NO_COVERAGE
        else return true;
127
    }
128
129
    private static boolean worthKeeping(Text text) {
130
        var textValue = text.getValue();
131 2 1. worthKeeping : negated conditional → NO_COVERAGE
2. worthKeeping : replaced boolean return with true for pro/verron/officestamper/utils/wml/WmlFactory::worthKeeping → NO_COVERAGE
        return !textValue.isEmpty();
132
    }
133
134
    /// Creates a new [Body] object containing the provided elements.
135
    ///
136
    /// @param elements A list of objects to be added to the new [Body].
137
    ///
138
    /// @return A new [Body] containing the provided elements.
139
    public static Body newBody(List<Object> elements) {
140
        Body body = new Body();
141
        var bodyContent = body.getContent();
142
        bodyContent.addAll(elements);
143 1 1. newBody : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newBody → NO_COVERAGE
        return body;
144
    }
145
146
    /// Creates a new paragraph containing the provided text values.
147
    ///
148
    /// @param texts The array of string values to be included in the new paragraph.
149
    ///
150
    /// @return A new [P] containing the provided text values.
151
    public static P newParagraph(String... texts) {
152 1 1. newParagraph : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newParagraph → NO_COVERAGE
        return newParagraph(Arrays.stream(texts)
153
                                  .map(WmlFactory::newRun)
154
                                  .toList());
155
    }
156
157
    /// Creates a new [PPr] (paragraph properties) object.
158
    ///
159
    /// @return A new [PPr] object.
160
    public static PPr newPPr() {
161 1 1. newPPr : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newPPr → NO_COVERAGE
        return new PPr();
162
    }
163
164
    /// Creates a new [Comments] object and populates it with a list of [Comment] objects.
165
    ///
166
    /// @param list A list of [Comment] objects to be added to the new [Comments] object.
167
    ///
168
    /// @return A new [Comments] object containing the provided [Comment] objects.
169
    public static Comments newComments(List<Comment> list) {
170
        Comments comments = new Comments();
171
        List<Comment> commentList = comments.getComment();
172
        commentList.addAll(list);
173 1 1. newComments : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newComments → NO_COVERAGE
        return comments;
174
    }
175
176
    /// Creates a new Inline object representing an image with the specified parameters, properly formatted for use
177
    /// in Word documents. The image is defined using WordprocessingML and associated relationships.
178
    ///
179
    /// @param relationship The relationship object that provides the relationship ID for the image.
180
    /// @param filenameHint A hint for the file name of the image, used to set display names in the document.
181
    /// @param altText The alternate text for the image, used for accessibility purposes.
182
    /// @param scale The scale object that defines the dimensions (cx, cy) of the image in EMUs (English Metric Units).
183
    /// @return An Inline object that represents the formatted image element to be embedded in the document.
184
    /// @throws UtilsException If any error occurs during the creation of the Inline object.
185
    public static Inline newImgInline(Relationship relationship, String filenameHint, String altText, Scale scale) {
186
        // creating random ids assuming unicity, id must not be too large otherwise Word cannot open the document
187
        var id1 = RANDOM.nextLong(100_000L);
188
        var id2 = RANDOM.nextInt(100_000);
189
        try {
190
            String ml = """
191
                    <wp:inline distT="0" distB="0" distL="0" distR="0"
192
                      xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
193
                      xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
194
                      xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
195
                      <wp:extent cx="${cx}" cy="${cy}"/>
196
                      <wp:effectExtent l="0" t="0" r="0" b="0"/>
197
                      <wp:docPr id="${id1}" name="${filenameHint}" descr="${altText}"/>
198
                      <wp:cNvGraphicFramePr>
199
                        <a:graphicFrameLocks noChangeAspect="1"
200
                          xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/>
201
                      </wp:cNvGraphicFramePr>
202
                      <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
203
                        <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
204
                          <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
205
                            <pic:nvPicPr>
206
                              <pic:cNvPr id="${id2}" name="${filenameHint}"/>
207
                              <pic:cNvPicPr/>
208
                            </pic:nvPicPr>
209
                            <pic:blipFill><a:blip r:embed="${rEmbedId}"/>
210
                                <a:stretch><a:fillRect/></a:stretch>
211
                            </pic:blipFill>
212
                            <pic:spPr>
213
                              <a:xfrm>
214
                                <a:off x="0" y="0"/>
215
                                <a:ext cx="${cx}" cy="${cy}"/>
216
                              </a:xfrm>
217
                              <a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
218
                            </pic:spPr>
219
                          </pic:pic>
220
                        </a:graphicData>
221
                      </a:graphic>
222
                    </wp:inline>""";
223
            var mappings = new HashMap<String, String>();
224
            mappings.put("cx", Long.toString(scale.cx()));
225
            mappings.put("cy", Long.toString(scale.cy()));
226
            mappings.put("filenameHint", filenameHint);
227
            mappings.put("altText", altText);
228
            mappings.put("rEmbedId", relationship.getId());
229
            mappings.put("id1", Long.toString(id1));
230
            mappings.put("id2", Integer.toString(id2));
231
            var jaxbElement = (JAXBElement<?>) XmlUtils.unmarshallFromTemplate(ml, mappings);
232 1 1. newImgInline : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newImgInline → NO_COVERAGE
            return (Inline) jaxbElement.getValue();
233
        } catch (Exception e) {
234
            throw new UtilsException(e);
235
        }
236
    }
237
238
    public static Scale computeScale(PageDimensions pageDimensions, Integer maxWidth, Dimension2D dpx) {
239
        double writableWidthTwips = pageDimensions.getWritableWidthTwips();
240 4 1. computeScale : changed conditional boundary → NO_COVERAGE
2. computeScale : negated conditional → NO_COVERAGE
3. computeScale : changed conditional boundary → NO_COVERAGE
4. computeScale : negated conditional → NO_COVERAGE
        if (maxWidth > 0 && maxWidth < writableWidthTwips) writableWidthTwips = maxWidth;
241
        double imageWidthTwips = UnitsOfMeasurement.pxToTwipDouble(dpx.getWidth());
242
        double imageHeightTwips = UnitsOfMeasurement.pxToTwipDouble(dpx.getHeight());
243
        long cx;
244
        long cy;
245 2 1. computeScale : changed conditional boundary → NO_COVERAGE
2. computeScale : negated conditional → NO_COVERAGE
        if (imageWidthTwips > writableWidthTwips) {
246
            cx = UnitsOfMeasurement.twipToEMU(writableWidthTwips);
247 2 1. computeScale : Replaced double multiplication with division → NO_COVERAGE
2. computeScale : Replaced double division with multiplication → NO_COVERAGE
            cy = UnitsOfMeasurement.twipToEMU(imageHeightTwips * writableWidthTwips / imageWidthTwips);
248
        }
249
        else {
250
            cx = UnitsOfMeasurement.twipToEMU(imageWidthTwips);
251
            cy = UnitsOfMeasurement.twipToEMU(imageHeightTwips);
252
        }
253 1 1. computeScale : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::computeScale → NO_COVERAGE
        return new Scale(cx, cy);
254
    }
255
256
    /// Creates a new run containing a single drawing.
257
    ///
258
    /// @param value The [Drawing] object to be included in the new run.
259
    ///
260
    /// @return A new [R] encapsulating the provided drawing.
261
    public static R newRun(Drawing value) {
262 1 1. newRun : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newRun → NO_COVERAGE
        return newRun(List.of(value));
263
    }
264
265
    /// Creates a new [Drawing] object containing the provided [Inline] object.
266
    ///
267
    /// @param inline The [Inline] object to be contained within the new [Drawing].
268
    ///
269
    /// @return A new [Drawing] object encapsulating the provided inline object.
270
    public static Drawing newDrawing(Inline inline) {
271
        var drawing = new Drawing();
272
        var anchorOrInline = drawing.getAnchorOrInline();
273
        anchorOrInline.add(inline);
274 1 1. newDrawing : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newDrawing → NO_COVERAGE
        return drawing;
275
    }
276
277
    /// Creates a new [CommentRangeStart] object with the specified ID and parent.
278
    ///
279
    /// @param id The unique identifier for the [CommentRangeStart] object.
280
    /// @param parent The parent element ([P]) to which this [CommentRangeStart] belongs.
281
    ///
282
    /// @return A new [CommentRangeStart] object with the specified ID and parent.
283
    public static CommentRangeStart newCommentRangeStart(BigInteger id, ContentAccessor parent) {
284
        var commentRangeStart = new CommentRangeStart();
285 1 1. newCommentRangeStart : removed call to org/docx4j/wml/CommentRangeStart::setId → NO_COVERAGE
        commentRangeStart.setId(id);
286 1 1. newCommentRangeStart : removed call to org/docx4j/wml/CommentRangeStart::setParent → NO_COVERAGE
        commentRangeStart.setParent(parent);
287 1 1. newCommentRangeStart : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newCommentRangeStart → NO_COVERAGE
        return commentRangeStart;
288
    }
289
290
    /// Creates a new [CommentRangeEnd] object with the specified ID and parent.
291
    ///
292
    /// @param id The unique identifier for the [CommentRangeEnd] object.
293
    /// @param parent The parent element ([P]) to which this [CommentRangeEnd] belongs.
294
    ///
295
    /// @return A new [CommentRangeEnd] object with the specified ID and parent.
296
    public static CommentRangeEnd newCommentRangeEnd(BigInteger id, ContentAccessor parent) {
297
        var commentRangeEnd = new CommentRangeEnd();
298 1 1. newCommentRangeEnd : removed call to org/docx4j/wml/CommentRangeEnd::setId → NO_COVERAGE
        commentRangeEnd.setId(id);
299 1 1. newCommentRangeEnd : removed call to org/docx4j/wml/CommentRangeEnd::setParent → NO_COVERAGE
        commentRangeEnd.setParent(parent);
300 1 1. newCommentRangeEnd : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newCommentRangeEnd → NO_COVERAGE
        return commentRangeEnd;
301
    }
302
303
    /// Creates a new [R.CommentReference] object with the specified ID and parent.
304
    ///
305
    /// @param id The unique identifier for the [R.CommentReference].
306
    /// @param parent The parent element ([P]) to which this [R.CommentReference] belongs.
307
    ///
308
    /// @return A new [R.CommentReference] object with the specified ID and parent.
309
    public static R.CommentReference newCommentReference(BigInteger id, ContentAccessor parent) {
310
        var commentReference = new R.CommentReference();
311 1 1. newCommentReference : removed call to org/docx4j/wml/R$CommentReference::setId → NO_COVERAGE
        commentReference.setId(id);
312 1 1. newCommentReference : removed call to org/docx4j/wml/R$CommentReference::setParent → NO_COVERAGE
        commentReference.setParent(parent);
313 1 1. newCommentReference : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newCommentReference → NO_COVERAGE
        return commentReference;
314
    }
315
316
    /// Creates a new table object.
317
    ///
318
    /// @return A new instance of [Tbl].
319
    public static Tbl newTbl() {
320 1 1. newTbl : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newTbl → NO_COVERAGE
        return new Tbl();
321
    }
322
323
    /// Creates a new cell object.
324
    ///
325
    /// @return A new instance of [Tc].
326
    public static Tc newCell() {
327 1 1. newCell : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newCell → NO_COVERAGE
        return new Tc();
328
    }
329
330
    /// Creates a new row object.
331
    ///
332
    /// @return A new instance of [Tr].
333
    public static Tr newRow() {
334 1 1. newRow : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newRow → NO_COVERAGE
        return new Tr();
335
    }
336
337
    /// Creates a new [WordprocessingMLPackage] object initialized with a main document part, and an empty comments
338
    /// part.
339
    ///
340
    /// @return A new instance of [WordprocessingMLPackage].
341
    public static WordprocessingMLPackage newWord() {
342
        try {
343
            var aPackage = WordprocessingMLPackage.createPackage();
344
            var mainDocumentPart = aPackage.getMainDocumentPart();
345
            var cp = newCommentsPart();
346 1 1. newWord : removed call to org/docx4j/openpackaging/parts/WordprocessingML/CommentsPart::init → NO_COVERAGE
            cp.init();
347 1 1. newWord : removed call to org/docx4j/openpackaging/parts/WordprocessingML/CommentsPart::setJaxbElement → NO_COVERAGE
            cp.setJaxbElement(newComments());
348
            mainDocumentPart.addTargetPart(cp);
349 1 1. newWord : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newWord → NO_COVERAGE
            return aPackage;
350
        } catch (InvalidFormatException e) {
351
            throw new UtilsException(e);
352
        }
353
    }
354
355
    /// Creates a new [CommentsPart] object. This method attempts to create a new instance of [CommentsPart]. If an
356
    /// [InvalidFormatException] occurs during the creation process, it wraps the exception in an [UtilsException] and
357
    /// throws it.
358
    ///
359
    /// @return A new instance of [CommentsPart].
360
    public static CommentsPart newCommentsPart() {
361
        try {
362 1 1. newCommentsPart : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newCommentsPart → NO_COVERAGE
            return new CommentsPart();
363
        } catch (InvalidFormatException e) {
364
            throw new UtilsException(e);
365
        }
366
    }
367
368
    private static Comments newComments() {
369 1 1. newComments : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newComments → NO_COVERAGE
        return new Comments();
370
    }
371
372
    /// Creates a new [Br] (break) object with text wrapping enabled.
373
    ///
374
    /// @return A new [Br] object with text wrapping type and no clear attribute set.
375
    public static Br newBr() {
376
        var br = new Br();
377 1 1. newBr : removed call to org/docx4j/wml/Br::setType → NO_COVERAGE
        br.setType(STBrType.TEXT_WRAPPING);
378 1 1. newBr : removed call to org/docx4j/wml/Br::setClear → NO_COVERAGE
        br.setClear(null);
379 1 1. newBr : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newBr → NO_COVERAGE
        return br;
380
    }
381
382
    /// Creates a new smart tag run with the specified element, run and attribute.
383
    ///
384
    /// @param element The element name for the smart tag.
385
    /// @param attribute The [CTAttr] to add to the smart tag properties.
386
    /// @param object The [Object] to include in the smart tag content.
387
    ///
388
    /// @return A new [CTSmartTagRun] object configured with the specified parameters.
389
    public static CTSmartTagRun newSmartTag(String element, CTAttr attribute, Object... object) {
390
        var smartTag = new CTSmartTagRun();
391 1 1. newSmartTag : removed call to org/docx4j/wml/CTSmartTagRun::setElement → NO_COVERAGE
        smartTag.setElement(element);
392
393
        var smartTagPr = new CTSmartTagPr();
394 1 1. newSmartTag : removed call to org/docx4j/wml/CTSmartTagRun::setSmartTagPr → NO_COVERAGE
        smartTag.setSmartTagPr(smartTagPr);
395
396
        var smartTagPrAttr = smartTagPr.getAttr();
397
        smartTagPrAttr.add(attribute);
398
399
        var smartTagContent = smartTag.getContent();
400
        smartTagContent.addAll(asList(object));
401 1 1. newSmartTag : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newSmartTag → NO_COVERAGE
        return smartTag;
402
    }
403
404
    /// Creates a new [CTAttr] object with the specified name and value.
405
    ///
406
    /// @param name The name of the attribute.
407
    /// @param value The value of the attribute.
408
    ///
409
    /// @return A new [CTAttr] object with the specified name and value.
410
    public static CTAttr newCtAttr(String name, String value) {
411
        var ctAttr = new CTAttr();
412 1 1. newCtAttr : removed call to org/docx4j/wml/CTAttr::setName → NO_COVERAGE
        ctAttr.setName(name);
413 1 1. newCtAttr : removed call to org/docx4j/wml/CTAttr::setVal → NO_COVERAGE
        ctAttr.setVal(value);
414 1 1. newCtAttr : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newCtAttr → NO_COVERAGE
        return ctAttr;
415
    }
416
417
    /// Creates a new [Pict] object containing the provided inner object.
418
    ///
419
    /// @param innerObj The object to be included in the new pict element.
420
    ///
421
    /// @return A new [Pict] object containing the provided inner object.
422
    public static Object newPict(Object innerObj) {
423
        var pict = new Pict();
424
        pict.getAnyAndAny()
425
            .add(innerObj);
426 1 1. newPict : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newPict → KILLED
        return pict;
427
    }
428
429
    /// Creates a new [SdtBlock] object containing the provided inner object.
430
    ///
431
    /// @param innerObj The object to be included in the new structured document tag block.
432
    ///
433
    /// @return A new [SdtBlock] object containing the provided inner object.
434
    public static SdtBlock newSdtBlock(Object innerObj) {
435
        var block = new SdtContentBlock();
436
        var blockContent = block.getContent();
437
        blockContent.add(innerObj);
438
        var sdtBlock = new SdtBlock();
439 1 1. newSdtBlock : removed call to org/docx4j/wml/SdtBlock::setSdtContent → KILLED
        sdtBlock.setSdtContent(block);
440 1 1. newSdtBlock : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newSdtBlock → KILLED
        return sdtBlock;
441
    }
442
443
    /// Creates a new [SdtRun] object containing the provided inner object.
444
    ///
445
    /// @param innerObj The object to be included in the new structured document tag run.
446
    ///
447
    /// @return A new [SdtRun] object containing the provided inner object.
448
    public static SdtRun newSdtRun(Object innerObj) {
449
        var sdtContentRun = new CTSdtContentRun();
450
        var sdtContentRunContent = sdtContentRun.getContent();
451
        sdtContentRunContent.add(innerObj);
452
        var sdtRun = new SdtRun();
453 1 1. newSdtRun : removed call to org/docx4j/wml/SdtRun::setSdtContent → KILLED
        sdtRun.setSdtContent(sdtContentRun);
454 1 1. newSdtRun : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newSdtRun → KILLED
        return sdtRun;
455
    }
456
457
    public static Inline newSVGInline(Relationship relationship, String altText, String filenameHint, Scale scale)
458
            throws JAXBException {
459
        String template = """
460
                <wp:inline distB="0" distL="0" distR="0" distT="0"
461
                xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
462
                                  xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
463
                                  xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
464
                                  xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
465
                                  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
466
                  <wp:extent cx="${cx}" cy="${cy}"/>
467
                  <wp:effectExtent b="0" l="0" r="0" t="0"/>
468
                  <wp:docPr id="${id1}" name="${filenameHint}" descr="${altText}"/>
469
                  <wp:cNvGraphicFramePr>
470
                    <a:graphicFrameLocks noChangeAspect="true"/>
471
                  </wp:cNvGraphicFramePr>
472
                  <a:graphic>
473
                    <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
474
                      <pic:pic>
475
                        <pic:nvPicPr>
476
                          <pic:cNvPr id="${id2}" name="${filenameHint}"/>
477
                          <pic:cNvPicPr/>
478
                        </pic:nvPicPr>
479
                        <pic:blipFill>
480
                          <a:blip>
481
                            <a:extLst>
482
                              <a:ext uri="{96DAC541-7B7A-43D3-8B79-37D633B846F1}">
483
                                <asvg:svgBlip
484
                                  xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main"
485
                                  r:embed="${relId}"/>
486
                              </a:ext>
487
                            </a:extLst>
488
                          </a:blip>
489
                          <a:stretch><a:fillRect/></a:stretch>
490
                        </pic:blipFill>
491
                        <pic:spPr>
492
                          <a:xfrm>
493
                            <a:off x="0" y="0"/>
494
                            <a:ext cx="${cx}" cy="${cy}"/>
495
                          </a:xfrm>
496
                          <a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
497
                        </pic:spPr>
498
                      </pic:pic>
499
                    </a:graphicData>
500
                  </a:graphic>
501
                </wp:inline>
502
                """;
503
504
        var id1 = RANDOM.nextLong(100_000L);
505
        var id2 = RANDOM.nextInt(100_000);
506
507
        var mappings = new HashMap<String, String>();
508
        mappings.put("cx", Long.toString(scale.cx()));
509
        mappings.put("cy", Long.toString(scale.cy()));
510
        mappings.put("id1", Long.toString(id1));
511
        mappings.put("id2", Integer.toString(id2));
512
        mappings.put("filenameHint", filenameHint);
513
        mappings.put("altText", altText);
514
        mappings.put("relId", relationship.getId());
515
516
        var jaxbElement = (JAXBElement<?>) XmlUtils.unmarshallFromTemplate(template, mappings);
517 1 1. newSVGInline : replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newSVGInline → NO_COVERAGE
        return (Inline) jaxbElement.getValue();
518
    }
519
520
    public record Scale(long cx, long cy) {}
521
}

Mutations

42

1.1
Location : newComment
Killed by : none
removed call to org/docx4j/wml/Comments$Comment::setId → NO_COVERAGE

45

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

54

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

63

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

72

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

85

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

94

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

104

1.1
Location : newText
Killed by : none
removed call to org/docx4j/wml/Text::setValue → NO_COVERAGE

105

1.1
Location : newText
Killed by : none
removed call to org/docx4j/wml/Text::setSpace → NO_COVERAGE

106

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

121

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

125

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

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

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

126

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

131

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

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

143

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

152

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

161

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

173

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

232

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

240

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

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

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

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

245

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

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

247

1.1
Location : computeScale
Killed by : none
Replaced double multiplication with division → NO_COVERAGE

2.2
Location : computeScale
Killed by : none
Replaced double division with multiplication → NO_COVERAGE

253

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

262

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

274

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

285

1.1
Location : newCommentRangeStart
Killed by : none
removed call to org/docx4j/wml/CommentRangeStart::setId → NO_COVERAGE

286

1.1
Location : newCommentRangeStart
Killed by : none
removed call to org/docx4j/wml/CommentRangeStart::setParent → NO_COVERAGE

287

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

298

1.1
Location : newCommentRangeEnd
Killed by : none
removed call to org/docx4j/wml/CommentRangeEnd::setId → NO_COVERAGE

299

1.1
Location : newCommentRangeEnd
Killed by : none
removed call to org/docx4j/wml/CommentRangeEnd::setParent → NO_COVERAGE

300

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

311

1.1
Location : newCommentReference
Killed by : none
removed call to org/docx4j/wml/R$CommentReference::setId → NO_COVERAGE

312

1.1
Location : newCommentReference
Killed by : none
removed call to org/docx4j/wml/R$CommentReference::setParent → NO_COVERAGE

313

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

320

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

327

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

334

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

346

1.1
Location : newWord
Killed by : none
removed call to org/docx4j/openpackaging/parts/WordprocessingML/CommentsPart::init → NO_COVERAGE

347

1.1
Location : newWord
Killed by : none
removed call to org/docx4j/openpackaging/parts/WordprocessingML/CommentsPart::setJaxbElement → NO_COVERAGE

349

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

362

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

369

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

377

1.1
Location : newBr
Killed by : none
removed call to org/docx4j/wml/Br::setType → NO_COVERAGE

378

1.1
Location : newBr
Killed by : none
removed call to org/docx4j/wml/Br::setClear → NO_COVERAGE

379

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

391

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

394

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

401

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

412

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

413

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

414

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

426

1.1
Location : newPict
Killed by : pro.verron.officestamper.utils.wml.DocxIteratorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.utils.wml.DocxIteratorTest]/[method:testNextHandlesPictStructure()]
replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newPict → KILLED

439

1.1
Location : newSdtBlock
Killed by : pro.verron.officestamper.utils.wml.DocxIteratorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.utils.wml.DocxIteratorTest]/[method:testNextHandlesSdtBlockStructure()]
removed call to org/docx4j/wml/SdtBlock::setSdtContent → KILLED

440

1.1
Location : newSdtBlock
Killed by : pro.verron.officestamper.utils.wml.DocxIteratorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.utils.wml.DocxIteratorTest]/[method:testNextHandlesSdtBlockStructure()]
replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newSdtBlock → KILLED

453

1.1
Location : newSdtRun
Killed by : pro.verron.officestamper.utils.wml.DocxIteratorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.utils.wml.DocxIteratorTest]/[method:testNextHandlesSdtRunStructure()]
removed call to org/docx4j/wml/SdtRun::setSdtContent → KILLED

454

1.1
Location : newSdtRun
Killed by : pro.verron.officestamper.utils.wml.DocxIteratorTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.utils.wml.DocxIteratorTest]/[method:testNextHandlesSdtRunStructure()]
replaced return value with null for pro/verron/officestamper/utils/wml/WmlFactory::newSdtRun → KILLED

517

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

Active mutators

Tests examined


Report generated by PIT 1.23.1 support