package jnpf.fileStorage.dms;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import jnpf.dmsEntity.storage.form.DmsFileUploadRegisterForm;
|
import jnpf.exception.DataException;
|
import jnpf.model.filecontent.FileContentImportForm;
|
import jnpf.service.DmsApprovalPageTagService;
|
import org.docx4j.XmlUtils;
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
import org.docx4j.wml.*;
|
import org.junit.Test;
|
import org.mockito.ArgumentCaptor;
|
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import java.io.ByteArrayOutputStream;
|
import java.util.Map;
|
import java.util.UUID;
|
import java.util.function.Function;
|
|
import static org.junit.Assert.*;
|
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.Mockito.*;
|
|
/** Exercises the real DOCX writer and page merger through physical-content import. */
|
public class DmsApprovalTagImportTest {
|
private static final ObjectFactory WML = new ObjectFactory();
|
private final DmsCommonFileReader reader = mock(DmsCommonFileReader.class);
|
private final DmsFileStorageService storage = mock(DmsFileStorageService.class);
|
private final DmsApprovalPageTagService pageTags = new DmsApprovalPageTagService();
|
private final FileContentImportService service = new FileContentImportService(reader, storage,
|
new DmsApprovalPageMergeService(pageTags), new DmsQianpiyeDocxWriter(),
|
new DmsDocxCommentCleaner(), new ObjectMapper());
|
|
@Test public void fillsOriginalWorkflowFormAndRowsTagsWithoutInsertingAPage() throws Exception {
|
FileContentImportForm form = form();
|
MultipartFile original = docx("main.docx", "原文件正文",
|
"dms.qianpiye.form.wenjian_bianhao", "{{文件编号}}",
|
"dms.qianpiye.flow.approve-1.approver", "{{审核人}}",
|
"dms.qianpiye.rows.common.distribution", "{{department}}({{copies}})");
|
read("main.docx", form.getFileJson(), form.getFileName(), original);
|
|
MultipartFile result = imported(form);
|
String xml = xml(result);
|
|
assertTrue(xml.contains("原文件正文"));
|
assertTrue(xml.contains("DOC-001"));
|
assertTrue(xml.contains("张三"));
|
assertTrue(xml.contains("质量部(10)"));
|
assertFalse(xml.contains("{{"));
|
assertFalse(pageTags.hasApprovalPage(result));
|
verify(reader, times(1)).withFile(any(), any(), any(), any());
|
}
|
|
@Test public void fillsBothConfiguredPageAndOriginalDocumentBeforeStoring() throws Exception {
|
FileContentImportForm form = form();
|
form.setSignaturePageFiles("[{\"url\":\"page.docx\"}]");
|
read("main.docx", form.getFileJson(), form.getFileName(), docx("main.docx", "原文件正文",
|
"dms.qianpiye.form.wenjian_bianhao", "{{文件编号}}"));
|
read("page.docx", form.getSignaturePageFiles(), "签批页", docx("page.docx", "配置的签批页",
|
"dms.qianpiye.flow.approve-1.approver", "{{审核人}}"));
|
|
MultipartFile result = imported(form);
|
String xml = xml(result);
|
|
assertTrue(xml.contains("原文件正文"));
|
assertTrue(xml.contains("配置的签批页"));
|
assertTrue(xml.contains("DOC-001"));
|
assertTrue(xml.contains("张三"));
|
assertFalse(xml.contains("{{"));
|
assertTrue(pageTags.hasApprovalPage(result));
|
verify(reader, times(2)).withFile(any(), any(), any(), any());
|
}
|
|
@Test public void untaggedOriginalKeepsItsContentWithoutAnApprovalPage() throws Exception {
|
FileContentImportForm form = form();
|
read("main.docx", form.getFileJson(), form.getFileName(), docx("main.docx", "无标注正文"));
|
|
MultipartFile result = imported(form);
|
|
assertTrue(xml(result).contains("无标注正文"));
|
assertFalse(pageTags.hasApprovalPage(result));
|
}
|
|
@Test public void clearsRemovedFieldsInBothBodyAndApprovalPageBeforeStoring() throws Exception {
|
FileContentImportForm form = form();
|
form.setSignaturePageFiles("[{\"url\":\"page.docx\"}]");
|
read("main.docx", form.getFileJson(), form.getFileName(), docx("main.docx", "正文",
|
"dms.qianpiye.form.deleted_field", "旧正文值",
|
"dms.qianpiye.form.wenjian_bianhao", "{{文件编号}}"));
|
read("page.docx", form.getSignaturePageFiles(), "签批页", docx("page.docx", "签批页",
|
"dms.qianpiye.form.deleted_table.column", "旧子表值",
|
"dms.qianpiye.rows.common.deleted_table", "旧子表整行",
|
"dms.qianpiye.flow.approve-1.approver", "{{审核人}}"));
|
|
MultipartFile result = imported(form);
|
String xml = xml(result);
|
|
assertTrue(xml.contains("DOC-001"));
|
assertTrue(xml.contains("张三"));
|
assertTrue(pageTags.hasApprovalPage(result));
|
assertFalse(xml.contains("旧正文值"));
|
assertFalse(xml.contains("旧子表值"));
|
assertFalse(xml.contains("旧子表整行"));
|
assertFalse(xml.contains("{{"));
|
}
|
|
@Test public void replacesAnOldFilledApprovalPageBeforeRenderingTheOriginalBody() throws Exception {
|
FileContentImportForm form = form();
|
form.setSignaturePageFiles("[{\"url\":\"page.docx\"}]");
|
MultipartFile body = docx("main.docx", "修订正文",
|
"dms.qianpiye.form.wenjian_bianhao", "{{文件编号}}");
|
// Historical generated rows have no remaining placeholders or saved pattern.
|
MultipartFile oldPage = docx("old.docx", "旧签批页",
|
"dms.qianpiye.rows.common.distribution", "历史部门(旧份数)");
|
MultipartFile original = new DmsApprovalPageMergeService(pageTags).replaceOrPrepend(body, oldPage);
|
read("main.docx", form.getFileJson(), form.getFileName(), original);
|
read("page.docx", form.getSignaturePageFiles(), "签批页", docx("page.docx", "新签批页",
|
"dms.qianpiye.flow.approve-1.approver", "{{审核人}}"));
|
|
String xml = xml(imported(form));
|
|
assertTrue(xml.contains("修订正文"));
|
assertTrue(xml.contains("新签批页"));
|
assertTrue(xml.contains("DOC-001"));
|
assertTrue(xml.contains("张三"));
|
assertFalse(xml.contains("旧签批页"));
|
assertFalse(xml.contains("历史部门"));
|
}
|
|
@Test public void originalTagRenderingFailureStopsPhysicalStorage() {
|
FileContentImportForm form = form();
|
read("main.docx", form.getFileJson(), form.getFileName(),
|
new MockMultipartFile("file", "main.docx", "application/octet-stream", new byte[]{1, 2, 3}));
|
|
assertThrows(DataException.class, () -> service.importContent(form));
|
|
verifyNoInteractions(storage);
|
}
|
|
private FileContentImportForm form() {
|
FileContentImportForm form = new FileContentImportForm();
|
form.setDocumentId(UUID.randomUUID());
|
form.setFileVersionId(UUID.randomUUID());
|
form.setFileName("归档名称");
|
form.setFileJson("[{\"url\":\"main.docx\"}]");
|
form.setApprovalFlowVersionId("flow-version");
|
form.setSignaturePageValues(Map.of(
|
"dms.qianpiye.form.wenjian_bianhao", "DOC-001",
|
"dms.qianpiye.flow.approve-1.approver", "张三",
|
"dms.qianpiye.rows.common.distribution", "[{\"department\":\"质量部\",\"copies\":\"10\"}]"));
|
return form;
|
}
|
|
private void read(String url, String fileJson, String name, MultipartFile file) {
|
when(reader.withFile(eq(url), eq(fileJson), eq(name), any())).thenAnswer(invocation ->
|
invocation.<Function<MultipartFile, DmsFileUploadRegisterForm>>getArgument(3).apply(file));
|
}
|
|
private MultipartFile imported(FileContentImportForm form) {
|
when(storage.storeWorkflowContent(eq(form.getDocumentId()), eq(form.getFileVersionId()), any()))
|
.thenReturn(new DmsFileUploadRegisterForm());
|
service.importContent(form);
|
ArgumentCaptor<MultipartFile> content = ArgumentCaptor.forClass(MultipartFile.class);
|
verify(storage).storeWorkflowContent(eq(form.getDocumentId()), eq(form.getFileVersionId()), content.capture());
|
assertEquals("归档名称.docx", content.getValue().getOriginalFilename());
|
return content.getValue();
|
}
|
|
private MultipartFile docx(String name, String body, String... tagsAndText) throws Exception {
|
WordprocessingMLPackage word = WordprocessingMLPackage.createPackage();
|
word.getMainDocumentPart().addParagraphOfText(body);
|
for (int index = 0; index < tagsAndText.length; index += 2) {
|
Tag tag = WML.createTag();
|
tag.setVal(tagsAndText[index]);
|
SdtPr properties = WML.createSdtPr();
|
properties.setTag(tag);
|
Text text = WML.createText();
|
text.setValue(tagsAndText[index + 1]);
|
R run = WML.createR();
|
run.getContent().add(WML.createRT(text));
|
CTSdtContentRun content = WML.createCTSdtContentRun();
|
content.getContent().add(run);
|
SdtRun control = WML.createSdtRun();
|
control.setSdtPr(properties);
|
control.setSdtContent(content);
|
P paragraph = WML.createP();
|
paragraph.getContent().add(WML.createPSdt(control));
|
word.getMainDocumentPart().getContent().add(paragraph);
|
}
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
word.save(bytes);
|
return new MockMultipartFile("file", name,
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", bytes.toByteArray());
|
}
|
|
private String xml(MultipartFile file) throws Exception {
|
WordprocessingMLPackage word = WordprocessingMLPackage.load(file.getInputStream());
|
return XmlUtils.marshaltoString(word.getMainDocumentPart().getJaxbElement(), true, true);
|
}
|
}
|