package jnpf.fileStorage.dms;
|
|
import jnpf.exception.DataException;
|
import jnpf.service.DmsApprovalPageTagService;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDPage;
|
import org.docx4j.XmlUtils;
|
import org.docx4j.model.structure.SectionWrapper;
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
|
import org.docx4j.relationships.Relationship;
|
import org.docx4j.wml.Hdr;
|
import org.docx4j.wml.HdrFtrRef;
|
import org.docx4j.wml.HeaderReference;
|
import org.docx4j.wml.ObjectFactory;
|
import org.docx4j.wml.SectPr;
|
import org.junit.BeforeClass;
|
import org.junit.Test;
|
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayOutputStream;
|
import java.math.BigInteger;
|
import java.util.List;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertTrue;
|
|
public class DmsApprovalPageMergeServiceTest {
|
private static final ObjectFactory WML = new ObjectFactory();
|
private final DmsApprovalPageTagService tags = new DmsApprovalPageTagService();
|
private final DmsApprovalPageMergeService service = new DmsApprovalPageMergeService(tags);
|
|
@BeforeClass
|
public static void useHeadlessRendering() {
|
System.setProperty("java.awt.headless", "true");
|
}
|
|
@Test
|
public void rendersPdfPagesBeforeTheOriginalDocxContent() throws Exception {
|
MultipartFile result = service.prepend(docx("main.docx", "ORIGINAL CONTENT"), pdf("approval.pdf"));
|
|
WordprocessingMLPackage merged = WordprocessingMLPackage.load(result.getInputStream());
|
String xml = XmlUtils.marshaltoString(
|
merged.getMainDocumentPart().getJaxbElement(), true, true);
|
assertTrue(xml.indexOf("w:drawing") >= 0);
|
assertTrue(xml.indexOf("w:drawing") < xml.indexOf("ORIGINAL CONTENT"));
|
assertTrue(xml.contains("w:type=\"page\""));
|
assertTrue(service.hasApprovalPage(result));
|
assertEquals("main.docx", result.getOriginalFilename());
|
}
|
|
@Test
|
public void embedsDocxApprovalPageAheadOfTheOriginalDocument() throws Exception {
|
MultipartFile result = service.prepend(
|
docx("main.docx", "ORIGINAL CONTENT"), docx("approval.docx", "APPROVAL CONTENT"));
|
|
WordprocessingMLPackage merged = WordprocessingMLPackage.load(result.getInputStream());
|
String xml = XmlUtils.marshaltoString(
|
merged.getMainDocumentPart().getJaxbElement(), true, true);
|
assertTrue(xml.indexOf("APPROVAL CONTENT") < xml.indexOf("ORIGINAL CONTENT"));
|
assertFalse(xml.contains("w:altChunk"));
|
assertTrue(xml.contains("w:val=\"nextPage\""));
|
assertTrue(service.hasApprovalPage(result));
|
}
|
|
@Test
|
public void preservesApprovalPageMarginsAndHeaderAsAnIndependentFirstSection() throws Exception {
|
MultipartFile result = service.prepend(
|
docxWithLayout("main.docx", "ORIGINAL CONTENT", 1800, null),
|
docxWithLayout("approval.docx", "APPROVAL CONTENT", 1080, "APPROVAL HEADER"));
|
|
WordprocessingMLPackage merged = WordprocessingMLPackage.load(result.getInputStream());
|
List<SectionWrapper> sections = merged.getDocumentModel().getSections();
|
assertEquals(2, sections.size());
|
assertEquals(BigInteger.valueOf(1080), sections.get(0).getSectPr().getPgMar().getLeft());
|
assertEquals(BigInteger.valueOf(1800), sections.get(1).getSectPr().getPgMar().getLeft());
|
HeaderPart approvalHeader = sections.get(0).getHeaderFooterPolicy().getDefaultHeader();
|
HeaderPart mainHeader = sections.get(1).getHeaderFooterPolicy().getDefaultHeader();
|
assertTrue(XmlUtils.marshaltoString(approvalHeader.getJaxbElement(), true, true)
|
.contains("APPROVAL HEADER"));
|
assertFalse(XmlUtils.marshaltoString(mainHeader.getJaxbElement(), true, true)
|
.contains("APPROVAL HEADER"));
|
String mainXml = XmlUtils.marshaltoString(
|
merged.getMainDocumentPart().getJaxbElement(), true, true);
|
assertFalse(mainXml.contains("APPROVAL HEADER"));
|
}
|
|
@Test
|
public void tagsUploadedDocxApprovalPageWithoutAddingVisibleText() throws Exception {
|
MultipartFile tagged = tags.tagApprovalPage(docx("approval.docx", "APPROVAL CONTENT"));
|
|
WordprocessingMLPackage word = WordprocessingMLPackage.load(tagged.getInputStream());
|
String xml = XmlUtils.marshaltoString(word.getMainDocumentPart().getJaxbElement(), true, true);
|
assertTrue(tags.hasApprovalPage(tagged));
|
assertTrue(xml.contains(DmsApprovalPageTagService.TAG_VALUE));
|
assertFalse(xml.contains("<w:id"));
|
assertTrue(xml.contains("APPROVAL CONTENT"));
|
}
|
|
@Test
|
public void doesNotInsertAnotherApprovalPageWhenMarkerAlreadyExists() throws Exception {
|
MultipartFile first = service.prepend(docx("main.docx", "ORIGINAL"), pdf("approval.pdf"));
|
|
assertSame(first, service.prepend(first, pdf("other.pdf")));
|
}
|
|
@Test
|
public void replacesAnExistingApprovalPageForARevision() throws Exception {
|
MultipartFile first = service.prepend(docx("main.docx", "ORIGINAL"), pdf("approval.pdf"));
|
MultipartFile replaced = service.replaceOrPrepend(first, pdf("other.pdf"));
|
|
WordprocessingMLPackage word = WordprocessingMLPackage.load(replaced.getInputStream());
|
String xml = XmlUtils.marshaltoString(word.getMainDocumentPart().getJaxbElement(), true, true);
|
assertEquals(1, occurrences(xml, DmsApprovalPageTagService.TAG_VALUE));
|
assertTrue(xml.contains("ORIGINAL"));
|
}
|
|
@Test
|
public void replacesAnExistingDocxApprovalPageForARevision() throws Exception {
|
MultipartFile first = service.prepend(
|
docx("main.docx", "ORIGINAL"), docx("approval.docx", "OLD APPROVAL"));
|
MultipartFile replaced = service.replaceOrPrepend(
|
first, docx("approval.docx", "NEW APPROVAL"));
|
|
WordprocessingMLPackage word = WordprocessingMLPackage.load(replaced.getInputStream());
|
String xml = XmlUtils.marshaltoString(word.getMainDocumentPart().getJaxbElement(), true, true);
|
assertEquals(1, occurrences(xml, DmsApprovalPageTagService.TAG_VALUE));
|
assertFalse(xml.contains("OLD APPROVAL"));
|
assertTrue(xml.contains("NEW APPROVAL"));
|
assertTrue(xml.contains("ORIGINAL"));
|
assertEquals(2, word.getDocumentModel().getSections().size());
|
}
|
|
@Test
|
public void rejectsUnsupportedConfiguredFilesInsteadOfSilentlySkippingThem() throws Exception {
|
assertThrows(DataException.class, () -> service.prepend(
|
docx("main.docx", "ORIGINAL"),
|
new MockMultipartFile("file", "approval.png", "image/png", new byte[]{1})));
|
assertThrows(DataException.class, () -> service.prepend(
|
new MockMultipartFile("file", "legacy.doc", "application/msword", new byte[]{1}),
|
pdf("approval.pdf")));
|
}
|
|
private MockMultipartFile docx(String name, String text) throws Exception {
|
WordprocessingMLPackage document = WordprocessingMLPackage.createPackage();
|
document.getMainDocumentPart().addParagraphOfText(text);
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
document.save(output);
|
return new MockMultipartFile("file", name,
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
output.toByteArray());
|
}
|
|
private MockMultipartFile docxWithLayout(String name, String text, long horizontalMargin,
|
String headerText) throws Exception {
|
WordprocessingMLPackage document = WordprocessingMLPackage.createPackage();
|
document.getMainDocumentPart().addParagraphOfText(text);
|
SectPr section = document.getMainDocumentPart().getJaxbElement().getBody().getSectPr();
|
section.getPgMar().setLeft(BigInteger.valueOf(horizontalMargin));
|
section.getPgMar().setRight(BigInteger.valueOf(horizontalMargin));
|
if (headerText != null) {
|
HeaderPart headerPart = new HeaderPart();
|
Hdr header = WML.createHdr();
|
header.getContent().add(document.getMainDocumentPart().createParagraphOfText(headerText));
|
headerPart.setJaxbElement(header);
|
Relationship relationship = document.getMainDocumentPart().addTargetPart(headerPart);
|
HeaderReference reference = WML.createHeaderReference();
|
reference.setType(HdrFtrRef.DEFAULT);
|
reference.setId(relationship.getId());
|
section.getEGHdrFtrReferences().add(reference);
|
}
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
document.save(output);
|
return new MockMultipartFile("file", name,
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
output.toByteArray());
|
}
|
|
private MockMultipartFile pdf(String name) throws Exception {
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
try (PDDocument document = new PDDocument()) {
|
document.addPage(new PDPage());
|
document.save(output);
|
}
|
return new MockMultipartFile("file", name, "application/pdf", output.toByteArray());
|
}
|
|
private int occurrences(String source, String value) {
|
int count = 0;
|
for (int index = 0; (index = source.indexOf(value, index)) >= 0; index += value.length()) count++;
|
return count;
|
}
|
}
|