KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > pdmodel > PDPageNode


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;
32
33 import org.pdfbox.cos.COSArray;
34 import org.pdfbox.cos.COSBase;
35 import org.pdfbox.cos.COSDictionary;
36 import org.pdfbox.cos.COSName;
37 import org.pdfbox.cos.COSNumber;
38 import org.pdfbox.cos.COSInteger;
39
40 import org.pdfbox.pdmodel.common.COSArrayList;
41 import org.pdfbox.pdmodel.common.COSObjectable;
42 import org.pdfbox.pdmodel.common.PDRectangle;
43
44 import java.util.ArrayList JavaDoc;
45 import java.util.Iterator JavaDoc;
46 import java.util.List JavaDoc;
47
48 /**
49  * This represents a page node in a pdf document.
50  *
51  * @author <a HREF="mailto:ben@benlitchfield.com">Ben Litchfield</a>
52  * @version $Revision: 1.8 $
53  */

54 public class PDPageNode implements COSObjectable
55 {
56     private COSDictionary page;
57
58     /**
59      * Creates a new instance of PDPage.
60      */

61     public PDPageNode()
62     {
63         page = new COSDictionary();
64         page.setItem( COSName.TYPE, COSName.PAGES );
65         page.setItem( COSName.KIDS, new COSArray() );
66         page.setItem( COSName.COUNT, new COSInteger( 0 ) );
67     }
68
69     /**
70      * Creates a new instance of PDPage.
71      *
72      * @param pages The dictionary pages.
73      */

74     public PDPageNode( COSDictionary pages )
75     {
76         page = pages;
77     }
78
79     /**
80      * This will update the count attribute of the page node. This only needs to
81      * be called if you add or remove pages. The PDDocument will call this for you
82      * when you use the PDDocumnet persistence methods. So, basically most clients
83      * will never need to call this.
84      *
85      * @return The update count for this node.
86      */

87     public long updateCount()
88     {
89         long totalCount = 0;
90         List kids = getKids();
91         Iterator JavaDoc kidIter = kids.iterator();
92         while( kidIter.hasNext() )
93         {
94             Object JavaDoc next = kidIter.next();
95             if( next instanceof PDPage )
96             {
97                 totalCount++;
98             }
99             else
100             {
101                 PDPageNode node = (PDPageNode)next;
102                 totalCount += node.updateCount();
103             }
104         }
105         page.setItem( COSName.COUNT, new COSInteger( totalCount ) );
106         return totalCount;
107     }
108
109     /**
110      * This will get the count of descendent page objects.
111      *
112      * @return The total number of descendent page objects.
113      */

114     public long getCount()
115     {
116         return ((COSNumber)page.getDictionaryObject( COSName.COUNT )).intValue();
117     }
118
119     /**
120      * This will get the underlying dictionary that this class acts on.
121      *
122      * @return The underlying dictionary for this class.
123      */

124     public COSDictionary getDictionary()
125     {
126         return page;
127     }
128
129     /**
130      * This is the parent page node.
131      *
132      * @return The parent to this page.
133      */

134     public PDPageNode getParent()
135     {
136         PDPageNode parent = null;
137         COSDictionary parentDic = (COSDictionary)page.getDictionaryObject( "Parent", "P" );
138         if( parentDic != null )
139         {
140             parent = new PDPageNode( parentDic );
141         }
142         return parent;
143     }
144
145     /**
146      * This will set the parent of this page.
147      *
148      * @param parent The parent to this page node.
149      */

150     public void setParent( PDPageNode parent )
151     {
152         page.setItem( COSName.PARENT, parent.getDictionary() );
153     }
154
155     /**
156      * {@inheritDoc}
157      */

158     public COSBase getCOSObject()
159     {
160         return page;
161     }
162
163     /**
164      * This will return all kids of this node, either PDPageNode or PDPage.
165      *
166      * @return All direct descendents of this node.
167      */

168     public List getKids()
169     {
170         List actuals = new ArrayList();
171         COSArray kids = getAllKids(actuals, page, false);
172         return new COSArrayList( actuals, kids );
173     }
174     
175     /**
176      * This will return all kids of this node as PDPage.
177      *
178      * @param result All direct and indirect descendents of this node are added to this list.
179      */

180     public void getAllKids(List result)
181     {
182         getAllKids(result, page, true);
183     }
184     
185     /**
186      * This will return all kids of the given page node as PDPage.
187      *
188      * @param result All direct and optionally indirect descendents of this node are added to this list.
189      * @param page Page dictionary of a page node.
190      * @param recurse if true indirect descendents are processed recursively
191      */

192     private static COSArray getAllKids(List result, COSDictionary page, boolean recurse)
193     {
194         COSArray kids = (COSArray)page.getDictionaryObject( COSName.KIDS );
195         
196         for( int i=0; i<kids.size(); i++ )
197         {
198             COSBase obj = kids.getObject( i );
199             if (obj instanceof COSDictionary)
200             {
201                 COSDictionary kid = (COSDictionary)obj;
202                 if( COSName.PAGE.equals( kid.getDictionaryObject( COSName.TYPE ) ) )
203                 {
204                     result.add( new PDPage( kid ) );
205                 }
206                 else
207                 {
208                     if (recurse)
209                     {
210                         getAllKids(result, kid, recurse);
211                     }
212                     else
213                     {
214                         result.add( new PDPageNode( kid ) );
215                     }
216                 }
217             }
218         }
219         return kids;
220     }
221
222     /**
223      * This will get the resources at this page node and not look up the hierarchy.
224      * This attribute is inheritable, and findResources() should probably used.
225      * This will return null if no resources are available at this level.
226      *
227      * @return The resources at this level in the hierarchy.
228      */

229     public PDResources getResources()
230     {
231         PDResources retval = null;
232         COSDictionary resources = (COSDictionary)page.getDictionaryObject( COSName.RESOURCES );
233         if( resources != null )
234         {
235             retval = new PDResources( resources );
236         }
237         return retval;
238     }
239
240     /**
241      * This will find the resources for this page by looking up the hierarchy until
242      * it finds them.
243      *
244      * @return The resources at this level in the hierarchy.
245      */

246     public PDResources findResources()
247     {
248         PDResources retval = getResources();
249         PDPageNode parent = getParent();
250         if( retval == null && parent != null )
251         {
252             retval = parent.findResources();
253         }
254         return retval;
255     }
256
257     /**
258      * This will set the resources for this page.
259      *
260      * @param resources The new resources for this page.
261      */

262     public void setResources( PDResources resources )
263     {
264         if( resources == null )
265         {
266             page.removeItem( COSName.RESOURCES );
267         }
268         else
269         {
270             page.setItem( COSName.RESOURCES, resources.getCOSDictionary() );
271         }
272     }
273
274     /**
275      * This will get the MediaBox at this page and not look up the hierarchy.
276      * This attribute is inheritable, and findMediaBox() should probably used.
277      * This will return null if no MediaBox are available at this level.
278      *
279      * @return The MediaBox at this level in the hierarchy.
280      */

281     public PDRectangle getMediaBox()
282     {
283         PDRectangle retval = null;
284         COSArray array = (COSArray)page.getDictionaryObject( COSName.MEDIA_BOX );
285         if( array != null )
286         {
287             retval = new PDRectangle( array );
288         }
289         return retval;
290     }
291
292     /**
293      * This will find the MediaBox for this page by looking up the hierarchy until
294      * it finds them.
295      *
296      * @return The MediaBox at this level in the hierarchy.
297      */

298     public PDRectangle findMediaBox()
299     {
300         PDRectangle retval = getMediaBox();
301         PDPageNode parent = getParent();
302         if( retval == null && parent != null )
303         {
304             retval = parent.findMediaBox();
305         }
306         return retval;
307     }
308
309     /**
310      * This will set the mediaBox for this page.
311      *
312      * @param mediaBox The new mediaBox for this page.
313      */

314     public void setMediaBox( PDRectangle mediaBox )
315     {
316         if( mediaBox == null )
317         {
318             page.removeItem( COSName.MEDIA_BOX );
319         }
320         else
321         {
322             page.setItem( COSName.MEDIA_BOX , mediaBox.getCOSArray() );
323         }
324     }
325
326 /**
327      * This will get the CropBox at this page and not look up the hierarchy.
328      * This attribute is inheritable, and findCropBox() should probably used.
329      * This will return null if no CropBox is available at this level.
330      *
331      * @return The CropBox at this level in the hierarchy.
332      */

333     public PDRectangle getCropBox()
334     {
335         PDRectangle retval = null;
336         COSArray array = (COSArray)page.getDictionaryObject( COSName.CROP_BOX );
337         if( array != null )
338         {
339             retval = new PDRectangle( array );
340         }
341         return retval;
342     }
343
344     /**
345      * This will find the CropBox for this page by looking up the hierarchy until
346      * it finds them.
347      *
348      * @return The CropBox at this level in the hierarchy.
349      */

350     public PDRectangle findCropBox()
351     {
352         PDRectangle retval = getCropBox();
353         PDPageNode parent = getParent();
354         if( retval == null && parent != null )
355         {
356             retval = findParentCropBox( parent );
357         }
358
359         //default value for cropbox is the media box
360
if( retval == null )
361         {
362             retval = findMediaBox();
363         }
364         return retval;
365     }
366
367     /**
368      * This will search for a crop box in the parent and return null if it is not
369      * found. It will NOT default to the media box if it cannot be found.
370      *
371      * @param node The node
372      */

373     private PDRectangle findParentCropBox( PDPageNode node )
374     {
375         PDRectangle rect = node.getCropBox();
376         PDPageNode parent = node.getParent();
377         if( rect == null && parent != null )
378         {
379             rect = findParentCropBox( node );
380         }
381         return rect;
382     }
383
384     /**
385      * This will set the CropBox for this page.
386      *
387      * @param cropBox The new CropBox for this page.
388      */

389     public void setCropBox( PDRectangle cropBox )
390     {
391         if( cropBox == null )
392         {
393             page.removeItem( COSName.CROP_BOX );
394         }
395         else
396         {
397             page.setItem( COSName.CROP_BOX, cropBox.getCOSArray() );
398         }
399     }
400
401     /**
402      * A value representing the rotation. This will be null if not set at this level
403      * The number of degrees by which the page should
404      * be rotated clockwise when displayed or printed. The value must be a multiple
405      * of 90.
406      *
407      * This will get the rotation at this page and not look up the hierarchy.
408      * This attribute is inheritable, and findRotation() should probably used.
409      * This will return null if no rotation is available at this level.
410      *
411      * @return The rotation at this level in the hierarchy.
412      */

413     public Integer JavaDoc getRotation()
414     {
415         Integer JavaDoc retval = null;
416         COSNumber value = (COSNumber)page.getDictionaryObject( COSName.ROTATE );
417         if( value != null )
418         {
419             retval = new Integer JavaDoc( value.intValue() );
420         }
421         return retval;
422     }
423
424     /**
425      * This will find the rotation for this page by looking up the hierarchy until
426      * it finds them.
427      *
428      * @return The rotation at this level in the hierarchy.
429      */

430     public int findRotation()
431     {
432         int retval = 0;
433         Integer JavaDoc rotation = getRotation();
434         if( rotation != null )
435         {
436             retval = rotation.intValue();
437         }
438         else
439         {
440             PDPageNode parent = getParent();
441             if( parent != null )
442             {
443                 retval = parent.findRotation();
444             }
445         }
446
447         return retval;
448     }
449
450     /**
451      * This will set the rotation for this page.
452      *
453      * @param rotation The new rotation for this page.
454      */

455     public void setRotation( int rotation )
456     {
457         page.setItem( COSName.ROTATE, new COSInteger( rotation ) );
458     }
459 }
Popular Tags