001: /*
002: * $Id: PRAcroForm.java 2441 2006-10-27 17:24:01Z xlv $
003: * $Name$
004: *
005: * Copyright 2001, 2002 by Paulo Soares.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * This class written by Mark Thompson, Copyright (C) 2002 by Mark Thompson.
024: *
025: * Contributor(s): all the names of the contributors are added in the source code
026: * where applicable.
027: *
028: * Alternatively, the contents of this file may be used under the terms of the
029: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
030: * provisions of LGPL are applicable instead of those above. If you wish to
031: * allow use of your version of this file only under the terms of the LGPL
032: * License and not to allow others to use your version of this file under
033: * the MPL, indicate your decision by deleting the provisions above and
034: * replace them with the notice and other provisions required by the LGPL.
035: * If you do not delete the provisions above, a recipient may use your version
036: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
037: *
038: * This library is free software; you can redistribute it and/or modify it
039: * under the terms of the MPL as stated above or under the terms of the GNU
040: * Library General Public License as published by the Free Software Foundation;
041: * either version 2 of the License, or any later version.
042: *
043: * This library is distributed in the hope that it will be useful, but WITHOUT
044: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
045: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
046: * details.
047: *
048: * If you didn't download this code from the following link, you should check if
049: * you aren't using an obsolete version:
050: * http://www.lowagie.com/iText/
051: */
052:
053: package com.lowagie.text.pdf;
054:
055: import java.util.ArrayList;
056: import java.util.HashMap;
057: import java.util.Iterator;
058:
059: /**
060: * This class captures an AcroForm on input. Basically, it extends Dictionary
061: * by indexing the fields of an AcroForm
062: * @author Mark Thompson
063: */
064:
065: public class PRAcroForm extends PdfDictionary {
066:
067: /**
068: * This class holds the information for a single field
069: */
070: public static class FieldInformation {
071: String name;
072: PdfDictionary info;
073: PRIndirectReference ref;
074:
075: FieldInformation(String name, PdfDictionary info,
076: PRIndirectReference ref) {
077: this .name = name;
078: this .info = info;
079: this .ref = ref;
080: }
081:
082: public String getName() {
083: return name;
084: }
085:
086: public PdfDictionary getInfo() {
087: return info;
088: }
089:
090: public PRIndirectReference getRef() {
091: return ref;
092: }
093: };
094:
095: ArrayList fields;
096: ArrayList stack;
097: HashMap fieldByName;
098: PdfReader reader;
099:
100: /**
101: * Constructor
102: * @param reader reader of the input file
103: */
104: public PRAcroForm(PdfReader reader) {
105: this .reader = reader;
106: fields = new ArrayList();
107: fieldByName = new HashMap();
108: stack = new ArrayList();
109: }
110:
111: /**
112: * Number of fields found
113: * @return size
114: */
115: public int size() {
116: return fields.size();
117: }
118:
119: public ArrayList getFields() {
120: return fields;
121: }
122:
123: public FieldInformation getField(String name) {
124: return (FieldInformation) fieldByName.get(name);
125: }
126:
127: /**
128: * Given the title (/T) of a reference, return the associated reference
129: * @param name a string containing the path
130: * @return a reference to the field, or null
131: */
132: public PRIndirectReference getRefByName(String name) {
133: FieldInformation fi = (FieldInformation) fieldByName.get(name);
134: if (fi == null)
135: return null;
136: return fi.getRef();
137: }
138:
139: /**
140: * Read, and comprehend the acroform
141: * @param root the docment root
142: */
143: public void readAcroForm(PdfDictionary root) {
144: if (root == null)
145: return;
146: hashMap = root.hashMap;
147: pushAttrib(root);
148: PdfArray fieldlist = (PdfArray) PdfReader
149: .getPdfObjectRelease(root.get(PdfName.FIELDS));
150: iterateFields(fieldlist, null, null);
151: }
152:
153: /**
154: * After reading, we index all of the fields. Recursive.
155: * @param fieldlist An array of fields
156: * @param fieldDict the last field dictionary we encountered (recursively)
157: * @param title the pathname of the field, up to this point or null
158: */
159: protected void iterateFields(PdfArray fieldlist,
160: PRIndirectReference fieldDict, String title) {
161: for (Iterator it = fieldlist.getArrayList().iterator(); it
162: .hasNext();) {
163: PRIndirectReference ref = (PRIndirectReference) it.next();
164: PdfDictionary dict = (PdfDictionary) PdfReader
165: .getPdfObjectRelease(ref);
166:
167: // if we are not a field dictionary, pass our parent's values
168: PRIndirectReference myFieldDict = fieldDict;
169: String myTitle = title;
170: PdfString tField = (PdfString) dict.get(PdfName.T);
171: boolean isFieldDict = tField != null;
172:
173: if (isFieldDict) {
174: myFieldDict = ref;
175: if (title == null)
176: myTitle = tField.toString();
177: else
178: myTitle = title + '.' + tField.toString();
179: }
180:
181: PdfArray kids = (PdfArray) dict.get(PdfName.KIDS);
182: if (kids != null) {
183: pushAttrib(dict);
184: iterateFields(kids, myFieldDict, myTitle);
185: stack.remove(stack.size() - 1); // pop
186: } else { // leaf node
187: if (myFieldDict != null) {
188: PdfDictionary mergedDict = (PdfDictionary) stack
189: .get(stack.size() - 1);
190: if (isFieldDict)
191: mergedDict = mergeAttrib(mergedDict, dict);
192:
193: mergedDict.put(PdfName.T, new PdfString(myTitle));
194: FieldInformation fi = new FieldInformation(myTitle,
195: mergedDict, myFieldDict);
196: fields.add(fi);
197: fieldByName.put(myTitle, fi);
198: }
199: }
200: }
201: }
202:
203: /**
204: * merge field attributes from two dictionaries
205: * @param parent one dictionary
206: * @param child the other dictionary
207: * @return a merged dictionary
208: */
209: protected PdfDictionary mergeAttrib(PdfDictionary parent,
210: PdfDictionary child) {
211: PdfDictionary targ = new PdfDictionary();
212: if (parent != null)
213: targ.putAll(parent);
214:
215: for (Iterator it = child.getKeys().iterator(); it.hasNext();) {
216: PdfName key = (PdfName) it.next();
217: if (key.equals(PdfName.DR) || key.equals(PdfName.DA)
218: || key.equals(PdfName.Q) || key.equals(PdfName.FF)
219: || key.equals(PdfName.DV) || key.equals(PdfName.V)
220: || key.equals(PdfName.FT) || key.equals(PdfName.F)) {
221: targ.put(key, child.get(key));
222: }
223: }
224: return targ;
225: }
226:
227: /**
228: * stack a level of dictionary. Merge in a dictionary from this level
229: */
230: protected void pushAttrib(PdfDictionary dict) {
231: PdfDictionary dic = null;
232: if (!stack.isEmpty()) {
233: dic = (PdfDictionary) stack.get(stack.size() - 1);
234: }
235: dic = mergeAttrib(dic, dict);
236: stack.add(dic);
237: }
238: }
|