OpenpackagingUtils.java

1
package pro.verron.officestamper.utils.openpackaging;
2
3
import org.docx4j.openpackaging.contenttype.ContentType;
4
import org.docx4j.openpackaging.contenttype.ContentTypeManager;
5
import org.docx4j.openpackaging.contenttype.ContentTypes;
6
import org.docx4j.openpackaging.exceptions.Docx4JException;
7
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
8
import org.docx4j.openpackaging.exceptions.PartUnrecognisedException;
9
import org.docx4j.openpackaging.packages.PresentationMLPackage;
10
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
11
import org.docx4j.openpackaging.parts.XmlPart;
12
import org.docx4j.openpackaging.parts.relationships.Namespaces;
13
import org.docx4j.wml.R;
14
import org.w3c.dom.Document;
15
import pro.verron.officestamper.utils.UtilsException;
16
import pro.verron.officestamper.utils.image.ImageRunOptions;
17
import pro.verron.officestamper.utils.svg.SvgUtils;
18
import pro.verron.officestamper.utils.wml.WmlFactory;
19
20
import java.io.InputStream;
21
import java.io.OutputStream;
22
import java.util.function.Supplier;
23
24
/// Utility class for working with Open Packaging documents. This class provides methods to load and export Word
25
/// documents using DOCX4J
26
public class OpenpackagingUtils {
27
    private OpenpackagingUtils() {
28
        throw new UtilsException("Utility class shouldn't be instantiated");
29
    }
30
31
    /// Loads a Word document from the provided input stream.
32
    ///
33
    /// @param is the input stream containing the Word document data
34
    /// @return a WordprocessingMLPackage representing the loaded document
35
    /// @throws UtilsException if there is an error loading the document
36
    public static WordprocessingMLPackage loadWord(InputStream is) {
37
        try {
38 1 1. loadWord : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::loadWord → NO_COVERAGE
            return WordprocessingMLPackage.load(is);
39
        } catch (Docx4JException e) {
40
            throw new UtilsException(e);
41
        }
42
    }
43
44
    /// Exports a Word document to the provided output stream.
45
    ///
46
    /// @param wordprocessingMLPackage the Word document to export
47
    /// @param os the output stream to write the document to
48
    /// @throws UtilsException if there is an error exporting the document
49
    public static void exportWord(WordprocessingMLPackage wordprocessingMLPackage, OutputStream os) {
50
        try {
51 1 1. exportWord : removed call to org/docx4j/openpackaging/packages/WordprocessingMLPackage::save → NO_COVERAGE
            wordprocessingMLPackage.save(os);
52
        } catch (Docx4JException e) {
53
            throw new UtilsException(e);
54
        }
55
    }
56
57
    /// Loads a PowerPoint document from the provided input stream.
58
    ///
59
    /// @param is the input stream containing the PowerPoint document data
60
    /// @return a PresentationMLPackage representing the loaded document
61
    /// @throws UtilsException if there is an error loading the document
62
    public static PresentationMLPackage loadPowerPoint(InputStream is) {
63
        try {
64 1 1. loadPowerPoint : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::loadPowerPoint → NO_COVERAGE
            return PresentationMLPackage.load(is);
65
        } catch (Docx4JException e) {
66
            throw new UtilsException(e);
67
        }
68
    }
69
70
    /// Exports a PowerPoint document to the provided output stream.
71
    ///
72
    /// @param presentationMLPackage the PowerPoint document to export
73
    /// @param os the output stream to write the document to
74
    /// @throws UtilsException if there is an error exporting the document
75
    public static void exportPowerPoint(PresentationMLPackage presentationMLPackage, OutputStream os) {
76
        try {
77 1 1. exportPowerPoint : removed call to org/docx4j/openpackaging/packages/PresentationMLPackage::save → NO_COVERAGE
            presentationMLPackage.save(os);
78
        } catch (Docx4JException e) {
79
            throw new UtilsException(e);
80
        }
81
    }
82
83
    /// Creates a new run element containing an image, which is embedded in a [WordprocessingMLPackage] document.
84
    ///
85
    /// @param openPackage       the open package of the Word document, providing access to the document model
86
    ///                          and its sections; typically used to generate the appropriate relationships
87
    ///                          and content.
88
    /// @param bytes             a supplier of the byte array representing the image data to be embedded
89
    ///                          in the document.
90
    /// @param imageRunOptions   options for the image run, including alternate text, filename hints,
91
    ///                          maximum width, and deduplication preferences.
92
    /// @return a [R] (run) object representing the created image run, which can be added to the
93
    ///         document content.
94
    /// @throws UtilsException   if there is an error during the creation of the image part, such as
95
    ///                          an invalid image format or issues with the document model.
96
    public static R newImageRun(
97
            OpenPackage<WordprocessingMLPackage> openPackage,
98
            Supplier<byte[]> bytes,
99
            ImageRunOptions imageRunOptions
100
    ) {
101
        try {
102
            var document = openPackage.document();
103
            var documentModel = document.getDocumentModel();
104
            var sections = documentModel.getSections();
105
            var lastSection = sections.getLast();
106
            var pageDimension = lastSection.getPageDimensions();
107
            var imgPart = openPackage.findOrCreateImgPart(bytes, imageRunOptions.deduplicate());
108
            var relationship = imgPart.relationship();
109
            var imgFormat = imgPart.format();
110
            var dimension = imgFormat.dimension();
111
            var format = imgFormat.name();
112
            var scale = WmlFactory.computeScale(pageDimension,
113 1 1. newImageRun : negated conditional → NO_COVERAGE
                    imageRunOptions.maxWidth() == null ? -1 : imageRunOptions.maxWidth(),
114
                    dimension);
115 1 1. newImageRun : negated conditional → NO_COVERAGE
            var inline = format.equals("svg")
116
                    ? WmlFactory.newSVGInline(relationship,
117
                    imageRunOptions.filenameHint(),
118
                    imageRunOptions.altText(),
119
                    scale)
120
                    : WmlFactory.newImgInline(relationship,
121
                            imageRunOptions.filenameHint(),
122
                            imageRunOptions.altText(),
123
                            scale);
124
            var drawing = WmlFactory.newDrawing(inline);
125 1 1. newImageRun : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::newImageRun → NO_COVERAGE
            return WmlFactory.newRun(drawing);
126
        } catch (Exception e) {
127
            throw new UtilsException("Failed to create an ImagePart", e);
128
        }
129
    }
130
131
    /// Extracts the SVG XML content from the provided byte array by parsing it into a document and
132
    /// creating an SVG part using the specified ContentTypeManager.
133
    ///
134
    /// @param bytes the byte array containing the SVG content to be parsed
135
    /// @param ctm the content type manager used to manage the creation of the SVG part
136
    /// @return the extracted XML content as a String
137
    /// @throws RuntimeException if an error occurs during the processing or extraction of the XML content
138
    public static String extractSvgXml(byte[] bytes, ContentTypeManager ctm) {
139
        var newDocument = SvgUtils.parseDocument(bytes);
140
        var svgPart = createSvgPart(ctm, newDocument, "/temporary");
141 1 1. extractSvgXml : replaced return value with "" for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::extractSvgXml → NO_COVERAGE
        return extractXml(svgPart);
142
    }
143
144
    /// Creates a new SVG part with the specified document, content type manager, and part name.
145
    ///
146
    /// @param contentTypeManager the content type manager used to create the SVG part
147
    /// @param document the XML document to associate with the new SVG part
148
    /// @param partName the name to assign to the new SVG part
149
    /// @return the created SVG part
150
    /// @throws UtilsException if an error occurs during part creation or initialization
151
    public static XmlPart createSvgPart(ContentTypeManager contentTypeManager, Document document, String partName) {
152
        XmlPart part;
153
        try {
154
            part = (XmlPart) contentTypeManager.newPartForContentType(ContentTypes.IMAGE_SVG, partName, null);
155
        } catch (InvalidFormatException | PartUnrecognisedException e) {
156
            throw new UtilsException(e);
157
        }
158 1 1. createSvgPart : removed call to org/docx4j/openpackaging/parts/XmlPart::setRelationshipType → NO_COVERAGE
        part.setRelationshipType(Namespaces.IMAGE);
159 1 1. createSvgPart : removed call to org/docx4j/openpackaging/parts/XmlPart::setContentType → NO_COVERAGE
        part.setContentType(new ContentType(ContentTypes.IMAGE_SVG));
160 1 1. createSvgPart : removed call to org/docx4j/openpackaging/parts/XmlPart::setDocument → NO_COVERAGE
        part.setDocument(document);
161 1 1. createSvgPart : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::createSvgPart → NO_COVERAGE
        return part;
162
    }
163
164
    /// Extracts the XML content from the specified XmlPart.
165
    ///
166
    /// @param xmlPart the XmlPart from which to extract the XML content
167
    /// @return the extracted XML content as a String
168
    /// @throws RuntimeException if an error occurs while retrieving the XML content
169
    public static String extractXml(XmlPart xmlPart) {
170
        String existingXml;
171
        try {
172
            existingXml = xmlPart.getXML();
173
        } catch (Docx4JException e) {
174
            throw new RuntimeException(e);
175
        }
176 1 1. extractXml : replaced return value with "" for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::extractXml → NO_COVERAGE
        return existingXml;
177
    }
178
}

Mutations

38

1.1
Location : loadWord
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::loadWord → NO_COVERAGE

51

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

64

1.1
Location : loadPowerPoint
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::loadPowerPoint → NO_COVERAGE

77

1.1
Location : exportPowerPoint
Killed by : none
removed call to org/docx4j/openpackaging/packages/PresentationMLPackage::save → NO_COVERAGE

113

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

115

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

125

1.1
Location : newImageRun
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::newImageRun → NO_COVERAGE

141

1.1
Location : extractSvgXml
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::extractSvgXml → NO_COVERAGE

158

1.1
Location : createSvgPart
Killed by : none
removed call to org/docx4j/openpackaging/parts/XmlPart::setRelationshipType → NO_COVERAGE

159

1.1
Location : createSvgPart
Killed by : none
removed call to org/docx4j/openpackaging/parts/XmlPart::setContentType → NO_COVERAGE

160

1.1
Location : createSvgPart
Killed by : none
removed call to org/docx4j/openpackaging/parts/XmlPart::setDocument → NO_COVERAGE

161

1.1
Location : createSvgPart
Killed by : none
replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::createSvgPart → NO_COVERAGE

176

1.1
Location : extractXml
Killed by : none
replaced return value with "" for pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::extractXml → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.25.5 support