| 1 | package pro.verron.officestamper.utils.openpackaging; | |
| 2 | ||
| 3 | import org.docx4j.openpackaging.contenttype.ContentTypeManager; | |
| 4 | import org.docx4j.openpackaging.contenttype.ContentTypes; | |
| 5 | import org.docx4j.openpackaging.exceptions.InvalidFormatException; | |
| 6 | import org.docx4j.openpackaging.exceptions.PartUnrecognisedException; | |
| 7 | import org.docx4j.openpackaging.packages.OpcPackage; | |
| 8 | import org.docx4j.openpackaging.parts.Part; | |
| 9 | import org.docx4j.openpackaging.parts.PartName; | |
| 10 | import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage; | |
| 11 | import org.docx4j.openpackaging.parts.relationships.RelationshipsPart; | |
| 12 | import org.docx4j.relationships.Relationship; | |
| 13 | import pro.verron.officestamper.utils.UtilsException; | |
| 14 | import pro.verron.officestamper.utils.image.ImgPart; | |
| 15 | import pro.verron.officestamper.utils.svg.SvgUtils; | |
| 16 | ||
| 17 | import java.io.ByteArrayInputStream; | |
| 18 | ||
| 19 | import static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImageName; | |
| 20 | import static pro.verron.officestamper.utils.image.ImgUtils.detectFormat; | |
| 21 | import static pro.verron.officestamper.utils.image.ImgUtils.supportedContentType; | |
| 22 | import static pro.verron.officestamper.utils.openpackaging.OpenpackagingUtils.*; | |
| 23 | ||
| 24 | /// Utility class for creating Open Packaging objects. | |
| 25 | /// | |
| 26 | /// This class provides helper methods to create instances of docx4j Open Packaging objects, wrapping checked exceptions | |
| 27 | /// in runtime [UtilsException] for easier handling. | |
| 28 | public class OpenpackagingFactory { | |
| 29 | ||
| 30 | private OpenpackagingFactory() { | |
| 31 | throw new UtilsException("Utility class shouldn't be instantiated"); | |
| 32 | } | |
| 33 | ||
| 34 | /// Creates a new PartName instance from the given string representation. | |
| 35 | /// | |
| 36 | /// This method wraps the checked [InvalidFormatException] that can occur when creating a PartName in a runtime | |
| 37 | /// [UtilsException]. | |
| 38 | /// | |
| 39 | /// @param partName the string representation of the part name | |
| 40 | /// | |
| 41 | /// @return a new PartName instance | |
| 42 | /// | |
| 43 | /// @throws UtilsException if the part name string is invalid | |
| 44 | public static PartName newPartName(String partName) { | |
| 45 | try { | |
| 46 |
1
1. newPartName : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingFactory::newPartName → NO_COVERAGE |
return new PartName(partName); |
| 47 | } catch (InvalidFormatException e) { | |
| 48 | throw new UtilsException(e); | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 | /// Creates a new [ImgPart] instance from the given [OpcPackage], source part, and image byte array. | |
| 53 | /// This method detects the image format, validates its compatibility, and establishes | |
| 54 | /// the necessary relationships within the package. | |
| 55 | /// | |
| 56 | /// @param opcPackage the [OpcPackage] to which this image part belongs | |
| 57 | /// @param sourcePart the source [Part] where the relationship to the image part will be created | |
| 58 | /// @param bytes the byte array containing image data | |
| 59 | /// @return a new [ImgPart] containing the detected image format and its relationship | |
| 60 | /// @throws UtilsException if byte array is empty, format cannot be detected, or image type is unsupported | |
| 61 | public static ImgPart newImgPart(OpcPackage opcPackage, Part sourcePart, byte[] bytes) { | |
| 62 |
1
1. newImgPart : negated conditional → NO_COVERAGE |
if (bytes.length == 0) throw new UtilsException("Can't create image from empty byte array"); |
| 63 | ||
| 64 | var optFormat = detectFormat(bytes); | |
| 65 |
1
1. lambda$newImgPart$0 : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingFactory::lambda$newImgPart$0 → NO_COVERAGE |
var format = optFormat.orElseThrow(() -> new UtilsException("Could not detect a supported image type.")); |
| 66 | ||
| 67 | var optMimeType = supportedContentType(format.name()); | |
| 68 |
1
1. lambda$newImgPart$1 : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingFactory::lambda$newImgPart$1 → NO_COVERAGE |
var mimeType = optMimeType.orElseThrow(() -> new UtilsException("Unsupported image type")); |
| 69 | ||
| 70 |
1
1. newImgPart : removed call to pro/verron/officestamper/utils/openpackaging/OpenpackagingUtils::ensureHasRelationshipPart → NO_COVERAGE |
ensureHasRelationshipPart(sourcePart); |
| 71 | var relationshipId = createRelationshipId(sourcePart); | |
| 72 | var partName = createImageName(opcPackage, sourcePart, relationshipId, format.name()); | |
| 73 | var ctm = opcPackage.getContentTypeManager(); | |
| 74 | ||
| 75 | Part imgPart; | |
| 76 |
1
1. newImgPart : negated conditional → NO_COVERAGE |
if (mimeType.equals(ContentTypes.IMAGE_SVG)) { |
| 77 | var document = SvgUtils.parseDocument(bytes); | |
| 78 | imgPart = createSvgPart(document, ctm, partName); | |
| 79 | } | |
| 80 | else imgPart = createImagePart(bytes, ctm, mimeType, partName); | |
| 81 | var relationship = setupRelationship(sourcePart, imgPart, relationshipId); | |
| 82 |
1
1. newImgPart : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingFactory::newImgPart → NO_COVERAGE |
return new ImgPart(format, relationship); |
| 83 | } | |
| 84 | ||
| 85 | private static Part createImagePart(byte[] bytes, ContentTypeManager ctm, String mimeType, String partName) { | |
| 86 | try { | |
| 87 | var imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType(mimeType, partName, null); | |
| 88 |
1
1. createImagePart : removed call to org/docx4j/openpackaging/parts/WordprocessingML/BinaryPartAbstractImage::setBinaryData → NO_COVERAGE |
imagePart.setBinaryData(new ByteArrayInputStream(bytes)); |
| 89 |
1
1. createImagePart : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingFactory::createImagePart → NO_COVERAGE |
return imagePart; |
| 90 | } catch (InvalidFormatException | PartUnrecognisedException e) { | |
| 91 | throw new UtilsException(e); | |
| 92 | } | |
| 93 | } | |
| 94 | ||
| 95 | /// Establishes a relationship between a source part and a target part using the specified relationship ID. | |
| 96 | /// | |
| 97 | /// @param sourcePart the source part from which the relationship originates | |
| 98 | /// @param targetPart the target part to which the relationship points | |
| 99 | /// @param relationshipId the unique identifier for the relationship | |
| 100 | /// @return the created relationship between the source and target parts | |
| 101 | /// @throws UtilsException if an error occurs while creating the relationship | |
| 102 | public static Relationship setupRelationship(Part sourcePart, Part targetPart, String relationshipId) { | |
| 103 | try { | |
| 104 | var reuseExisting = RelationshipsPart.AddPartBehaviour.REUSE_EXISTING; | |
| 105 |
1
1. setupRelationship : replaced return value with null for pro/verron/officestamper/utils/openpackaging/OpenpackagingFactory::setupRelationship → NO_COVERAGE |
return sourcePart.addTargetPart(targetPart, reuseExisting, relationshipId); |
| 106 | } catch (InvalidFormatException e) { | |
| 107 | throw new UtilsException(e); | |
| 108 | } | |
| 109 | } | |
| 110 | } | |
Mutations | ||
| 46 |
1.1 |
|
| 62 |
1.1 |
|
| 65 |
1.1 |
|
| 68 |
1.1 |
|
| 70 |
1.1 |
|
| 76 |
1.1 |
|
| 82 |
1.1 |
|
| 88 |
1.1 |
|
| 89 |
1.1 |
|
| 105 |
1.1 |