Skip to content

Commit 719254a

Browse files
committed
Copy parent field if it is not present in the destination document
Previously we copied its children, but not the parent itself DEVSIX-4902
1 parent 7c60c14 commit 719254a

File tree

14 files changed

+129
-7
lines changed

14 files changed

+129
-7
lines changed

forms/src/main/java/com/itextpdf/forms/PdfPageFormCopier.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,14 @@ private void copyParentFormField(PdfPage toPage, Map<String, PdfFormField> field
167167
PdfAnnotation annot, PdfFormField parentField) {
168168
PdfString parentName = parentField.getFieldName();
169169
if (!fieldsTo.containsKey(parentName.toUnicodeString())) {
170+
// no such field, hence we should simply add it
170171
PdfFormField field = createParentFieldCopy(annot.getPdfObject(), documentTo);
171172
PdfArray kids = field.getKids();
172173
field.getPdfObject().remove(PdfName.Kids);
173174
formTo.addField(field, toPage);
174175
field.getPdfObject().put(PdfName.Kids, kids);
175176
} else {
177+
// it is either a field (field name will not be null) or a widget (field name is not null)
176178
PdfFormField field = makeFormField(annot.getPdfObject());
177179
if (field == null) {
178180
return;
@@ -190,18 +192,36 @@ private void copyParentFormField(PdfPage toPage, Map<String, PdfFormField> field
190192
fieldsTo);
191193
}
192194
} else {
193-
if (!parentField.getKids().contains(field.getPdfObject())) {
195+
if (!parentField.getKids().contains(field.getPdfObject())
196+
&& formTo.getFields().contains(parentField.getPdfObject())) {
197+
// its parent is already a field of the resultant document,
198+
// hence we only need to update its children
194199
HashSet<String> existingFields = new HashSet<>();
195200
getAllFieldNames(formTo.getFields(), existingFields);
196201
addChildToExistingParent(annot.getPdfObject(), existingFields);
202+
} else {
203+
// its parent is not a field of the resultant document, but the latter contains
204+
// a field of the same name, therefore we should merge them (note that merging in this context
205+
// differs from merging a widget and an annotation into a single entity)
206+
PdfFormField mergedField = mergeFieldsWithTheSameName(field);
207+
// we need to add the field not to its representation (#getFormFields()), but to
208+
// /Fields entry of the acro form
209+
formTo.addField(mergedField, toPage);
197210
}
198211
}
199212
}
200213
}
201214

202215
private PdfFormField mergeFieldsWithTheSameName(PdfFormField newField) {
203-
String fullFieldName = newField.getFieldName().toUnicodeString();
204216
PdfString fieldName = newField.getPdfObject().getAsString(PdfName.T);
217+
if (null == fieldName) {
218+
fieldName = newField.getParent().getAsString(PdfName.T);
219+
}
220+
221+
String fullFieldName = fieldName.toUnicodeString();
222+
if (null != newField.getFieldName()) {
223+
fullFieldName = newField.getFieldName().toUnicodeString();
224+
}
205225

206226
logger.warn(MessageFormatUtil.format(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, fullFieldName));
207227

forms/src/test/java/com/itextpdf/forms/FormFieldFlatteningTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ private static void fillTextFieldsThenFlattenThenCompare(String testName) throws
254254
}
255255

256256
@Test
257-
@LogMessages(messages = {@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 3)})
257+
@LogMessages(messages = {@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 5)})
258258
//Logging is expected since there are duplicate field names
259259
//isReadOnly should be true after DEVSIX-2156
260260
public void flattenReadOnly() throws IOException {

forms/src/test/java/com/itextpdf/forms/PdfFormCopyTest.java

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ This file is part of the iText (R) project.
5353
import com.itextpdf.test.annotations.LogMessage;
5454
import com.itextpdf.test.annotations.LogMessages;
5555
import com.itextpdf.test.annotations.type.IntegrationTest;
56+
5657
import org.junit.Assert;
5758
import org.junit.BeforeClass;
5859
import org.junit.Test;
@@ -73,7 +74,7 @@ public static void beforeClass() {
7374

7475
@Test
7576
@LogMessages(messages = {
76-
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 13)
77+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 32)
7778
})
7879
public void copyFieldsTest01() throws IOException, InterruptedException {
7980
String srcFilename1 = sourceFolder + "appearances1.pdf";
@@ -328,7 +329,7 @@ public void copyFieldsTest06() throws IOException, InterruptedException {
328329

329330
@Test
330331
@LogMessages(messages = {
331-
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 13)
332+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 32)
332333
})
333334
public void copyFieldsTest07() throws IOException, InterruptedException {
334335
String srcFilename = sourceFolder + "datasheet.pdf";
@@ -350,7 +351,7 @@ public void copyFieldsTest07() throws IOException, InterruptedException {
350351

351352
@Test
352353
@LogMessages(messages = {
353-
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 13)
354+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 32)
354355
})
355356
public void copyFieldsTest08() throws IOException, InterruptedException {
356357
String srcFilename1 = sourceFolder + "appearances1.pdf";
@@ -378,7 +379,7 @@ public void copyFieldsTest08() throws IOException, InterruptedException {
378379

379380
@Test
380381
@LogMessages(messages = {
381-
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 26)
382+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 64)
382383
})
383384
public void copyFieldsTest09() throws IOException, InterruptedException {
384385
String srcFilename = sourceFolder + "datasheet.pdf";
@@ -596,4 +597,103 @@ public void copyAndEditRadioButtons() throws IOException, InterruptedException {
596597

597598
Assert.assertNull(new CompareTool().compareByContent(destFilename, cmpFileName, destinationFolder, "diff_"));
598599
}
600+
601+
@Test
602+
@LogMessages(messages = {
603+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD)
604+
})
605+
public void mergeMergedFieldAndMergedFieldTest() throws IOException, InterruptedException {
606+
String srcFileName1 = sourceFolder + "fieldMergedWithWidget.pdf";
607+
String destFilename = destinationFolder + "mergeMergedFieldAndMergedFieldTest.pdf";
608+
String cmpFileName = sourceFolder + "cmp_mergeMergedFieldAndMergedFieldTest.pdf";
609+
610+
try (
611+
PdfWriter writer = new PdfWriter(destFilename);
612+
PdfDocument resultPdfDocument = new PdfDocument(writer);
613+
PdfReader reader1 = new PdfReader(srcFileName1);
614+
PdfDocument sourceDoc1 = new PdfDocument(reader1);) {
615+
PdfAcroForm.getAcroForm(resultPdfDocument, true);
616+
PdfPageFormCopier formCopier = new PdfPageFormCopier();
617+
618+
sourceDoc1.copyPagesTo(1, sourceDoc1.getNumberOfPages(), resultPdfDocument, formCopier);
619+
sourceDoc1.copyPagesTo(1, sourceDoc1.getNumberOfPages(), resultPdfDocument, formCopier);
620+
}
621+
622+
Assert.assertNull(new CompareTool().compareByContent(destFilename, cmpFileName, destinationFolder, "diff_"));
623+
}
624+
625+
@Test
626+
@LogMessages(messages = {
627+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, count = 2)
628+
})
629+
public void mergeMergedFieldAndTwoWidgetsTest() throws IOException, InterruptedException {
630+
String srcFileName1 = sourceFolder + "fieldMergedWithWidget.pdf";
631+
String srcFileName2 = sourceFolder + "fieldTwoWidgets.pdf";
632+
String destFilename = destinationFolder + "mergeMergedFieldAndTwoWidgetsTest.pdf";
633+
String cmpFileName = sourceFolder + "cmp_mergeMergedFieldAndTwoWidgetsTest.pdf";
634+
635+
try (
636+
PdfWriter writer = new PdfWriter(destFilename);
637+
PdfDocument resultPdfDocument = new PdfDocument(writer);
638+
PdfReader reader1 = new PdfReader(srcFileName1);
639+
PdfDocument sourceDoc1 = new PdfDocument(reader1);
640+
PdfReader reader2 = new PdfReader(srcFileName2);
641+
PdfDocument sourceDoc2 = new PdfDocument(reader2);) {
642+
PdfAcroForm.getAcroForm(resultPdfDocument, true);
643+
PdfPageFormCopier formCopier = new PdfPageFormCopier();
644+
645+
sourceDoc1.copyPagesTo(1, sourceDoc1.getNumberOfPages(), resultPdfDocument, formCopier);
646+
sourceDoc2.copyPagesTo(1, sourceDoc2.getNumberOfPages(), resultPdfDocument, formCopier);
647+
}
648+
649+
Assert.assertNull(new CompareTool().compareByContent(destFilename, cmpFileName, destinationFolder, "diff_"));
650+
}
651+
652+
@Test
653+
@LogMessages(messages = {
654+
@LogMessage(messageTemplate = LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD)
655+
})
656+
public void mergeTwoWidgetsAndMergedFieldTest() throws IOException, InterruptedException {
657+
String srcFileName1 = sourceFolder + "fieldMergedWithWidget.pdf";
658+
String srcFileName2 = sourceFolder + "fieldTwoWidgets.pdf";
659+
String destFilename = destinationFolder + "mergeTwoWidgetsAndMergedFieldTest.pdf";
660+
String cmpFileName = sourceFolder + "cmp_mergeTwoWidgetsAndMergedFieldTest.pdf";
661+
662+
try (
663+
PdfWriter writer = new PdfWriter(destFilename);
664+
PdfDocument resultPdfDocument = new PdfDocument(writer);
665+
PdfReader reader1 = new PdfReader(srcFileName1);
666+
PdfDocument sourceDoc1 = new PdfDocument(reader1);
667+
PdfReader reader2 = new PdfReader(srcFileName2);
668+
PdfDocument sourceDoc2 = new PdfDocument(reader2);) {
669+
PdfAcroForm.getAcroForm(resultPdfDocument, true);
670+
PdfPageFormCopier formCopier = new PdfPageFormCopier();
671+
672+
sourceDoc2.copyPagesTo(1, sourceDoc2.getNumberOfPages(), resultPdfDocument, formCopier);
673+
sourceDoc1.copyPagesTo(1, sourceDoc1.getNumberOfPages(), resultPdfDocument, formCopier);
674+
}
675+
676+
Assert.assertNull(new CompareTool().compareByContent(destFilename, cmpFileName, destinationFolder, "diff_"));
677+
}
678+
679+
@Test
680+
public void mergeTwoWidgetsAndTwoWidgetsTest() throws IOException, InterruptedException {
681+
String srcFileName2 = sourceFolder + "fieldTwoWidgets.pdf";
682+
String destFilename = destinationFolder + "mergeTwoWidgetsAndTwoWidgetsTest.pdf";
683+
String cmpFileName = sourceFolder + "cmp_mergeTwoWidgetsAndTwoWidgetsTest.pdf";
684+
685+
try (
686+
PdfWriter writer = new PdfWriter(destFilename);
687+
PdfDocument resultPdfDocument = new PdfDocument(writer);
688+
PdfReader reader2 = new PdfReader(srcFileName2);
689+
PdfDocument sourceDoc2 = new PdfDocument(reader2);) {
690+
PdfAcroForm.getAcroForm(resultPdfDocument, true);
691+
PdfPageFormCopier formCopier = new PdfPageFormCopier();
692+
693+
sourceDoc2.copyPagesTo(1, sourceDoc2.getNumberOfPages(), resultPdfDocument, formCopier);
694+
sourceDoc2.copyPagesTo(1, sourceDoc2.getNumberOfPages(), resultPdfDocument, formCopier);
695+
}
696+
697+
Assert.assertNull(new CompareTool().compareByContent(destFilename, cmpFileName, destinationFolder, "diff_"));
698+
}
599699
}

0 commit comments

Comments
 (0)