001: /**
002: * Copyright (c) 2003-2006, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package org.pdfbox.pdmodel.interactive.form;
031:
032: import org.pdfbox.cos.COSArray;
033: import org.pdfbox.cos.COSBase;
034: import org.pdfbox.cos.COSDictionary;
035: import org.pdfbox.cos.COSName;
036: import org.pdfbox.cos.COSString;
037:
038: import org.pdfbox.pdmodel.PDDocument;
039: import org.pdfbox.pdmodel.PDResources;
040:
041: import org.pdfbox.pdmodel.common.COSArrayList;
042: import org.pdfbox.pdmodel.common.COSObjectable;
043: import org.pdfbox.pdmodel.fdf.FDFDictionary;
044: import org.pdfbox.pdmodel.fdf.FDFDocument;
045: import org.pdfbox.pdmodel.fdf.FDFCatalog;
046: import org.pdfbox.pdmodel.fdf.FDFField;
047:
048: import java.io.IOException;
049:
050: import java.util.ArrayList;
051: import java.util.HashMap;
052: import java.util.Iterator;
053: import java.util.List;
054: import java.util.Map;
055:
056: /**
057: * This class represents the acroform of a PDF document.
058: *
059: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
060: * @version $Revision: 1.14 $
061: */
062: public class PDAcroForm implements COSObjectable {
063: private COSDictionary acroForm;
064: private PDDocument document;
065:
066: private Map fieldCache;
067:
068: /**
069: * Constructor.
070: *
071: * @param doc The document that this form is part of.
072: */
073: public PDAcroForm(PDDocument doc) {
074: document = doc;
075: acroForm = new COSDictionary();
076: COSArray fields = new COSArray();
077: acroForm.setItem(COSName.getPDFName("Fields"), fields);
078: }
079:
080: /**
081: * Constructor.
082: *
083: * @param doc The document that this form is part of.
084: * @param form The existing acroForm.
085: */
086: public PDAcroForm(PDDocument doc, COSDictionary form) {
087: document = doc;
088: acroForm = form;
089: }
090:
091: /**
092: * This will get the document associated with this form.
093: *
094: * @return The PDF document.
095: */
096: public PDDocument getDocument() {
097: return document;
098: }
099:
100: /**
101: * This will get the dictionary that this form wraps.
102: *
103: * @return The dictionary for this form.
104: */
105: public COSDictionary getDictionary() {
106: return acroForm;
107: }
108:
109: /**
110: * This method will import an entire FDF document into the PDF document
111: * that this acroform is part of.
112: *
113: * @param fdf The FDF document to import.
114: *
115: * @throws IOException If there is an error doing the import.
116: */
117: public void importFDF(FDFDocument fdf) throws IOException {
118: List fields = fdf.getCatalog().getFDF().getFields();
119: if (fields != null) {
120: for (int i = 0; i < fields.size(); i++) {
121: FDFField fdfField = (FDFField) fields.get(i);
122: PDField docField = getField(fdfField
123: .getPartialFieldName());
124: if (docField != null) {
125: docField.importFDF(fdfField);
126: }
127: }
128: }
129: }
130:
131: /**
132: * This will export all FDF form data.
133: *
134: * @return An FDF document used to export the document.
135: * @throws IOException If there is an error when exporting the document.
136: */
137: public FDFDocument exportFDF() throws IOException {
138: FDFDocument fdf = new FDFDocument();
139: FDFCatalog catalog = fdf.getCatalog();
140: FDFDictionary fdfDict = new FDFDictionary();
141: catalog.setFDF(fdfDict);
142:
143: List fdfFields = new ArrayList();
144: List fields = getFields();
145: Iterator fieldIter = fields.iterator();
146: while (fieldIter.hasNext()) {
147: PDField docField = (PDField) fieldIter.next();
148: addFieldAndChildren(docField, fdfFields);
149: }
150: fdfDict.setID(document.getDocument().getDocumentID());
151: if (fdfFields.size() > 0) {
152: fdfDict.setFields(fdfFields);
153: }
154: return fdf;
155: }
156:
157: private void addFieldAndChildren(PDField docField, List fdfFields)
158: throws IOException {
159: Object fieldValue = docField.getValue();
160: FDFField fdfField = new FDFField();
161: fdfField.setPartialFieldName(docField.getPartialName());
162: fdfField.setValue(fieldValue);
163: List kids = docField.getKids();
164: List childFDFFields = new ArrayList();
165: if (kids != null) {
166:
167: for (int i = 0; i < kids.size(); i++) {
168: addFieldAndChildren((PDField) kids.get(i),
169: childFDFFields);
170: }
171: if (childFDFFields.size() > 0) {
172: fdfField.setKids(childFDFFields);
173: }
174: }
175: if (fieldValue != null || childFDFFields.size() > 0) {
176: fdfFields.add(fdfField);
177: }
178: }
179:
180: /**
181: * This will return all of the fields in the document. The type
182: * will be a org.pdfbox.pdmodel.field.PDField.
183: *
184: * @return A list of all the fields.
185: * @throws IOException If there is an error while getting the list of fields.
186: */
187: public List getFields() throws IOException {
188: List retval = null;
189: COSArray fields = (COSArray) acroForm
190: .getDictionaryObject(COSName.getPDFName("Fields"));
191:
192: if (fields != null) {
193: List actuals = new ArrayList();
194: for (int i = 0; i < fields.size(); i++) {
195: COSDictionary element = (COSDictionary) fields
196: .getObject(i);
197: if (element != null) {
198: PDField field = PDFieldFactory.createField(this ,
199: element);
200: if (field != null) {
201: actuals.add(field);
202: }
203: }
204: }
205: retval = new COSArrayList(actuals, fields);
206: }
207: return retval;
208: }
209:
210: /**
211: * Set the fields that are part of this AcroForm.
212: *
213: * @param fields The fields that are part of this form.
214: */
215: public void setFields(List fields) {
216: acroForm.setItem("Fields", COSArrayList
217: .converterToCOSArray(fields));
218: }
219:
220: /**
221: * This will tell this form to cache the fields into a Map structure
222: * for fast access via the getField method. The default is false. You would
223: * want this to be false if you were changing the COSDictionary behind the scenes,
224: * otherwise setting this to true is acceptable.
225: *
226: * @param cache A boolean telling if we should cache the fields.
227: * @throws IOException If there is an error while caching the fields.
228: */
229: public void setCacheFields(boolean cache) throws IOException {
230: if (cache) {
231: fieldCache = new HashMap();
232: List fields = getFields();
233: Iterator fieldIter = fields.iterator();
234: while (fieldIter.hasNext()) {
235: PDField next = (PDField) fieldIter.next();
236: fieldCache.put(next.getFullyQualifiedName(), next);
237: }
238: } else {
239: fieldCache = null;
240: }
241: }
242:
243: /**
244: * This will tell if this acro form is caching the fields.
245: *
246: * @return true if the fields are being cached.
247: */
248: public boolean isCachingFields() {
249: return fieldCache != null;
250: }
251:
252: /**
253: * This will get a field by name, possibly using the cache if setCache is true.
254: *
255: * @param name The name of the field to get.
256: *
257: * @return The field with that name of null if one was not found.
258: *
259: * @throws IOException If there is an error getting the field type.
260: */
261: public PDField getField(String name) throws IOException {
262: PDField retval = null;
263: if (fieldCache != null) {
264: retval = (PDField) fieldCache.get(name);
265: } else {
266: String[] nameSubSection = name.split("\\.");
267: COSArray fields = (COSArray) acroForm
268: .getDictionaryObject(COSName.getPDFName("Fields"));
269:
270: for (int i = 0; i < fields.size() && retval == null; i++) {
271: COSDictionary element = (COSDictionary) fields
272: .getObject(i);
273: if (element != null) {
274: COSString fieldName = (COSString) element
275: .getDictionaryObject(COSName
276: .getPDFName("T"));
277: if (fieldName.getString().equals(name)
278: || fieldName.getString().equals(
279: nameSubSection[0])) {
280: PDField root = PDFieldFactory.createField(this ,
281: element);
282:
283: if (nameSubSection.length > 1) {
284: PDField kid = root.findKid(nameSubSection,
285: 1);
286: if (kid != null) {
287: retval = kid;
288: } else {
289: retval = root;
290: }
291: } else {
292: retval = root;
293: }
294: }
295: }
296: }
297: }
298: return retval;
299: }
300:
301: /**
302: * This will get the default resources for the acro form.
303: *
304: * @return The default resources.
305: */
306: public PDResources getDefaultResources() {
307: PDResources retval = null;
308: COSDictionary dr = (COSDictionary) acroForm
309: .getDictionaryObject(COSName.getPDFName("DR"));
310: if (dr != null) {
311: retval = new PDResources(dr);
312: }
313: return retval;
314: }
315:
316: /**
317: * This will set the default resources for the acroform.
318: *
319: * @param dr The new default resources.
320: */
321: public void setDefaultResources(PDResources dr) {
322: COSDictionary drDict = null;
323: if (dr != null) {
324: drDict = dr.getCOSDictionary();
325: }
326: acroForm.setItem(COSName.getPDFName("DR"), drDict);
327: }
328:
329: /**
330: * {@inheritDoc}
331: */
332: public COSBase getCOSObject() {
333: return acroForm;
334: }
335:
336: /**
337: * Get the XFA resource, the XFA resource is only used for PDF 1.5+ forms.
338: *
339: * @return The xfa resource or null if it does not exist.
340: */
341: public PDXFA getXFA() {
342: PDXFA xfa = null;
343: COSBase base = acroForm.getDictionaryObject("XFA");
344: if (base != null) {
345: xfa = new PDXFA(base);
346: }
347: return xfa;
348: }
349:
350: /**
351: * Set the XFA resource, this is only used for PDF 1.5+ forms.
352: *
353: * @param xfa The xfa resource.
354: */
355: public void setXFA(PDXFA xfa) {
356: acroForm.setItem("XFA", xfa);
357: }
358: }
|