RunUtil.java

1
package pro.verron.officestamper.core;
2
3
import jakarta.xml.bind.JAXBElement;
4
import org.docx4j.model.styles.StyleUtil;
5
import org.docx4j.wml.*;
6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8
import org.springframework.lang.Nullable;
9
import pro.verron.officestamper.api.OfficeStamperException;
10
11
import java.util.Objects;
12
13
import static java.util.stream.Collectors.joining;
14
import static pro.verron.officestamper.utils.WmlFactory.newRun;
15
import static pro.verron.officestamper.utils.WmlFactory.newText;
16
17
/// Utility class to handle runs.
18
///
19
/// @author Joseph Verron
20
/// @author Tom Hombergs
21
/// @version ${version}
22
/// @since 1.0.0
23
public class RunUtil {
24
25
26
    private static final String PRESERVE = "preserve";
27
    private static final Logger log = LoggerFactory.getLogger(RunUtil.class);
28
29
    private RunUtil() {
30
        throw new OfficeStamperException("Utility class shouldn't be instantiated");
31
    }
32
33
    /// Extracts textual content from a given object, handling various object types,
34
    /// such as runs, text elements, and other specific constructs.
35
    /// The method accounts for different cases, such as run breaks, hyphens,
36
    /// and other document-specific constructs, and converts them into
37
    /// corresponding string representations.
38
    ///
39
    /// @param content the object from which text content is to be extracted.
40
    ///                This could be of various types such as R, JAXBElement, Text,
41
    ///                or specific document elements.
42
    ///
43
    /// @return a string representation of the extracted textual content.
44
    /// If the object's type is not handled, an empty string is returned.
45
    public static String getText(Object content) {
46 1 1. getText : replaced return value with "" for pro/verron/officestamper/core/RunUtil::getText → KILLED
        return switch (content) {
47
            case R run -> run.getContent()
48
                             .stream()
49
                             .map(RunUtil::getText)
50
                             .collect(joining());
51
            case JAXBElement<?> jaxbElement when jaxbElement.getName()
52
                                                            .getLocalPart()
53 1 1. getText : negated conditional → KILLED
                                                            .equals("instrText") -> "<instrText>";
54
            case JAXBElement<?> jaxbElement when !jaxbElement.getName()
55
                                                             .getLocalPart()
56 1 1. getText : negated conditional → KILLED
                                                             .equals("instrText") -> getText(jaxbElement.getValue());
57
            case Text text -> getText(text);
58
            case R.Tab _ -> "\t";
59
            case R.Cr _ -> "\n";
60 1 1. getText : negated conditional → KILLED
            case Br br when br.getType() == null -> "\n";
61 1 1. getText : negated conditional → SURVIVED
            case Br br when br.getType() == STBrType.TEXT_WRAPPING -> "\n";
62 1 1. getText : negated conditional → SURVIVED
            case Br br when br.getType() == STBrType.PAGE -> "\n";
63 1 1. getText : negated conditional → NO_COVERAGE
            case Br br when br.getType() == STBrType.COLUMN -> "\n";
64
            case R.NoBreakHyphen _ -> "‑";
65
            case R.SoftHyphen _ -> "\u00AD";
66 4 1. getText : negated conditional → SURVIVED
2. getText : negated conditional → SURVIVED
3. getText : negated conditional → SURVIVED
4. getText : negated conditional → SURVIVED
            case R.LastRenderedPageBreak _, R.AnnotationRef _, R.CommentReference _, Drawing _ -> "";
67
            case FldChar _ -> "<fldchar>";
68
            case CTFtnEdnRef ref -> ref.getId()
69
                                       .toString();
70
            case R.Sym sym -> "<sym(%s, %s)>".formatted(sym.getFont(), sym.getChar());
71
            default -> {
72
                log.debug("Unhandled object type: {}", content.getClass());
73
                yield "";
74
            }
75
        };
76
    }
77
78
    private static String getText(Text text) {
79
        // According to specs, 'space' value can be empty or 'preserve'.
80
        // In the first case, we are supposed to ignore spaces around the 'text' value.
81
        var value = text.getValue();
82
        var space = text.getSpace();
83 2 1. getText : negated conditional → KILLED
2. getText : replaced return value with "" for pro/verron/officestamper/core/RunUtil::getText → KILLED
        return Objects.equals(space, PRESERVE) ? value : value.trim();
84
    }
85
86
    /// Creates a new run with the specified text and inherits the style of the parent paragraph.
87
    ///
88
    /// @param text the initial text of the run.
89
    ///
90
    /// @return the newly created run.
91
    public static R create(String text, PPr paragraphPr) {
92
        R run = newRun(text);
93 1 1. create : removed call to pro/verron/officestamper/core/RunUtil::applyParagraphStyle → NO_COVERAGE
        applyParagraphStyle(run, paragraphPr);
94 1 1. create : replaced return value with null for pro/verron/officestamper/core/RunUtil::create → NO_COVERAGE
        return run;
95
    }
96
97
    /// Applies the style of the given paragraph to the given content object (if the content object is a Run).
98
    ///
99
    /// @param run the Run to which the style should be applied.
100
    public static void applyParagraphStyle(R run, @Nullable PPr paragraphPr) {
101 1 1. applyParagraphStyle : negated conditional → NO_COVERAGE
        if (paragraphPr == null) return;
102
        var runPr = paragraphPr.getRPr();
103 1 1. applyParagraphStyle : negated conditional → NO_COVERAGE
        if (runPr == null) return;
104
        RPr runProperties = new RPr();
105
        StyleUtil.apply(runPr, runProperties);
106 1 1. applyParagraphStyle : removed call to org/docx4j/wml/R::setRPr → NO_COVERAGE
        run.setRPr(runProperties);
107
    }
108
109
    /// Sets the text of the given run to the given value.
110
    ///
111
    /// @param run  the run whose text to change.
112
    /// @param text the text to set.
113
    public static void setText(R run, String text) {
114
        run.getContent()
115 1 1. setText : removed call to java/util/List::clear → KILLED
           .clear();
116
        Text textObj = newText(text);
117
        run.getContent()
118
           .add(textObj);
119
    }
120
121
    static R create(String text, RPr rPr) {
122
        R newStartRun = newRun(text);
123 1 1. create : removed call to org/docx4j/wml/R::setRPr → SURVIVED
        newStartRun.setRPr(rPr);
124 1 1. create : replaced return value with null for pro/verron/officestamper/core/RunUtil::create → KILLED
        return newStartRun;
125
    }
126
}

Mutations

46

1.1
Location : getText
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:#22]
replaced return value with "" for pro/verron/officestamper/core/RunUtil::getText → KILLED

53

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

56

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

60

1.1
Location : getText
Killed by : pro.verron.officestamper.test.CustomFunctionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.CustomFunctionTests]/[test-template:interfaces(pro.verron.officestamper.test.ContextFactory)]/[test-template-invocation:#2]
negated conditional → KILLED

61

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

62

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

63

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

66

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

2.2
Location : getText
Killed by : none
negated conditional → SURVIVED Covering tests

3.3
Location : getText
Killed by : none
negated conditional → SURVIVED Covering tests

4.4
Location : getText
Killed by : none
negated conditional → SURVIVED Covering tests

83

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

2.2
Location : getText
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:#22]
replaced return value with "" for pro/verron/officestamper/core/RunUtil::getText → KILLED

93

1.1
Location : create
Killed by : none
removed call to pro/verron/officestamper/core/RunUtil::applyParagraphStyle → NO_COVERAGE

94

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

101

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

103

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

106

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

115

1.1
Location : setText
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:#13]
removed call to java/util/List::clear → KILLED

123

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

124

1.1
Location : create
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:#5]
replaced return value with null for pro/verron/officestamper/core/RunUtil::create → KILLED

Active mutators

Tests examined


Report generated by PIT 1.21.0