KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > pdmodel > interactive > form > PDField


1 /**
2  * Copyright (c) 2003-2006, www.pdfbox.org
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * 3. Neither the name of pdfbox; nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * http://www.pdfbox.org
29  *
30  */

31 package org.pdfbox.pdmodel.interactive.form;
32
33 import org.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions;
34 import org.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
35
36 import org.pdfbox.pdmodel.common.COSArrayList;
37 import org.pdfbox.pdmodel.common.COSObjectable;
38
39 import org.pdfbox.cos.COSArray;
40 import org.pdfbox.cos.COSBase;
41 import org.pdfbox.cos.COSDictionary;
42 import org.pdfbox.cos.COSInteger;
43 import org.pdfbox.cos.COSName;
44
45 import org.pdfbox.pdmodel.common.PDTextStream;
46
47 import org.pdfbox.pdmodel.fdf.FDFField;
48 import org.pdfbox.util.BitFlagHelper;
49
50 import java.io.IOException JavaDoc;
51
52 import java.util.ArrayList JavaDoc;
53 import java.util.List JavaDoc;
54
55 /**
56  * This is the superclass for a Field element in a PDF.
57  * Based on the COS object model from PDFBox.
58  *
59  * @author sug
60  * @version $Revision: 1.23 $
61  */

62 public abstract class PDField implements COSObjectable
63 {
64     /**
65      * A Ff flag.
66      */

67     public static final int FLAG_READ_ONLY = 1;
68     /**
69      * A Ff flag.
70      */

71     public static final int FLAG_REQUIRED = 1 << 1;
72     /**
73      * A Ff flag.
74      */

75     public static final int FLAG_NO_EXPORT = 1 << 2;
76     
77     
78     private PDAcroForm acroForm;
79
80     private COSDictionary dictionary;
81
82     /**
83      * Constructor.
84      *
85      * @param theAcroForm The form that this field is part of.
86      */

87     public PDField( PDAcroForm theAcroForm )
88     {
89         acroForm = theAcroForm;
90         dictionary = new COSDictionary();
91         //no required fields in base field class
92
}
93
94
95     /**
96      * Creates a COSField from a COSDictionary, expected to be
97      * a correct object definition for a field in PDF.
98      *
99      * @param theAcroForm The form that this field is part of.
100      * @param field the PDF objet to represent as a field.
101      */

102     public PDField(PDAcroForm theAcroForm, COSDictionary field)
103     {
104         acroForm = theAcroForm;
105         dictionary = field;
106     }
107
108     /**
109      * Returns the partial name of the field.
110      *
111      * @return the name of the field
112      */

113     public String JavaDoc getPartialName()
114     {
115         return getDictionary().getString( "T" );
116     }
117
118     /**
119      * This will set the partial name of the field.
120      *
121      * @param name The new name for the field.
122      */

123     public void setPartialName( String JavaDoc name )
124     {
125         getDictionary().setString( "T", name );
126     }
127     
128     /**
129      * Returns the fully qualified name of the field, which is a concatenation of
130      * the names of all the parents fields.
131      *
132      * @return the name of the field
133      *
134      * @throws IOException If there is an error generating the fully qualified name.
135      */

136     public String JavaDoc getFullyQualifiedName() throws IOException JavaDoc
137     {
138         PDField parent = getParent();
139         String JavaDoc parentName = null;
140         if( parent != null )
141         {
142             parentName = parent.getFullyQualifiedName();
143         }
144         String JavaDoc finalName = getPartialName();
145         if( parentName != null )
146         {
147             finalName = parentName + "." + finalName;
148         }
149         return finalName;
150     }
151     
152     /**
153      * Get the FT entry of the field. This is a read only field and is set depending
154      * on the actual type. The field type is an inheritable attribute. This method will
155      * return only the direct value on this object. Use the findFieldType for an upward
156      * recursive search.
157      *
158      * @return The Field type.
159      *
160      * @see PDField#findFieldType()
161      */

162     public String JavaDoc getFieldType()
163     {
164         return getDictionary().getNameAsString( "FT" );
165     }
166     
167     /**
168      * Find the field type and optionally do a recursive upward search. Sometimes the fieldtype
169      * will be specified on the parent instead of the direct object. This will look at this
170      * object for the field type, if none is specified then it will look to the parent if there
171      * is a parent. If there is no parent and no field type has been found then this
172      * will return null.
173      *
174      * @return The field type or null if none was found.
175      */

176     public String JavaDoc findFieldType()
177     {
178         return findFieldType( getDictionary() );
179     }
180     
181     private String JavaDoc findFieldType( COSDictionary dic )
182     {
183         String JavaDoc retval = dic.getNameAsString( "FT" );
184         if( retval == null )
185         {
186             COSDictionary parent = (COSDictionary)dic.getDictionaryObject( "Parent", "P" );
187             if( parent != null )
188             {
189                 retval = findFieldType( parent );
190             }
191         }
192         return retval;
193         
194     }
195
196
197     /**
198      * setValue sets the fields value to a given string.
199      *
200      * @param value the string value
201      *
202      * @throws IOException If there is an error creating the appearance stream.
203      */

204     public abstract void setValue(String JavaDoc value) throws IOException JavaDoc;
205     
206     /**
207      * getValue gets the fields value to as a string.
208      *
209      * @return The string value of this field.
210      *
211      * @throws IOException If there is an error getting the value.
212      */

213     public abstract String JavaDoc getValue() throws IOException JavaDoc;
214
215     /**
216      * sets the field to be read-only.
217      *
218      * @param readonly The new flag for readonly.
219      */

220     public void setReadonly(boolean readonly)
221     {
222         BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_READ_ONLY, readonly );
223     }
224
225     /**
226      *
227      * @return true if the field is readonly
228      */

229     public boolean isReadonly()
230     {
231         return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_READ_ONLY );
232     }
233     
234     /**
235      * sets the field to be required.
236      *
237      * @param required The new flag for required.
238      */

239     public void setRequired(boolean required)
240     {
241         BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_REQUIRED, required );
242     }
243
244     /**
245      *
246      * @return true if the field is required
247      */

248     public boolean isRequired()
249     {
250         return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_REQUIRED );
251     }
252     
253     /**
254      * sets the field to be not exported..
255      *
256      * @param noExport The new flag for noExport.
257      */

258     public void setNoExport(boolean noExport)
259     {
260         BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_NO_EXPORT, noExport );
261     }
262
263     /**
264      *
265      * @return true if the field is not to be exported.
266      */

267     public boolean isNoExport()
268     {
269         return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_NO_EXPORT );
270     }
271
272     /**
273      * This will get the flags for this field.
274      *
275      * @return flags The set of flags.
276      */

277     public int getFieldFlags()
278     {
279         int retval = 0;
280         COSInteger ff = (COSInteger)getDictionary().getDictionaryObject( COSName.getPDFName( "Ff" ) );
281         if( ff != null )
282         {
283             retval = ff.intValue();
284         }
285         return retval;
286     }
287
288     /**
289      * This will set the flags for this field.
290      *
291      * @param flags The new flags.
292      */

293     public void setFieldFlags( int flags )
294     {
295         COSInteger ff = new COSInteger( flags );
296         getDictionary().setItem( COSName.getPDFName( "Ff" ), ff );
297     }
298
299     /**
300      * This will import a fdf field from a fdf document.
301      *
302      * @param fdfField The fdf field to import.
303      *
304      * @throws IOException If there is an error importing the data for this field.
305      */

306     public void importFDF( FDFField fdfField ) throws IOException JavaDoc
307     {
308         Object JavaDoc fieldValue = fdfField.getValue();
309         int fieldFlags = getFieldFlags();
310
311         if( fieldValue != null )
312         {
313             if( fieldValue instanceof String JavaDoc )
314             {
315                 setValue( (String JavaDoc)fieldValue );
316             }
317             else if( fieldValue instanceof PDTextStream )
318             {
319                 setValue( ((PDTextStream)fieldValue).getAsString() );
320             }
321             else
322             {
323                 throw new IOException JavaDoc( "Unknown field type:" + fieldValue.getClass().getName() );
324             }
325         }
326         Integer JavaDoc ff = fdfField.getFieldFlags();
327         if( ff != null )
328         {
329             setFieldFlags( ff.intValue() );
330         }
331         else
332         {
333             //these are suppose to be ignored if the Ff is set.
334
Integer JavaDoc setFf = fdfField.getSetFieldFlags();
335
336             if( setFf != null )
337             {
338                 int setFfInt = setFf.intValue();
339                 fieldFlags = fieldFlags | setFfInt;
340                 setFieldFlags( fieldFlags );
341             }
342
343             Integer JavaDoc clrFf = fdfField.getClearFieldFlags();
344             if( clrFf != null )
345             {
346                 //we have to clear the bits of the document fields for every bit that is
347
//set in this field.
348
//
349
//Example:
350
//docFf = 1011
351
//clrFf = 1101
352
//clrFfValue = 0010;
353
//newValue = 1011 & 0010 which is 0010
354
int clrFfValue = clrFf.intValue();
355                 clrFfValue ^= 0xFFFFFFFF;
356                 fieldFlags = fieldFlags & clrFfValue;
357                 setFieldFlags( fieldFlags );
358             }
359         }
360
361         PDAnnotationWidget widget = getWidget();
362         if( widget != null )
363         {
364             int annotFlags = widget.getAnnotationFlags();
365             Integer JavaDoc f = fdfField.getWidgetFieldFlags();
366             if( f != null && widget != null )
367             {
368                 widget.setAnnotationFlags( f.intValue() );
369             }
370             else
371             {
372                 //these are suppose to be ignored if the F is set.
373
Integer JavaDoc setF = fdfField.getSetWidgetFieldFlags();
374                 if( setF != null )
375                 {
376                     annotFlags = annotFlags | setF.intValue();
377                     widget.setAnnotationFlags( annotFlags );
378                 }
379
380                 Integer JavaDoc clrF = fdfField.getClearWidgetFieldFlags();
381                 if( clrF != null )
382                 {
383                     //we have to clear the bits of the document fields for every bit that is
384
//set in this field.
385
//
386
//Example:
387
//docF = 1011
388
//clrF = 1101
389
//clrFValue = 0010;
390
//newValue = 1011 & 0010 which is 0010
391
int clrFValue = clrF.intValue();
392                     clrFValue ^= 0xFFFFFFFFL;
393                     annotFlags = annotFlags & clrFValue;
394                     widget.setAnnotationFlags( annotFlags );
395                 }
396             }
397         }
398         List fdfKids = fdfField.getKids();
399         List pdKids = getKids();
400         for( int i=0; fdfKids != null && i<fdfKids.size(); i++ )
401         {
402             FDFField fdfChild = (FDFField)fdfKids.get( i );
403             String JavaDoc fdfName = fdfChild.getPartialFieldName();
404             for( int j=0; j<pdKids.size(); j++ )
405             {
406                 Object JavaDoc pdChildObj = pdKids.get( j );
407                 if( pdChildObj instanceof PDField )
408                 {
409                     PDField pdChild = (PDField)pdChildObj;
410                     if( fdfName != null && fdfName.equals( pdChild.getPartialName() ) )
411                     {
412                         pdChild.importFDF( fdfChild );
413                     }
414                 }
415             }
416         }
417     }
418
419     /**
420      * This will get the single associated widget that is part of this field. This
421      * occurs when the Widget is embedded in the fields dictionary. Sometimes there
422      * are multiple sub widgets associated with this field, in which case you want to
423      * use getKids(). If the kids entry is specified, then the first entry in that
424      * list will be returned.
425      *
426      * @return The widget that is associated with this field.
427      * @throws IOException If there is an error getting the widget object.
428      */

429     public PDAnnotationWidget getWidget() throws IOException JavaDoc
430     {
431         PDAnnotationWidget retval = null;
432         List kids = getKids();
433         if( kids == null )
434         {
435             retval = new PDAnnotationWidget( getDictionary() );
436         }
437         else if( kids.size() > 0 )
438         {
439             Object JavaDoc firstKid = kids.get( 0 );
440             if( firstKid instanceof PDAnnotationWidget )
441             {
442                 retval = (PDAnnotationWidget)firstKid;
443             }
444             else
445             {
446                 retval = ((PDField)firstKid).getWidget();
447             }
448         }
449         else
450         {
451             retval = null;
452         }
453         return retval;
454     }
455     
456     /**
457      * Get the parent field to this field, or null if none exists.
458      *
459      * @return The parent field.
460      *
461      * @throws IOException If there is an error creating the parent field.
462      */

463     public PDField getParent() throws IOException JavaDoc
464     {
465         PDField parent = null;
466         COSDictionary parentDic = (COSDictionary)getDictionary().getDictionaryObject( "Parent" );
467         if( parentDic != null )
468         {
469             parent = PDFieldFactory.createField( getAcroForm(), parentDic );
470         }
471         return parent;
472     }
473     
474     /**
475      * Set the parent of this field.
476      *
477      * @param parent The parent to this field.
478      */

479     public void setParent( PDField parent )
480     {
481         getDictionary().setItem( "Parent", parent );
482     }
483     
484     /**
485      * This will find one of the child elements. The name array are the components
486      * of the name to search down the tree of names. The nameIndex is where to
487      * start in that array. This method is called recursively until it finds
488      * the end point based on the name array.
489      *
490      * @param name An array that picks the path to the field.
491      * @param nameIndex The index into the array.
492      * @return The field at the endpoint or null if none is found.
493      * @throws IOException If there is an error creating the field.
494      */

495     public PDField findKid( String JavaDoc[] name, int nameIndex ) throws IOException JavaDoc
496     {
497         PDField retval = null;
498         COSArray kids = (COSArray)getDictionary().getDictionaryObject( COSName.KIDS );
499         if( kids != null )
500         {
501             for (int i = 0; retval == null && i < kids.size(); i++)
502             {
503                 COSDictionary kidDictionary = (COSDictionary)kids.getObject(i);
504                 if( name[nameIndex].equals( kidDictionary.getString( "T" ) ) )
505                 {
506                     retval = PDFieldFactory.createField( acroForm, kidDictionary );
507                     if( name.length > nameIndex+1 )
508                     {
509                         retval = retval.findKid( name, nameIndex+1 );
510                     }
511                 }
512             }
513         }
514         return retval;
515     }
516
517     /**
518      * This will get all the kids of this field. The values in the list
519      * will either be PDWidget or PDField. Normally they will be PDWidget objects
520      * unless this is a non-terminal field and they will be child PDField objects.
521      *
522      * @return A list of either PDWidget or PDField objects.
523      * @throws IOException If there is an error retrieving the kids.
524      */

525     public List getKids() throws IOException JavaDoc
526     {
527         List retval = null;
528         COSArray kids = (COSArray)getDictionary().getDictionaryObject(COSName.KIDS);
529         if( kids != null )
530         {
531             List kidsList = new ArrayList();
532             for (int i = 0; i < kids.size(); i++)
533             {
534                 COSDictionary kidDictionary = (COSDictionary)kids.getObject(i);
535                 COSDictionary parent = (COSDictionary)kidDictionary.getDictionaryObject( "Parent" );
536                 if( kidDictionary.getDictionaryObject( "FT" ) != null ||
537                     (parent != null && parent.getDictionaryObject( "FT" ) != null ) )
538                 {
539                     kidsList.add( PDFieldFactory.createField( acroForm, kidDictionary ));
540                 }
541                 else if( "Widget".equals( kidDictionary.getNameAsString( "Subtype" ) ) )
542                 {
543                     kidsList.add( new PDAnnotationWidget( kidDictionary ) );
544                 }
545                 else
546                 {
547                     //
548
kidsList.add( PDFieldFactory.createField( acroForm, kidDictionary ));
549                 }
550             }
551             retval = new COSArrayList( kidsList, kids );
552         }
553         return retval;
554     }
555
556     /**
557      * This will set the list of kids.
558      *
559      * @param kids The list of child widgets.
560      */

561     public void setKids( List kids )
562     {
563         COSArray kidsArray = COSArrayList.converterToCOSArray( kids );
564         getDictionary().setItem( COSName.KIDS, kidsArray );
565     }
566
567     /**
568      * This will return a string representation of this field.
569      *
570      * @return A string representation of this field.
571      */

572     public String JavaDoc toString()
573     {
574         return "" + getDictionary().getDictionaryObject( COSName.getPDFName( "V" ) );
575     }
576
577     /**
578      * This will get the acroform that this field is part of.
579      *
580      * @return The form this field is on.
581      */

582     public PDAcroForm getAcroForm()
583     {
584         return acroForm;
585     }
586
587     /**
588      * This will set the form this field is on.
589      *
590      * @param value The new form to use.
591      */

592     public void setAcroForm(PDAcroForm value)
593     {
594         acroForm = value;
595     }
596
597     /**
598      * This will get the dictionary associated with this field.
599      *
600      * @return The dictionary that this class wraps.
601      */

602     public COSDictionary getDictionary()
603     {
604         return dictionary;
605     }
606
607     /**
608      * Convert this standard java object to a COS object.
609      *
610      * @return The cos object that matches this Java object.
611      */

612     public COSBase getCOSObject()
613     {
614         return dictionary;
615     }
616     
617     /**
618      * Get the additional actions for this field. This will return null
619      * if there are no additional actions for this field.
620      *
621      * @return The actions of the field.
622      */

623     public PDFormFieldAdditionalActions getActions()
624     {
625         COSDictionary aa = (COSDictionary)dictionary.getDictionaryObject( "AA" );
626         PDFormFieldAdditionalActions retval = null;
627         if( aa != null )
628         {
629             retval = new PDFormFieldAdditionalActions( aa );
630         }
631         return retval;
632     }
633     
634     /**
635      * Set the actions of the field.
636      *
637      * @param actions The field actions.
638      */

639     public void setActions( PDFormFieldAdditionalActions actions )
640     {
641         dictionary.setItem( "AA", actions );
642     }
643 }
Popular Tags