1 | /* | |
2 | * Copyright 2003 by Paulo Soares. | |
3 | * | |
4 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
5 | * (the "License"); you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
7 | * | |
8 | * Software distributed under the License is distributed on an "AS IS" basis, | |
9 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
10 | * for the specific language governing rights and limitations under the License. | |
11 | * | |
12 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
15 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
16 | * All Rights Reserved. | |
17 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
18 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
19 | * | |
20 | * Contributor(s): all the names of the contributors are added in the source code | |
21 | * where applicable. | |
22 | * | |
23 | * Alternatively, the contents of this file may be used under the terms of the | |
24 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
25 | * provisions of LGPL are applicable instead of those above. If you wish to | |
26 | * allow use of your version of this file only under the terms of the LGPL | |
27 | * License and not to allow others to use your version of this file under | |
28 | * the MPL, indicate your decision by deleting the provisions above and | |
29 | * replace them with the notice and other provisions required by the LGPL. | |
30 | * If you do not delete the provisions above, a recipient may use your version | |
31 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
32 | * | |
33 | * This library is free software; you can redistribute it and/or modify it | |
34 | * under the terms of the MPL as stated above or under the terms of the GNU | |
35 | * Library General Public License as published by the Free Software Foundation; | |
36 | * either version 2 of the License, or any later version. | |
37 | * | |
38 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
39 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
40 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
41 | * details. | |
42 | * | |
43 | * If you didn't download this code from the following link, you should check if | |
44 | * you aren't using an obsolete version: | |
45 | * http://www.lowagie.com/iText/ | |
46 | */ | |
47 | package com.lowagie.text.pdf; | |
48 | ||
49 | import java.io.IOException; | |
50 | import java.io.OutputStream; | |
51 | import java.util.ArrayList; | |
52 | import java.util.HashMap; | |
53 | import java.util.Map; | |
54 | import java.util.StringTokenizer; | |
55 | ||
56 | import com.lowagie.text.DocWriter; | |
57 | ||
58 | /** Writes an FDF form. | |
59 | * @author Paulo Soares (psoares@consiste.pt) | |
60 | */ | |
61 | public class FdfWriter { | |
62 | private static final byte[] HEADER_FDF = DocWriter.getISOBytes("%FDF-1.2\n%\u00e2\u00e3\u00cf\u00d3\n"); | |
63 | HashMap fields = new HashMap(); | |
64 | ||
65 | /** The PDF file associated with the FDF. */ | |
66 | private String file; | |
67 | | |
68 | /** Creates a new FdfWriter. */ | |
69 | public FdfWriter() { | |
70 | } | |
71 | ||
72 | /** Writes the content to a stream. | |
73 | * @param os the stream | |
74 | * @throws IOException on error | |
75 | */ | |
76 | public void writeTo(OutputStream os) throws IOException { | |
77 | Wrt wrt = new Wrt(os, this); | |
78 |
1
1. writeTo : removed call to com/lowagie/text/pdf/FdfWriter$Wrt::writeTo → NO_COVERAGE |
wrt.writeTo(); |
79 | } | |
80 | | |
81 | boolean setField(String field, PdfObject value) { | |
82 | HashMap map = fields; | |
83 | StringTokenizer tk = new StringTokenizer(field, "."); | |
84 |
1
1. setField : negated conditional → NO_COVERAGE |
if (!tk.hasMoreTokens()) |
85 |
1
1. setField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
86 | while (true) { | |
87 | String s = tk.nextToken(); | |
88 | Object obj = map.get(s); | |
89 |
1
1. setField : negated conditional → NO_COVERAGE |
if (tk.hasMoreTokens()) { |
90 |
1
1. setField : negated conditional → NO_COVERAGE |
if (obj == null) { |
91 | obj = new HashMap(); | |
92 | map.put(s, obj); | |
93 | map = (HashMap)obj; | |
94 | continue; | |
95 | } | |
96 |
1
1. setField : negated conditional → NO_COVERAGE |
else if (obj instanceof HashMap) |
97 | map = (HashMap)obj; | |
98 | else | |
99 |
1
1. setField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
100 | } | |
101 | else { | |
102 |
1
1. setField : negated conditional → NO_COVERAGE |
if (!(obj instanceof HashMap)) { |
103 | map.put(s, value); | |
104 |
1
1. setField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
105 | } | |
106 | else | |
107 |
1
1. setField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
108 | } | |
109 | } | |
110 | } | |
111 | | |
112 | void iterateFields(HashMap values, HashMap map, String name) { | |
113 | for (Object o : map.entrySet()) { | |
114 | Map.Entry entry = (Map.Entry) o; | |
115 | String s = (String) entry.getKey(); | |
116 | Object obj = entry.getValue(); | |
117 |
1
1. iterateFields : negated conditional → NO_COVERAGE |
if (obj instanceof HashMap) |
118 |
1
1. iterateFields : removed call to com/lowagie/text/pdf/FdfWriter::iterateFields → NO_COVERAGE |
iterateFields(values, (HashMap) obj, name + "." + s); |
119 | else | |
120 | values.put((name + "." + s).substring(1), obj); | |
121 | } | |
122 | } | |
123 | | |
124 | /** Removes the field value. | |
125 | * @param field the field name | |
126 | * @return <CODE>true</CODE> if the field was found and removed, | |
127 | * <CODE>false</CODE> otherwise | |
128 | */ | |
129 | public boolean removeField(String field) { | |
130 | HashMap map = fields; | |
131 | StringTokenizer tk = new StringTokenizer(field, "."); | |
132 |
1
1. removeField : negated conditional → NO_COVERAGE |
if (!tk.hasMoreTokens()) |
133 |
1
1. removeField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
134 | ArrayList hist = new ArrayList(); | |
135 | while (true) { | |
136 | String s = tk.nextToken(); | |
137 | Object obj = map.get(s); | |
138 |
1
1. removeField : negated conditional → NO_COVERAGE |
if (obj == null) |
139 |
1
1. removeField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
140 | hist.add(map); | |
141 | hist.add(s); | |
142 |
1
1. removeField : negated conditional → NO_COVERAGE |
if (tk.hasMoreTokens()) { |
143 |
1
1. removeField : negated conditional → NO_COVERAGE |
if (obj instanceof HashMap) |
144 | map = (HashMap)obj; | |
145 | else | |
146 |
1
1. removeField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
147 | } | |
148 | else { | |
149 |
1
1. removeField : negated conditional → NO_COVERAGE |
if (obj instanceof HashMap) |
150 |
1
1. removeField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
151 | else | |
152 | break; | |
153 | } | |
154 | } | |
155 |
4
1. removeField : changed conditional boundary → NO_COVERAGE 2. removeField : Changed increment from -2 to 2 → NO_COVERAGE 3. removeField : Replaced integer subtraction with addition → NO_COVERAGE 4. removeField : negated conditional → NO_COVERAGE |
for (int k = hist.size() - 2; k >= 0; k -= 2) { |
156 | map = (HashMap)hist.get(k); | |
157 |
1
1. removeField : Replaced integer addition with subtraction → NO_COVERAGE |
String s = (String)hist.get(k + 1); |
158 | map.remove(s); | |
159 |
1
1. removeField : negated conditional → NO_COVERAGE |
if (!map.isEmpty()) |
160 | break; | |
161 | } | |
162 |
1
1. removeField : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
163 | } | |
164 | | |
165 | /** Gets all the fields. The map is keyed by the fully qualified | |
166 | * field name and the values are <CODE>PdfObject</CODE>. | |
167 | * @return a map with all the fields | |
168 | */ | |
169 | public HashMap getFields() { | |
170 | HashMap values = new HashMap(); | |
171 |
1
1. getFields : removed call to com/lowagie/text/pdf/FdfWriter::iterateFields → NO_COVERAGE |
iterateFields(values, fields, ""); |
172 |
1
1. getFields : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getFields to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return values; |
173 | } | |
174 | | |
175 | /** Gets the field value. | |
176 | * @param field the field name | |
177 | * @return the field value or <CODE>null</CODE> if not found | |
178 | */ | |
179 | public String getField(String field) { | |
180 | HashMap map = fields; | |
181 | StringTokenizer tk = new StringTokenizer(field, "."); | |
182 |
1
1. getField : negated conditional → NO_COVERAGE |
if (!tk.hasMoreTokens()) |
183 |
1
1. getField : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getField to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
184 | while (true) { | |
185 | String s = tk.nextToken(); | |
186 | Object obj = map.get(s); | |
187 |
1
1. getField : negated conditional → NO_COVERAGE |
if (obj == null) |
188 |
1
1. getField : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getField to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
189 |
1
1. getField : negated conditional → NO_COVERAGE |
if (tk.hasMoreTokens()) { |
190 |
1
1. getField : negated conditional → NO_COVERAGE |
if (obj instanceof HashMap) |
191 | map = (HashMap)obj; | |
192 | else | |
193 |
1
1. getField : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getField to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
194 | } | |
195 | else { | |
196 |
1
1. getField : negated conditional → NO_COVERAGE |
if (obj instanceof HashMap) |
197 |
1
1. getField : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getField to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
198 | else { | |
199 |
1
1. getField : negated conditional → NO_COVERAGE |
if (((PdfObject)obj).isString()) |
200 |
1
1. getField : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getField to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ((PdfString)obj).toUnicodeString(); |
201 | else | |
202 |
1
1. getField : mutated return of Object value for com/lowagie/text/pdf/FdfWriter::getField to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return PdfName.decodeName(obj.toString()); |
203 | } | |
204 | } | |
205 | } | |
206 | } | |
207 | | |
208 | /** Sets the field value as a name. | |
209 | * @param field the fully qualified field name | |
210 | * @param value the value | |
211 | * @return <CODE>true</CODE> if the value was inserted, | |
212 | * <CODE>false</CODE> if the name is incompatible with | |
213 | * an existing field | |
214 | */ | |
215 | public boolean setFieldAsName(String field, String value) { | |
216 |
1
1. setFieldAsName : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return setField(field, new PdfName(value)); |
217 | } | |
218 | | |
219 | /** Sets the field value as a string. | |
220 | * @param field the fully qualified field name | |
221 | * @param value the value | |
222 | * @return <CODE>true</CODE> if the value was inserted, | |
223 | * <CODE>false</CODE> if the name is incompatible with | |
224 | * an existing field | |
225 | */ | |
226 | public boolean setFieldAsString(String field, String value) { | |
227 |
1
1. setFieldAsString : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return setField(field, new PdfString(value, PdfObject.TEXT_UNICODE)); |
228 | } | |
229 | | |
230 | /** | |
231 | * Sets the field value as a <CODE>PDFAction</CODE>. | |
232 | * For example, this method allows setting a form submit button action using {@link PdfAction#createSubmitForm(String, Object[], int)}. | |
233 | * This method creates an <CODE>A</CODE> entry for the specified field in the underlying FDF file. | |
234 | * Method contributed by Philippe Laflamme (plaflamme) | |
235 | * @param field the fully qualified field name | |
236 | * @param action the field's action | |
237 | * @return <CODE>true</CODE> if the value was inserted, | |
238 | * <CODE>false</CODE> if the name is incompatible with | |
239 | * an existing field | |
240 | * @since 2.1.5 | |
241 | */ | |
242 | public boolean setFieldAsAction(String field, PdfAction action) { | |
243 | return setField(field, action); | |
244 | } | |
245 | | |
246 | /** Sets all the fields from this <CODE>FdfReader</CODE> | |
247 | * @param fdf the <CODE>FdfReader</CODE> | |
248 | */ | |
249 | public void setFields(FdfReader fdf) { | |
250 | Map<String, PdfDictionary> map = fdf.getFields(); | |
251 | for (Map.Entry<String, PdfDictionary> entry : map.entrySet()) { | |
252 | String key = entry.getKey(); | |
253 | PdfDictionary dic = entry.getValue(); | |
254 | PdfObject v = dic.get(PdfName.V); | |
255 |
1
1. setFields : negated conditional → NO_COVERAGE |
if (v != null) { |
256 | setField(key, v); | |
257 | } | |
258 | v = dic.get(PdfName.A); // (plaflamme) | |
259 |
1
1. setFields : negated conditional → NO_COVERAGE |
if (v != null) { |
260 | setField(key, v); | |
261 | } | |
262 | } | |
263 | } | |
264 | | |
265 | /** Sets all the fields from this <CODE>PdfReader</CODE> | |
266 | * @param pdf the <CODE>PdfReader</CODE> | |
267 | */ | |
268 | public void setFields(PdfReader pdf) { | |
269 |
1
1. setFields : removed call to com/lowagie/text/pdf/FdfWriter::setFields → NO_COVERAGE |
setFields(pdf.getAcroFields()); |
270 | } | |
271 | | |
272 | /** Sets all the fields from this <CODE>AcroFields</CODE> | |
273 | * @param af the <CODE>AcroFields</CODE> | |
274 | */ | |
275 | public void setFields(AcroFields af) { | |
276 | for (Object o : af.getFields().entrySet()) { | |
277 | Map.Entry entry = (Map.Entry) o; | |
278 | String fn = (String) entry.getKey(); | |
279 | AcroFields.Item item = (AcroFields.Item) entry.getValue(); | |
280 | PdfDictionary dic = item.getMerged(0); | |
281 | PdfObject v = PdfReader.getPdfObjectRelease(dic.get(PdfName.V)); | |
282 |
1
1. setFields : negated conditional → NO_COVERAGE |
if (v == null) |
283 | continue; | |
284 | PdfObject ft = PdfReader.getPdfObjectRelease(dic.get(PdfName.FT)); | |
285 |
2
1. setFields : negated conditional → NO_COVERAGE 2. setFields : negated conditional → NO_COVERAGE |
if (ft == null || PdfName.SIG.equals(ft)) |
286 | continue; | |
287 | setField(fn, v); | |
288 | } | |
289 | } | |
290 | | |
291 | /** Gets the PDF file name associated with the FDF. | |
292 | * @return the PDF file name associated with the FDF | |
293 | */ | |
294 | public String getFile() { | |
295 | return this.file; | |
296 | } | |
297 | | |
298 | /** Sets the PDF file name associated with the FDF. | |
299 | * @param file the PDF file name associated with the FDF | |
300 | * | |
301 | */ | |
302 | public void setFile(String file) { | |
303 | this.file = file; | |
304 | } | |
305 | | |
306 | static class Wrt extends PdfWriter { | |
307 | private FdfWriter fdf; | |
308 | | |
309 | Wrt(OutputStream os, FdfWriter fdf) throws IOException { | |
310 | super(new PdfDocument(), os); | |
311 | this.fdf = fdf; | |
312 |
1
1. |
this.os.write(HEADER_FDF); |
313 | body = new PdfBody(this); | |
314 | } | |
315 | | |
316 | void writeTo() throws IOException { | |
317 | PdfDictionary dic = new PdfDictionary(); | |
318 |
1
1. writeTo : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.FIELDS, calculate(fdf.fields)); |
319 |
1
1. writeTo : negated conditional → NO_COVERAGE |
if (fdf.file != null) |
320 |
1
1. writeTo : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.F, new PdfString(fdf.file, PdfObject.TEXT_UNICODE)); |
321 | PdfDictionary fd = new PdfDictionary(); | |
322 |
1
1. writeTo : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
fd.put(PdfName.FDF, dic); |
323 | PdfIndirectReference ref = addToBody(fd).getIndirectReference(); | |
324 |
1
1. writeTo : removed call to com/lowagie/text/pdf/OutputStreamCounter::write → NO_COVERAGE |
os.write(getISOBytes("trailer\n")); |
325 | PdfDictionary trailer = new PdfDictionary(); | |
326 |
1
1. writeTo : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
trailer.put(PdfName.ROOT, ref); |
327 |
1
1. writeTo : removed call to com/lowagie/text/pdf/PdfDictionary::toPdf → NO_COVERAGE |
trailer.toPdf(null, os); |
328 |
1
1. writeTo : removed call to com/lowagie/text/pdf/OutputStreamCounter::write → NO_COVERAGE |
os.write(getISOBytes("\n%%EOF\n")); |
329 |
1
1. writeTo : removed call to com/lowagie/text/pdf/OutputStreamCounter::close → NO_COVERAGE |
os.close(); |
330 | } | |
331 | | |
332 | | |
333 | PdfArray calculate(HashMap map) { | |
334 | PdfArray ar = new PdfArray(); | |
335 | for (Object o : map.entrySet()) { | |
336 | Map.Entry entry = (Map.Entry) o; | |
337 | String key = (String) entry.getKey(); | |
338 | Object v = entry.getValue(); | |
339 | PdfDictionary dic = new PdfDictionary(); | |
340 |
1
1. calculate : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.T, new PdfString(key, PdfObject.TEXT_UNICODE)); |
341 |
1
1. calculate : negated conditional → NO_COVERAGE |
if (v instanceof HashMap) { |
342 |
1
1. calculate : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.KIDS, calculate((HashMap) v)); |
343 |
1
1. calculate : negated conditional → NO_COVERAGE |
} else if (v instanceof PdfAction) { // (plaflamme) |
344 |
1
1. calculate : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.A, (PdfAction) v); |
345 | } else { | |
346 |
1
1. calculate : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.V, (PdfObject) v); |
347 | } | |
348 | ar.add(dic); | |
349 | } | |
350 |
1
1. calculate : mutated return of Object value for com/lowagie/text/pdf/FdfWriter$Wrt::calculate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ar; |
351 | } | |
352 | } | |
353 | } | |
Mutations | ||
78 |
1.1 |
|
84 |
1.1 |
|
85 |
1.1 |
|
89 |
1.1 |
|
90 |
1.1 |
|
96 |
1.1 |
|
99 |
1.1 |
|
102 |
1.1 |
|
104 |
1.1 |
|
107 |
1.1 |
|
117 |
1.1 |
|
118 |
1.1 |
|
132 |
1.1 |
|
133 |
1.1 |
|
138 |
1.1 |
|
139 |
1.1 |
|
142 |
1.1 |
|
143 |
1.1 |
|
146 |
1.1 |
|
149 |
1.1 |
|
150 |
1.1 |
|
155 |
1.1 2.2 3.3 4.4 |
|
157 |
1.1 |
|
159 |
1.1 |
|
162 |
1.1 |
|
171 |
1.1 |
|
172 |
1.1 |
|
182 |
1.1 |
|
183 |
1.1 |
|
187 |
1.1 |
|
188 |
1.1 |
|
189 |
1.1 |
|
190 |
1.1 |
|
193 |
1.1 |
|
196 |
1.1 |
|
197 |
1.1 |
|
199 |
1.1 |
|
200 |
1.1 |
|
202 |
1.1 |
|
216 |
1.1 |
|
227 |
1.1 |
|
255 |
1.1 |
|
259 |
1.1 |
|
269 |
1.1 |
|
282 |
1.1 |
|
285 |
1.1 2.2 |
|
312 |
1.1 |
|
318 |
1.1 |
|
319 |
1.1 |
|
320 |
1.1 |
|
322 |
1.1 |
|
324 |
1.1 |
|
326 |
1.1 |
|
327 |
1.1 |
|
328 |
1.1 |
|
329 |
1.1 |
|
340 |
1.1 |
|
341 |
1.1 |
|
342 |
1.1 |
|
343 |
1.1 |
|
344 |
1.1 |
|
346 |
1.1 |
|
350 |
1.1 |