RepeatDocPartProcessor.java

1
package pro.verron.officestamper.preset.processors.repeatdocpart;
2
3
import org.docx4j.openpackaging.exceptions.Docx4JException;
4
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
5
import org.docx4j.wml.ContentAccessor;
6
import org.docx4j.wml.P;
7
import org.docx4j.wml.R;
8
import org.docx4j.wml.SectPr;
9
import org.jvnet.jaxb2_commons.ppp.Child;
10
import org.springframework.lang.Nullable;
11
import pro.verron.officestamper.api.*;
12
import pro.verron.officestamper.core.CommentUtil;
13
import pro.verron.officestamper.core.DocumentUtil;
14
import pro.verron.officestamper.core.SectionUtil;
15
import pro.verron.officestamper.preset.CommentProcessorFactory;
16
import pro.verron.officestamper.utils.WmlFactory;
17
18
import java.io.IOException;
19
import java.io.OutputStream;
20
import java.io.PipedInputStream;
21
import java.io.PipedOutputStream;
22
import java.util.*;
23
import java.util.concurrent.CopyOnWriteArrayList;
24
import java.util.concurrent.Executors;
25
import java.util.concurrent.ThreadFactory;
26
import java.util.concurrent.atomic.AtomicReference;
27
import java.util.function.Consumer;
28
import java.util.function.Supplier;
29
import java.util.function.UnaryOperator;
30
31
import static java.util.Objects.requireNonNull;
32
import static java.util.stream.Collectors.toMap;
33
import static pro.verron.officestamper.core.DocumentUtil.walkObjectsAndImportImages;
34
import static pro.verron.officestamper.core.SectionUtil.getPreviousSectionBreakIfPresent;
35
36
/**
37
 * This class is responsible for processing the <ds: repeat> tag.
38
 * It uses the {@link OfficeStamper} to stamp the sub document and then
39
 * copies the resulting sub document to the correct position in the
40
 * main document.
41
 *
42
 * @author Joseph Verron
43
 * @author Youssouf Naciri
44
 * @version ${version}
45
 * @since 1.3.0
46
 */
47
public class RepeatDocPartProcessor
48
        extends AbstractCommentProcessor
49
        implements CommentProcessorFactory.IRepeatDocPartProcessor {
50
    private static final ThreadFactory threadFactory = Executors.defaultThreadFactory();
51
52
    private final OfficeStamper<WordprocessingMLPackage> stamper;
53
    private final Map<Comment, Iterable<Object>> contexts = new HashMap<>();
54
    private final Supplier<? extends List<?>> nullSupplier;
55
56
    private RepeatDocPartProcessor(
57
            ParagraphPlaceholderReplacer placeholderReplacer,
58
            OfficeStamper<WordprocessingMLPackage> stamper,
59
            Supplier<? extends List<?>> nullSupplier
60
    ) {
61
        super(placeholderReplacer);
62
        this.stamper = stamper;
63
        this.nullSupplier = nullSupplier;
64
    }
65
66
    /**
67
     * <p>newInstance.</p>
68
     *
69
     * @param pr      the placeholderReplacer
70
     * @param stamper the stamper
71
     *
72
     * @return a new instance of this processor
73
     */
74
    public static CommentProcessor newInstance(
75
            ParagraphPlaceholderReplacer pr, OfficeStamper<WordprocessingMLPackage> stamper
76
    ) {
77 1 1. newInstance : replaced return value with null for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::newInstance → KILLED
        return new RepeatDocPartProcessor(pr, stamper, Collections::emptyList);
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    @Override public void repeatDocPart(@Nullable Iterable<Object> contexts) {
84 1 1. repeatDocPart : negated conditional → KILLED
        if (contexts == null) contexts = Collections.emptyList();
85
86
        Comment currentComment = getCurrentCommentWrapper();
87
        List<Object> elements = currentComment.getElements();
88
89 1 1. repeatDocPart : negated conditional → KILLED
        if (!elements.isEmpty()) {
90
            this.contexts.put(currentComment, contexts);
91
        }
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97
    @Override public void commitChanges(DocxPart source) {
98
        for (Map.Entry<Comment, Iterable<Object>> entry : this.contexts.entrySet()) {
99
            var comment = entry.getKey();
100
            var expressionContexts = entry.getValue();
101
            var gcp = requireNonNull(comment.getParent());
102
            var repeatElements = comment.getElements();
103
            var subTemplate = CommentUtil.createSubWordDocument(comment);
104
            var oddNumberOfBreaks = SectionUtil.hasOddNumberOfSectionBreaks(repeatElements);
105
            var sectionBreakInserter = getPreviousSectionBreakIfPresent(repeatElements.getFirst(), gcp)
106 2 1. lambda$commitChanges$0 : replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::lambda$commitChanges$0 → KILLED
2. lambda$commitChanges$1 : replaced return value with null for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::lambda$commitChanges$1 → KILLED
                    .map(psb -> (UnaryOperator<List<Object>>) objs -> insertSectionBreak(objs, psb, oddNumberOfBreaks))
107
                    .orElse(UnaryOperator.identity());
108 1 1. commitChanges : negated conditional → KILLED
            var changes = expressionContexts == null
109
                    ? nullSupplier.get()
110
                    : stampSubDocuments(source.document(), expressionContexts, gcp, subTemplate, sectionBreakInserter);
111
            var gcpContent = gcp.getContent();
112
            var index = gcpContent.indexOf(repeatElements.getFirst());
113
            gcpContent.addAll(index, changes);
114
            gcpContent.removeAll(repeatElements);
115
        }
116
    }
117
118
    private static List<Object> insertSectionBreak(
119
            List<Object> elements, SectPr previousSectionBreak, boolean oddNumberOfBreaks
120
    ) {
121
        var inserts = new ArrayList<>(elements);
122 1 1. insertSectionBreak : negated conditional → KILLED
        if (oddNumberOfBreaks) {
123 1 1. insertSectionBreak : negated conditional → KILLED
            if (inserts.getLast() instanceof P p) {
124 1 1. insertSectionBreak : removed call to pro/verron/officestamper/core/SectionUtil::applySectionBreakToParagraph → KILLED
                SectionUtil.applySectionBreakToParagraph(previousSectionBreak, p);
125
            }
126
            else {
127
                // when the last repeated element is not a paragraph,
128
                // it is necessary to add one carrying the section break.
129
                P p = WmlFactory.newParagraph(List.of());
130 1 1. insertSectionBreak : removed call to pro/verron/officestamper/core/SectionUtil::applySectionBreakToParagraph → KILLED
                SectionUtil.applySectionBreakToParagraph(previousSectionBreak, p);
131
                inserts.add(p);
132
            }
133
        }
134 1 1. insertSectionBreak : replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::insertSectionBreak → KILLED
        return inserts;
135
    }
136
137
    private List<Object> stampSubDocuments(
138
            WordprocessingMLPackage document,
139
            Iterable<Object> expressionContexts,
140
            ContentAccessor gcp,
141
            WordprocessingMLPackage subTemplate,
142
            UnaryOperator<List<Object>> sectionBreakInserter
143
    ) {
144
        var subDocuments = stampSubDocuments(expressionContexts, subTemplate);
145
        var replacements = subDocuments.stream()
146
                                       //TODO: move side effect somewhere else
147 1 1. lambda$stampSubDocuments$2 : replaced return value with Collections.emptyMap for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::lambda$stampSubDocuments$2 → KILLED
                                       .map(p -> walkObjectsAndImportImages(p, document))
148
                                       .map(Map::entrySet)
149
                                       .flatMap(Set::stream)
150
                                       .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
151
152
        var changes = new ArrayList<>();
153
        for (WordprocessingMLPackage subDocument : subDocuments) {
154
            var os = sectionBreakInserter.apply(DocumentUtil.allElements(subDocument));
155
            os.stream()
156
              .filter(ContentAccessor.class::isInstance)
157
              .map(ContentAccessor.class::cast)
158 2 1. stampSubDocuments : removed call to java/util/stream/Stream::forEach → KILLED
2. lambda$stampSubDocuments$3 : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::recursivelyReplaceImages → KILLED
              .forEach(o -> recursivelyReplaceImages(o, replacements));
159 2 1. lambda$stampSubDocuments$4 : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::setParentIfPossible → SURVIVED
2. stampSubDocuments : removed call to java/util/List::forEach → SURVIVED
            os.forEach(c -> setParentIfPossible(c, gcp));
160
            changes.addAll(os);
161
        }
162 1 1. stampSubDocuments : replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::stampSubDocuments → KILLED
        return changes;
163
    }
164
165
    private List<WordprocessingMLPackage> stampSubDocuments(
166
            Iterable<Object> subContexts, WordprocessingMLPackage subTemplate
167
    ) {
168
        var subDocuments = new ArrayList<WordprocessingMLPackage>();
169
        for (Object subContext : subContexts) {
170 1 1. lambda$stampSubDocuments$5 : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::copy → TIMED_OUT
            var templateCopy = outputWord(os -> copy(subTemplate, os));
171 1 1. lambda$stampSubDocuments$6 : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::stamp → TIMED_OUT
            var subDocument = outputWord(os -> stamp(subContext, templateCopy, os));
172
            subDocuments.add(subDocument);
173
        }
174 1 1. stampSubDocuments : replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::stampSubDocuments → KILLED
        return subDocuments;
175
    }
176
177
    private static void recursivelyReplaceImages(
178
            ContentAccessor r, Map<R, R> replacements
179
    ) {
180
        Queue<ContentAccessor> q = new ArrayDeque<>();
181
        q.add(r);
182 1 1. recursivelyReplaceImages : negated conditional → KILLED
        while (!q.isEmpty()) {
183
            ContentAccessor run = q.remove();
184 2 1. recursivelyReplaceImages : negated conditional → KILLED
2. recursivelyReplaceImages : negated conditional → KILLED
            if (replacements.containsKey(run) && run instanceof Child child
185 1 1. recursivelyReplaceImages : negated conditional → KILLED
                && child.getParent() instanceof ContentAccessor parent) {
186
                List<Object> parentContent = parent.getContent();
187 1 1. recursivelyReplaceImages : removed call to java/util/List::add → KILLED
                parentContent.add(parentContent.indexOf(run), replacements.get(run));
188
                parentContent.remove(run);
189
            }
190
            else {
191
                q.addAll(run.getContent()
192
                            .stream()
193
                            .filter(ContentAccessor.class::isInstance)
194
                            .map(ContentAccessor.class::cast)
195
                            .toList());
196
            }
197
        }
198
    }
199
200
    private static void setParentIfPossible(
201
            Object object, ContentAccessor parent
202
    ) {
203 2 1. setParentIfPossible : removed call to org/jvnet/jaxb2_commons/ppp/Child::setParent → SURVIVED
2. setParentIfPossible : negated conditional → KILLED
        if (object instanceof Child child) child.setParent(parent);
204
    }
205
206
    private WordprocessingMLPackage outputWord(Consumer<OutputStream> outputter) {
207
        var exceptionHandler = new ProcessorExceptionHandler();
208
        try (var os = new PipedOutputStream(); var is = new PipedInputStream(os)) {
209
            // closing on exception to not block the pipe infinitely
210
            // TODO: model both PipedxxxStream as 1 class for only 1 close()
211 1 1. outputWord : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ProcessorExceptionHandler::onException → SURVIVED
            exceptionHandler.onException(is::close); // I know it's redundant,
212 1 1. outputWord : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ProcessorExceptionHandler::onException → TIMED_OUT
            exceptionHandler.onException(os::close); // but symmetry
213
214 1 1. lambda$outputWord$7 : removed call to java/util/function/Consumer::accept → TIMED_OUT
            var thread = threadFactory.newThread(() -> outputter.accept(os));
215 1 1. outputWord : removed call to java/lang/Thread::setUncaughtExceptionHandler → TIMED_OUT
            thread.setUncaughtExceptionHandler(exceptionHandler);
216 1 1. outputWord : removed call to java/lang/Thread::start → TIMED_OUT
            thread.start();
217
            var wordprocessingMLPackage = WordprocessingMLPackage.load(is);
218 1 1. outputWord : removed call to java/lang/Thread::join → SURVIVED
            thread.join();
219
            return wordprocessingMLPackage;
220
        } catch (Docx4JException | IOException e) {
221
            OfficeStamperException exception = new OfficeStamperException(e);
222
            exceptionHandler.exception()
223 1 1. outputWord : removed call to java/util/Optional::ifPresent → KILLED
                            .ifPresent(exception::addSuppressed);
224
            throw exception;
225
        } catch (InterruptedException e) {
226
            OfficeStamperException exception = new OfficeStamperException(e);
227
            exceptionHandler.exception()
228 1 1. outputWord : removed call to java/util/Optional::ifPresent → NO_COVERAGE
                            .ifPresent(e::addSuppressed);
229
            Thread.currentThread()
230 1 1. outputWord : removed call to java/lang/Thread::interrupt → NO_COVERAGE
                  .interrupt();
231
            throw exception;
232
        }
233
    }
234
235
    private void copy(
236
            WordprocessingMLPackage aPackage, OutputStream outputStream
237
    ) {
238
        try {
239 1 1. copy : removed call to org/docx4j/openpackaging/packages/WordprocessingMLPackage::save → TIMED_OUT
            aPackage.save(outputStream);
240
        } catch (Docx4JException e) {
241
            throw new OfficeStamperException(e);
242
        }
243
    }
244
245
    private void stamp(
246
            Object context, WordprocessingMLPackage template, OutputStream outputStream
247
    ) {
248 1 1. stamp : removed call to pro/verron/officestamper/api/OfficeStamper::stamp → TIMED_OUT
        stamper.stamp(template, context, outputStream);
249
    }
250
251
    /**
252
     * {@inheritDoc}
253
     */
254
    @Override public void reset() {
255 1 1. reset : removed call to java/util/Map::clear → SURVIVED
        contexts.clear();
256
    }
257
258
    /**
259
     * A functional interface representing runnable task able to throw an exception.
260
     * It extends the {@link Runnable} interface and provides default implementation
261
     * of the {@link Runnable#run()} method handling the exception by rethrowing it
262
     * wrapped inside a {@link OfficeStamperException}.
263
     *
264
     * @author Joseph Verron
265
     * @version ${version}
266
     * @since 1.6.6
267
     */
268
    interface ThrowingRunnable
269
            extends Runnable {
270
271
        /**
272
         * Executes the runnable task, handling any exception by throwing it wrapped
273
         * inside a {@link OfficeStamperException}.
274
         */
275
        default void run() {
276
            try {
277 1 1. run : removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ThrowingRunnable::throwingRun → TIMED_OUT
                throwingRun();
278
            } catch (Exception e) {
279
                throw new OfficeStamperException(e);
280
            }
281
        }
282
283
        /**
284
         * Executes the runnable task
285
         *
286
         * @throws Exception if an exception occurs executing the task
287
         */
288
        void throwingRun()
289
                throws Exception;
290
    }
291
292
    /**
293
     * This class is responsible for capturing and handling uncaught exceptions
294
     * that occur in a thread.
295
     * It implements the {@link Thread.UncaughtExceptionHandler} interface and can
296
     * be assigned to a thread using the
297
     * {@link Thread#setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)} method.
298
     * When an exception occurs in the thread,
299
     * the {@link ProcessorExceptionHandler#uncaughtException(Thread, Throwable)}
300
     * method will be called.
301
     * This class provides the following features:
302
     * 1. Capturing and storing the uncaught exception.
303
     * 2. Executing a list of routines when an exception occurs.
304
     * 3. Providing access to the captured exception, if any.
305
     * Example usage:
306
     * <code>
307
     * ProcessorExceptionHandler exceptionHandler = new
308
     * ProcessorExceptionHandler(){};
309
     * thread.setUncaughtExceptionHandler(exceptionHandler);
310
     * </code>
311
     *
312
     * @author Joseph Verron
313
     * @version ${version}
314
     * @see Thread.UncaughtExceptionHandler
315
     * @since 1.6.6
316
     */
317
    static class ProcessorExceptionHandler
318
            implements Thread.UncaughtExceptionHandler {
319
        private final AtomicReference<Throwable> exception;
320
        private final List<Runnable> onException;
321
322
        /**
323
         * Constructs a new instance for managing thread's uncaught exceptions.
324
         * Once set to a thread, it retains the exception information and performs specified routines.
325
         */
326
        public ProcessorExceptionHandler() {
327
            this.exception = new AtomicReference<>();
328
            this.onException = new CopyOnWriteArrayList<>();
329
        }
330
331
        /**
332
         * {@inheritDoc}
333
         * <p>
334
         * Captures and stores an uncaught exception from a thread run
335
         * and executes all defined routines on occurrence of the exception.
336
         */
337
        @Override public void uncaughtException(Thread t, Throwable e) {
338 1 1. uncaughtException : removed call to java/util/concurrent/atomic/AtomicReference::set → KILLED
            exception.set(e);
339 1 1. uncaughtException : removed call to java/util/List::forEach → TIMED_OUT
            onException.forEach(Runnable::run);
340
        }
341
342
        /**
343
         * Adds a routine to the list of routines that should be run
344
         * when an exception occurs.
345
         *
346
         * @param runnable The runnable routine to be added
347
         */
348
        public void onException(ThrowingRunnable runnable) {
349
            onException.add(runnable);
350
        }
351
352
        /**
353
         * Returns the captured exception if present.
354
         *
355
         * @return an {@link Optional} containing the captured exception,
356
         * or an {@link Optional#empty()} if no exception was captured
357
         */
358
        public Optional<Throwable> exception() {
359 1 1. exception : replaced return value with Optional.empty for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ProcessorExceptionHandler::exception → KILLED
            return Optional.ofNullable(exception.get());
360
        }
361
    }
362
}

Mutations

77

1.1
Location : newInstance
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:#34]
replaced return value with null for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::newInstance → KILLED

84

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

89

1.1
Location : repeatDocPart
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[test-template:test52(pro.verron.officestamper.test.RegressionTests$Conditions, java.lang.String)]/[test-template-invocation:#1]
negated conditional → KILLED

106

1.1
Location : lambda$commitChanges$0
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:#18]
replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::lambda$commitChanges$0 → KILLED

2.2
Location : lambda$commitChanges$1
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:#15]
replaced return value with null for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::lambda$commitChanges$1 → KILLED

108

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

122

1.1
Location : insertSectionBreak
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:#18]
negated conditional → KILLED

123

1.1
Location : insertSectionBreak
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:#15]
negated conditional → KILLED

124

1.1
Location : insertSectionBreak
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:#15]
removed call to pro/verron/officestamper/core/SectionUtil::applySectionBreakToParagraph → KILLED

130

1.1
Location : insertSectionBreak
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:#17]
removed call to pro/verron/officestamper/core/SectionUtil::applySectionBreakToParagraph → KILLED

134

1.1
Location : insertSectionBreak
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:#18]
replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::insertSectionBreak → KILLED

147

1.1
Location : lambda$stampSubDocuments$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:#9]
replaced return value with Collections.emptyMap for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::lambda$stampSubDocuments$2 → KILLED

158

1.1
Location : stampSubDocuments
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:#9]
removed call to java/util/stream/Stream::forEach → KILLED

2.2
Location : lambda$stampSubDocuments$3
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:#9]
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::recursivelyReplaceImages → KILLED

159

1.1
Location : lambda$stampSubDocuments$4
Killed by : none
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::setParentIfPossible → SURVIVED
Covering tests

2.2
Location : stampSubDocuments
Killed by : none
removed call to java/util/List::forEach → SURVIVED Covering tests

162

1.1
Location : stampSubDocuments
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:#18]
replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::stampSubDocuments → KILLED

170

1.1
Location : lambda$stampSubDocuments$5
Killed by : none
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::copy → TIMED_OUT

171

1.1
Location : lambda$stampSubDocuments$6
Killed by : none
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::stamp → TIMED_OUT

174

1.1
Location : stampSubDocuments
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:#18]
replaced return value with Collections.emptyList for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor::stampSubDocuments → KILLED

182

1.1
Location : recursivelyReplaceImages
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:#9]
negated conditional → KILLED

184

1.1
Location : recursivelyReplaceImages
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:#9]
negated conditional → KILLED

2.2
Location : recursivelyReplaceImages
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[test-template:test52(pro.verron.officestamper.test.RegressionTests$Conditions, java.lang.String)]/[test-template-invocation:#3]
negated conditional → KILLED

185

1.1
Location : recursivelyReplaceImages
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:#9]
negated conditional → KILLED

187

1.1
Location : recursivelyReplaceImages
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:#9]
removed call to java/util/List::add → KILLED

203

1.1
Location : setParentIfPossible
Killed by : none
removed call to org/jvnet/jaxb2_commons/ppp/Child::setParent → SURVIVED
Covering tests

2.2
Location : setParentIfPossible
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:#17]
negated conditional → KILLED

211

1.1
Location : outputWord
Killed by : none
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ProcessorExceptionHandler::onException → SURVIVED
Covering tests

212

1.1
Location : outputWord
Killed by : none
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ProcessorExceptionHandler::onException → TIMED_OUT

214

1.1
Location : lambda$outputWord$7
Killed by : none
removed call to java/util/function/Consumer::accept → TIMED_OUT

215

1.1
Location : outputWord
Killed by : none
removed call to java/lang/Thread::setUncaughtExceptionHandler → TIMED_OUT

216

1.1
Location : outputWord
Killed by : none
removed call to java/lang/Thread::start → TIMED_OUT

218

1.1
Location : outputWord
Killed by : none
removed call to java/lang/Thread::join → SURVIVED
Covering tests

223

1.1
Location : outputWord
Killed by : pro.verron.officestamper.test.RepeatDocPartBadPlaceholderTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RepeatDocPartBadPlaceholderTest]/[method:testBadExpressionShouldNotBlockCallerThread()]
removed call to java/util/Optional::ifPresent → KILLED

228

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

230

1.1
Location : outputWord
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

239

1.1
Location : copy
Killed by : none
removed call to org/docx4j/openpackaging/packages/WordprocessingMLPackage::save → TIMED_OUT

248

1.1
Location : stamp
Killed by : none
removed call to pro/verron/officestamper/api/OfficeStamper::stamp → TIMED_OUT

255

1.1
Location : reset
Killed by : none
removed call to java/util/Map::clear → SURVIVED
Covering tests

277

1.1
Location : run
Killed by : none
removed call to pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ThrowingRunnable::throwingRun → TIMED_OUT

338

1.1
Location : uncaughtException
Killed by : pro.verron.officestamper.test.RepeatDocPartBadPlaceholderTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RepeatDocPartBadPlaceholderTest]/[method:testBadExpressionShouldNotBlockCallerThread()]
removed call to java/util/concurrent/atomic/AtomicReference::set → KILLED

339

1.1
Location : uncaughtException
Killed by : none
removed call to java/util/List::forEach → TIMED_OUT

359

1.1
Location : exception
Killed by : pro.verron.officestamper.test.RepeatDocPartBadPlaceholderTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RepeatDocPartBadPlaceholderTest]/[method:testBadExpressionShouldNotBlockCallerThread()]
replaced return value with Optional.empty for pro/verron/officestamper/preset/processors/repeatdocpart/RepeatDocPartProcessor$ProcessorExceptionHandler::exception → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.1