Skip to content

Commit 30b3660

Browse files
committed
Add setting of the 'modified' flag when modifying acroform
DEVSIX-3077
1 parent 169a95f commit 30b3660

23 files changed

+341
-29
lines changed

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ public void addField(PdfFormField field, PdfPage page) {
236236
PdfAnnotation annot = PdfAnnotation.makeAnnotation(fieldDic);
237237
addWidgetAnnotationToPage(page, annot);
238238
}
239+
240+
setModified();
239241
}
240242

241243
/**
@@ -313,10 +315,11 @@ public PdfDocument getPdfDocument() {
313315
public PdfAcroForm setNeedAppearances(boolean needAppearances) {
314316
if (VersionConforming.validatePdfVersionForDeprecatedFeatureLogError(document, PdfVersion.PDF_2_0, VersionConforming.DEPRECATED_NEED_APPEARANCES_IN_ACROFORM)) {
315317
getPdfObject().remove(PdfName.NeedAppearances);
316-
return this;
318+
setModified();
317319
} else {
318-
return put(PdfName.NeedAppearances, PdfBoolean.valueOf(needAppearances));
320+
put(PdfName.NeedAppearances, PdfBoolean.valueOf(needAppearances));
319321
}
322+
return this;
320323
}
321324

322325
/**
@@ -598,6 +601,7 @@ public boolean isGenerateAppearance() {
598601
public void setGenerateAppearance(boolean generateAppearance) {
599602
if (generateAppearance) {
600603
getPdfObject().remove(PdfName.NeedAppearances);
604+
setModified();
601605
}
602606
this.generateAppearance = generateAppearance;
603607
}
@@ -768,13 +772,15 @@ public boolean removeField(String fieldName) {
768772
if (parent != null) {
769773
parent.getAsArray(PdfName.Kids).remove(fieldObject);
770774
fields.remove(fieldName);
775+
parent.setModified();
771776
return true;
772777
}
773778

774779
PdfArray fieldsPdfArray = getFields();
775780
if (fieldsPdfArray.contains(fieldObject)) {
776781
fieldsPdfArray.remove(fieldObject);
777782
this.fields.remove(fieldName);
783+
setModified();
778784
return true;
779785
}
780786
return false;
@@ -1000,6 +1006,7 @@ public void removeXfaForm() {
10001006

10011007
public PdfAcroForm put(PdfName key, PdfObject value) {
10021008
getPdfObject().put(key, value);
1009+
setModified();
10031010
return this;
10041011
}
10051012

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package com.itextpdf.forms;
2+
3+
import com.itextpdf.forms.fields.PdfFormField;
4+
import com.itextpdf.kernel.geom.Rectangle;
5+
import com.itextpdf.kernel.pdf.PdfDocument;
6+
import com.itextpdf.kernel.pdf.PdfReader;
7+
import com.itextpdf.kernel.pdf.PdfWriter;
8+
import com.itextpdf.kernel.pdf.StampingProperties;
9+
import com.itextpdf.kernel.utils.CompareTool;
10+
import com.itextpdf.test.ExtendedITextTest;
11+
import com.itextpdf.test.annotations.type.IntegrationTest;
12+
13+
import java.io.FileNotFoundException;
14+
import java.io.IOException;
15+
import org.junit.Assert;
16+
import org.junit.BeforeClass;
17+
import org.junit.Test;
18+
import org.junit.experimental.categories.Category;
19+
20+
@Category(IntegrationTest.class)
21+
public class PdfAcroFormInAppendModeTest extends ExtendedITextTest {
22+
23+
private static final String destinationFolder = "./target/test/com/itextpdf/forms/PdfAcroFormInAppendModeTest/";
24+
private static final String sourceFolder = "./src/test/resources/com/itextpdf/forms/PdfAcroFormInAppendModeTest/";
25+
private static final String inputFile = destinationFolder + "inputFile.pdf";
26+
27+
@BeforeClass
28+
public static void beforeClass() throws FileNotFoundException {
29+
createDestinationFolder(destinationFolder);
30+
createInputFile();
31+
}
32+
33+
@Test
34+
public void createFieldInAppendModeTest() throws IOException, InterruptedException {
35+
String outputFile = "createFieldInAppendModeTest.pdf";
36+
PdfDocument outputDoc = createDocInAppendMode(destinationFolder + outputFile);
37+
PdfFormField field = PdfFormField.createCheckBox(
38+
outputDoc,
39+
new Rectangle(10, 10, 24, 24),
40+
"checkboxname", "On",
41+
PdfFormField.TYPE_CHECK);
42+
PdfAcroForm.getAcroForm(outputDoc, true).addField(field);
43+
outputDoc.close();
44+
compareWithCmp(outputFile);
45+
}
46+
47+
@Test
48+
public void removeFieldInAppendModeTest() throws IOException, InterruptedException {
49+
String outputFile = "removeFieldInAppendModeTest.pdf";
50+
PdfDocument outputDoc = createDocInAppendMode(destinationFolder + outputFile);
51+
PdfAcroForm.getAcroForm(outputDoc, true).removeField("textfield2");
52+
outputDoc.close();
53+
compareWithCmp(outputFile);
54+
}
55+
56+
@Test
57+
public void removeFieldWithParentInAppendModeTest() throws IOException, InterruptedException {
58+
// Creating input document
59+
String inputFile = "inputRemoveFieldWithParentInAppendModeTest.pdf";
60+
PdfDocument inDoc = new PdfDocument(new PdfWriter(destinationFolder + inputFile));
61+
inDoc.addNewPage();
62+
PdfFormField root = PdfFormField.createEmptyField(inDoc);
63+
root.setFieldName("root");
64+
PdfFormField child = PdfFormField.createEmptyField(inDoc);
65+
child.setFieldName("child");
66+
root.addKid(child);
67+
PdfAcroForm.getAcroForm(inDoc, true).addField(root);
68+
inDoc.close();
69+
70+
// Creating stamping document
71+
String outputFile = "removeFieldWithParentInAppendModeTest.pdf";
72+
PdfReader reader = new PdfReader(destinationFolder + inputFile);
73+
PdfWriter writer = new PdfWriter(destinationFolder + outputFile);
74+
PdfDocument outputDoc = new PdfDocument(reader, writer, new StampingProperties().useAppendMode());
75+
76+
PdfAcroForm.getAcroForm(outputDoc, true).removeField("root.child");
77+
78+
outputDoc.close();
79+
compareWithCmp(outputFile);
80+
}
81+
82+
@Test
83+
public void replaceFieldInAppendModeTest() throws IOException, InterruptedException {
84+
String outputFile = "replaceFieldInAppendModeTest.pdf";
85+
PdfDocument outputDoc = createDocInAppendMode(destinationFolder + outputFile);
86+
PdfFormField newField = PdfFormField.createText(outputDoc, new Rectangle(20, 160, 100, 20), "newfield", "new field");
87+
PdfAcroForm.getAcroForm(outputDoc, true).replaceField("textfield1", newField);
88+
outputDoc.close();
89+
compareWithCmp(outputFile);
90+
}
91+
92+
private static void createInputFile() throws FileNotFoundException {
93+
PdfDocument document = new PdfDocument(new PdfWriter(inputFile));
94+
document.addNewPage();
95+
PdfAcroForm.getAcroForm(document, true)
96+
.addField(PdfFormField.createText(document, new Rectangle(20, 160, 100, 20), "textfield1", "text1"));
97+
PdfAcroForm.getAcroForm(document, true)
98+
.addField(PdfFormField.createText(document, new Rectangle(20, 130, 100, 20), "textfield2", "text2"));
99+
document.close();
100+
}
101+
102+
private static PdfDocument createDocInAppendMode(String outFile) throws IOException {
103+
PdfReader reader = new PdfReader(inputFile);
104+
PdfWriter writer = new PdfWriter(outFile);
105+
return new PdfDocument(reader, writer, new StampingProperties().useAppendMode());
106+
}
107+
108+
private static void compareWithCmp(String outputFile) throws IOException, InterruptedException {
109+
Assert.assertNull(new CompareTool()
110+
.compareByContent(destinationFolder + outputFile, sourceFolder + "cmp_" + outputFile, destinationFolder,
111+
"diff_"));
112+
}
113+
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package com.itextpdf.forms;
2+
3+
import com.itextpdf.io.source.ByteArrayOutputStream;
4+
import com.itextpdf.kernel.pdf.PdfArray;
5+
import com.itextpdf.kernel.pdf.PdfBoolean;
6+
import com.itextpdf.kernel.pdf.PdfDictionary;
7+
import com.itextpdf.kernel.pdf.PdfDocument;
8+
import com.itextpdf.kernel.pdf.PdfName;
9+
import com.itextpdf.kernel.pdf.PdfNumber;
10+
import com.itextpdf.kernel.pdf.PdfObject;
11+
import com.itextpdf.kernel.pdf.PdfStream;
12+
import com.itextpdf.kernel.pdf.PdfString;
13+
import com.itextpdf.kernel.pdf.PdfVersion;
14+
import com.itextpdf.kernel.pdf.PdfWriter;
15+
import com.itextpdf.kernel.pdf.WriterProperties;
16+
import com.itextpdf.test.ExtendedITextTest;
17+
import com.itextpdf.test.annotations.LogMessage;
18+
import com.itextpdf.test.annotations.LogMessages;
19+
import com.itextpdf.test.annotations.type.UnitTest;
20+
21+
import org.junit.Assert;
22+
import org.junit.Test;
23+
import org.junit.experimental.categories.Category;
24+
25+
@Category(UnitTest.class)
26+
public class PdfAcroFormTest extends ExtendedITextTest {
27+
28+
@Test
29+
public void setSignatureFlagsTest() {
30+
PdfDocument outputDoc = createDocument();
31+
32+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
33+
acroForm.setSignatureFlags(65);
34+
35+
boolean isModified = acroForm.getPdfObject().isModified();
36+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
37+
PdfObject sigFlags = acroForm.getPdfObject().get(PdfName.SigFlags);
38+
outputDoc.close();
39+
40+
Assert.assertEquals(new PdfNumber(65), sigFlags);
41+
Assert.assertTrue(isModified);
42+
Assert.assertTrue(isReleaseForbidden);
43+
}
44+
45+
@Test
46+
public void setCalculationOrderTest() {
47+
PdfDocument outputDoc = createDocument();
48+
49+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
50+
PdfArray calculationOrderArray = new PdfArray(new int[] {1, 0});
51+
acroForm.setCalculationOrder(calculationOrderArray);
52+
53+
boolean isModified = acroForm.getPdfObject().isModified();
54+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
55+
PdfObject calculationOrder = acroForm.getPdfObject().get(PdfName.CO);
56+
outputDoc.close();
57+
58+
Assert.assertEquals(calculationOrderArray, calculationOrder);
59+
Assert.assertTrue(isModified);
60+
Assert.assertTrue(isReleaseForbidden);
61+
}
62+
63+
@Test
64+
public void setDefaultAppearanceTest() {
65+
PdfDocument outputDoc = createDocument();
66+
67+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
68+
acroForm.setDefaultAppearance("default appearance");
69+
70+
boolean isModified = acroForm.getPdfObject().isModified();
71+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
72+
PdfObject calculationOrder = acroForm.getPdfObject().get(PdfName.DA);
73+
outputDoc.close();
74+
75+
Assert.assertEquals(new PdfString("default appearance"), calculationOrder);
76+
Assert.assertTrue(isModified);
77+
Assert.assertTrue(isReleaseForbidden);
78+
}
79+
80+
@Test
81+
public void setDefaultJustificationTest() {
82+
PdfDocument outputDoc = createDocument();
83+
84+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
85+
acroForm.setDefaultJustification(14);
86+
87+
boolean isModified = acroForm.getPdfObject().isModified();
88+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
89+
PdfObject defaultJustification = acroForm.getPdfObject().get(PdfName.Q);
90+
outputDoc.close();
91+
92+
Assert.assertEquals(new PdfNumber(14), defaultJustification);
93+
Assert.assertTrue(isModified);
94+
Assert.assertTrue(isReleaseForbidden);
95+
}
96+
97+
@Test
98+
public void setDefaultResourcesTest() {
99+
PdfDocument outputDoc = createDocument();
100+
101+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
102+
103+
PdfDictionary dictionary = new PdfDictionary();
104+
PdfAcroForm.getAcroForm(outputDoc, true).setDefaultResources(dictionary);
105+
106+
boolean isModified = acroForm.getPdfObject().isModified();
107+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
108+
PdfObject defaultResourcesDict = acroForm.getPdfObject().get(PdfName.DR);
109+
outputDoc.close();
110+
111+
Assert.assertEquals(dictionary, defaultResourcesDict);
112+
Assert.assertTrue(isModified);
113+
Assert.assertTrue(isReleaseForbidden);
114+
}
115+
116+
@Test
117+
public void setNeedAppearancesTest() {
118+
PdfDocument outputDoc = createDocument();
119+
120+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
121+
acroForm.setNeedAppearances(false);
122+
123+
boolean isModified = acroForm.getPdfObject().isModified();
124+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
125+
PdfObject needAppearance = acroForm.getPdfObject().get(PdfName.NeedAppearances);
126+
127+
outputDoc.close();
128+
129+
Assert.assertEquals(new PdfBoolean(false), needAppearance);
130+
Assert.assertTrue(isModified);
131+
Assert.assertTrue(isReleaseForbidden);
132+
}
133+
134+
@Test
135+
@LogMessages(messages = @LogMessage(messageTemplate = "NeedAppearances has been deprecated in PDF 2.0. Appearance streams are required in PDF 2.0."))
136+
public void setNeedAppearancesInPdf2Test() {
137+
PdfDocument outputDoc = new PdfDocument(
138+
new PdfWriter(new ByteArrayOutputStream(), new WriterProperties().setPdfVersion(
139+
PdfVersion.PDF_2_0)));
140+
outputDoc.addNewPage();
141+
142+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
143+
acroForm.setNeedAppearances(false);
144+
145+
boolean isModified = acroForm.getPdfObject().isModified();
146+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
147+
PdfObject needAppearance = acroForm.getPdfObject().get(PdfName.NeedAppearances);
148+
149+
outputDoc.close();
150+
151+
Assert.assertNull(needAppearance);
152+
Assert.assertTrue(isModified);
153+
Assert.assertTrue(isReleaseForbidden);
154+
}
155+
156+
@Test
157+
public void setGenerateAppearanceTest() {
158+
PdfDocument outputDoc = createDocument();
159+
160+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
161+
acroForm.setNeedAppearances(false);
162+
acroForm.setGenerateAppearance(true);
163+
164+
boolean isModified = acroForm.getPdfObject().isModified();
165+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
166+
boolean isGenerateAppearance = acroForm.isGenerateAppearance();
167+
Object needAppearances = acroForm.getPdfObject().get(PdfName.NeedAppearances);
168+
outputDoc.close();
169+
170+
Assert.assertNull(needAppearances);
171+
Assert.assertTrue(isGenerateAppearance);
172+
Assert.assertTrue(isModified);
173+
Assert.assertTrue(isReleaseForbidden);
174+
}
175+
176+
@Test
177+
public void setXFAResourcePdfArrayTest() {
178+
PdfDocument outputDoc = createDocument();
179+
180+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
181+
PdfArray array = new PdfArray();
182+
acroForm.setXFAResource(array);
183+
184+
boolean isModified = acroForm.getPdfObject().isModified();
185+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
186+
PdfObject xfaObject = acroForm.getPdfObject().get(PdfName.XFA);
187+
outputDoc.close();
188+
189+
Assert.assertEquals(array, xfaObject);
190+
Assert.assertTrue(isModified);
191+
Assert.assertTrue(isReleaseForbidden);
192+
}
193+
194+
@Test
195+
public void setXFAResourcePdfStreamTest() {
196+
PdfDocument outputDoc = createDocument();
197+
198+
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(outputDoc, true);
199+
PdfStream stream = new PdfStream();
200+
acroForm.setXFAResource(stream);
201+
202+
boolean isModified = acroForm.getPdfObject().isModified();
203+
boolean isReleaseForbidden = acroForm.getPdfObject().isReleaseForbidden();
204+
PdfObject xfaObject = acroForm.getPdfObject().get(PdfName.XFA);
205+
outputDoc.close();
206+
207+
Assert.assertEquals(stream, xfaObject);
208+
Assert.assertTrue(isModified);
209+
Assert.assertTrue(isReleaseForbidden);
210+
}
211+
212+
private static PdfDocument createDocument() {
213+
PdfDocument outputDoc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream()));
214+
outputDoc.addNewPage();
215+
return outputDoc;
216+
}
217+
}

0 commit comments

Comments
 (0)