1 /*
2 * $Id: PdfArray.java 3761 2009-03-06 16:33:57Z blowagie $
3 *
4 * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * (the "License"); you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the License.
13 *
14 * The Original Code is 'iText, a free JAVA-PDF library'.
15 *
16 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18 * All Rights Reserved.
19 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21 *
22 * Contributor(s): all the names of the contributors are added in the source code
23 * where applicable.
24 *
25 * Alternatively, the contents of this file may be used under the terms of the
26 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27 * provisions of LGPL are applicable instead of those above. If you wish to
28 * allow use of your version of this file only under the terms of the LGPL
29 * License and not to allow others to use your version of this file under
30 * the MPL, indicate your decision by deleting the provisions above and
31 * replace them with the notice and other provisions required by the LGPL.
32 * If you do not delete the provisions above, a recipient may use your version
33 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34 *
35 * This library is free software; you can redistribute it and/or modify it
36 * under the terms of the MPL as stated above or under the terms of the GNU
37 * Library General Public License as published by the Free Software Foundation;
38 * either version 2 of the License, or any later version.
39 *
40 * This library is distributed in the hope that it will be useful, but WITHOUT
41 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43 * details.
44 *
45 * If you didn't download this code from the following link, you should check if
46 * you aren't using an obsolete version:
47 * http://www.lowagie.com/iText/
48 */
49
50 package com.lowagie.text.pdf;
51
52 import java.io.IOException;
53 import java.io.OutputStream;
54 import java.util.ArrayList;
55 import java.util.Iterator;
56 import java.util.ListIterator;
57
58 /**
59 * <CODE>PdfArray</CODE> is the PDF Array object.
60 * <P>
61 * An array is a sequence of PDF objects. An array may contain a mixture of
62 * object types.
63 * An array is written as a left square bracket ([), followed by a sequence of
64 * objects, followed by a right square bracket (]).<BR>
65 * This object is described in the 'Portable Document Format Reference Manual
66 * version 1.7' section 3.2.5 (page 58).
67 *
68 * @see PdfObject
69 */
70 public class PdfArray extends PdfObject {
71
72 // CLASS VARIABLES
73
74 /** this is the actual array of PdfObjects */
75 protected ArrayList arrayList;
76
77 // constructors
78
79 /**
80 * Constructs an empty <CODE>PdfArray</CODE>-object.
81 */
82 public PdfArray() {
83 super(ARRAY);
84 arrayList = new ArrayList();
85 }
86
87 /**
88 * Constructs an <CODE>PdfArray</CODE>-object, containing 1
89 * <CODE>PdfObject</CODE>.
90 *
91 * @param object a <CODE>PdfObject</CODE> that has to be added to the array
92 */
93 public PdfArray(PdfObject object) {
94 super(ARRAY);
95 arrayList = new ArrayList();
96 arrayList.add(object);
97 }
98
99 /**
100 * Constructs a <CODE>PdfArray</CODE>-object, containing all
101 * <CODE>float</CODE> values in a specified array.
102 *
103 * The <CODE>float</CODE> values are internally converted to
104 * <CODE>PdfNumber</CODE> objects.
105 *
106 * @param values an array of <CODE>float</CODE> values to be added
107 */
108 public PdfArray(float values[]) {
109 super(ARRAY);
110 arrayList = new ArrayList();
111 add(values);
112 }
113
114 /**
115 * Constructs a <CODE>PdfArray</CODE>-object, containing all
116 * <CODE>int</CODE> values in a specified array.
117 *
118 * The <CODE>int</CODE> values are internally converted to
119 * <CODE>PdfNumber</CODE> objects.
120 *
121 * @param values an array of <CODE>int</CODE> values to be added
122 */
123 public PdfArray(int values[]) {
124 super(ARRAY);
125 arrayList = new ArrayList();
126 add(values);
127 }
128
129 /**
130 * Constructs a <CODE>PdfArray</CODE>, containing all elements of a
131 * specified <CODE>ArrayList</CODE>.
132 *
133 * @param l an <CODE>ArrayList</CODE> with <CODE>PdfObject</CODE>s to be
134 * added to the array
135 * @throws ClassCastException if the <CODE>ArrayList</CODE> contains
136 * something that isn't a <CODE>PdfObject</CODE>
137 * @since 2.1.3
138 */
139 public PdfArray(ArrayList l) {
140 this();
141 for (Iterator i = l.iterator(); i.hasNext(); )
142 add((PdfObject)i.next());
143 }
144
145 /**
146 * Constructs an <CODE>PdfArray</CODE>-object, containing all
147 * <CODE>PdfObject</CODE>s in a specified <CODE>PdfArray</CODE>.
148 *
149 * @param array a <CODE>PdfArray</CODE> to be added to the array
150 */
151 public PdfArray(PdfArray array) {
152 super(ARRAY);
153 arrayList = new ArrayList(array.arrayList);
154 }
155
156 // METHODS OVERRIDING SOME PDFOBJECT METHODS
157
158 /**
159 * Writes the PDF representation of this <CODE>PdfArray</CODE> as an array
160 * of <CODE>byte</CODE> to the specified <CODE>OutputStream</CODE>.
161 *
162 * @param writer for backwards compatibility
163 * @param os the <CODE>OutputStream</CODE> to write the bytes to.
164 */
165 public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
166 os.write('[');
167
168 Iterator i = arrayList.iterator();
169 PdfObject object;
170 int type = 0;
171 if (i.hasNext()) {
172 object = (PdfObject) i.next();
173 if (object == null)
174 object = PdfNull.PDFNULL;
175 object.toPdf(writer, os);
176 }
177 while (i.hasNext()) {
178 object = (PdfObject) i.next();
179 if (object == null)
180 object = PdfNull.PDFNULL;
181 type = object.type();
182 if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
183 os.write(' ');
184 object.toPdf(writer, os);
185 }
186 os.write(']');
187 }
188
189 /**
190 * Returns a string representation of this <CODE>PdfArray</CODE>.
191 *
192 * The string representation consists of a list of all
193 * <CODE>PdfObject</CODE>s contained in this <CODE>PdfArray</CODE>,
194 * enclosed in square brackets ("[]"). Adjacent elements are separated
195 * by the characters ", " (comma and space).
196 *
197 * @return the string representation of this <CODE>PdfArray</CODE>
198 */
199 public String toString() {
200 return arrayList.toString();
201 }
202
203 // ARRAY CONTENT METHODS
204
205 /**
206 * Overwrites a specified location of the array, returning the previous
207 * value
208 *
209 * @param idx The index of the element to be overwritten
210 * @param obj new value for the specified index
211 * @throws IndexOutOfBoundsException if the specified position doesn't exist
212 * @return the previous value
213 * @since 2.1.5
214 */
215 public PdfObject set(int idx, PdfObject obj) {
216 return (PdfObject) arrayList.set(idx, obj);
217 }
218
219 /**
220 * Remove the element at the specified position from the array.
221 *
222 * Shifts any subsequent elements to the left (subtracts one from their
223 * indices).
224 *
225 * @param idx The index of the element to be removed.
226 * @throws IndexOutOfBoundsException the specified position doesn't exist
227 * @since 2.1.5
228 */
229 public PdfObject remove(int idx) {
230 return (PdfObject) arrayList.remove(idx);
231 }
232
233 /**
234 * Get the internal arrayList for this PdfArray. Not Recommended.
235 *
236 * @deprecated
237 * @return the internal ArrayList. Naughty Naughty.
238 */
239 public ArrayList getArrayList() {
240 return arrayList;
241 }
242
243 /**
244 * Returns the number of entries in the array.
245 *
246 * @return the size of the ArrayList
247 */
248 public int size() {
249 return arrayList.size();
250 }
251
252 /**
253 * Returns <CODE>true</CODE> if the array is empty.
254 *
255 * @return <CODE>true</CODE> if the array is empty
256 * @since 2.1.5
257 */
258 public boolean isEmpty() {
259 return arrayList.isEmpty();
260 }
261
262 /**
263 * Adds a <CODE>PdfObject</CODE> to the end of the <CODE>PdfArray</CODE>.
264 *
265 * The <CODE>PdfObject</CODE> will be the last element.
266 *
267 * @param object <CODE>PdfObject</CODE> to add
268 * @return always <CODE>true</CODE>
269 */
270 public boolean add(PdfObject object) {
271 return arrayList.add(object);
272 }
273
274 /**
275 * Adds an array of <CODE>float</CODE> values to end of the
276 * <CODE>PdfArray</CODE>.
277 *
278 * The values will be the last elements.
279 * The <CODE>float</CODE> values are internally converted to
280 * <CODE>PdfNumber</CODE> objects.
281 *
282 * @param values An array of <CODE>float</CODE> values to add
283 * @return always <CODE>true</CODE>
284 */
285 public boolean add(float values[]) {
286 for (int k = 0; k < values.length; ++k)
287 arrayList.add(new PdfNumber(values[k]));
288 return true;
289 }
290
291 /**
292 * Adds an array of <CODE>int</CODE> values to end of the <CODE>PdfArray</CODE>.
293 *
294 * The values will be the last elements.
295 * The <CODE>int</CODE> values are internally converted to
296 * <CODE>PdfNumber</CODE> objects.
297 *
298 * @param values An array of <CODE>int</CODE> values to add
299 * @return always <CODE>true</CODE>
300 */
301 public boolean add(int values[]) {
302 for (int k = 0; k < values.length; ++k)
303 arrayList.add(new PdfNumber(values[k]));
304 return true;
305 }
306
307 /**
308 * Inserts the specified element at the specified position.
309 *
310 * Shifts the element currently at that position (if any) and
311 * any subsequent elements to the right (adds one to their indices).
312 *
313 * @param index The index at which the specified element is to be inserted
314 * @param element The element to be inserted
315 * @throws IndexOutOfBoundsException if the specified index is larger than the
316 * last position currently set, plus 1.
317 * @since 2.1.5
318 */
319 public void add(int index, PdfObject element) {
320 arrayList.add(index, element);
321 }
322
323 /**
324 * Inserts a <CODE>PdfObject</CODE> at the beginning of the
325 * <CODE>PdfArray</CODE>.
326 *
327 * The <CODE>PdfObject</CODE> will be the first element, any other elements
328 * will be shifted to the right (adds one to their indices).
329 *
330 * @param object The <CODE>PdfObject</CODE> to add
331 */
332 public void addFirst(PdfObject object) {
333 arrayList.add(0, object);
334 }
335
336 /**
337 * Checks if the <CODE>PdfArray</CODE> already contains a certain
338 * <CODE>PdfObject</CODE>.
339 *
340 * @param object The <CODE>PdfObject</CODE> to check
341 * @return <CODE>true</CODE>
342 */
343 public boolean contains(PdfObject object) {
344 return arrayList.contains(object);
345 }
346
347 /**
348 * Returns the list iterator for the array.
349 *
350 * @return a ListIterator
351 */
352 public ListIterator listIterator() {
353 return arrayList.listIterator();
354 }
355
356 /**
357 * Returns the <CODE>PdfObject</CODE> with the specified index.
358 *
359 * A possible indirect references is not resolved, so the returned
360 * <CODE>PdfObject</CODE> may be either a direct object or an indirect
361 * reference, depending on how the object is stored in the
362 * <CODE>PdfArray</CODE>.
363 *
364 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
365 * @return A <CODE>PdfObject</CODE>
366 */
367 public PdfObject getPdfObject(int idx) {
368 return (PdfObject)arrayList.get(idx);
369 }
370
371 /**
372 * Returns the <CODE>PdfObject</CODE> with the specified index, resolving
373 * a possible indirect reference to a direct object.
374 *
375 * Thus this method will never return a <CODE>PdfIndirectReference</CODE>
376 * object.
377 *
378 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
379 * @return A direct <CODE>PdfObject</CODE> or <CODE>null</CODE>
380 */
381 public PdfObject getDirectObject(int idx) {
382 return PdfReader.getPdfObject(getPdfObject(idx));
383 }
384
385 // DOWNCASTING GETTERS
386 // @author Mark A Storer (2/17/06)
387
388 /**
389 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfDictionary</CODE>,
390 * resolving indirect references.
391 *
392 * The object corresponding to the specified index is retrieved and
393 * resolvedto a direct object.
394 * If it is a <CODE>PdfDictionary</CODE>, it is cast down and returned as such.
395 * Otherwise <CODE>null</CODE> is returned.
396 *
397 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
398 * @return the corresponding <CODE>PdfDictionary</CODE> object,
399 * or <CODE>null</CODE>
400 */
401 public PdfDictionary getAsDict(int idx) {
402 PdfDictionary dict = null;
403 PdfObject orig = getDirectObject(idx);
404 if (orig != null && orig.isDictionary())
405 dict = (PdfDictionary) orig;
406 return dict;
407 }
408
409 /**
410 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfArray</CODE>,
411 * resolving indirect references.
412 *
413 * The object corresponding to the specified index is retrieved and
414 * resolved to a direct object.
415 * If it is a <CODE>PdfArray</CODE>, it is cast down and returned as such.
416 * Otherwise <CODE>null</CODE> is returned.
417 *
418 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
419 * @return the corresponding <CODE>PdfArray</CODE> object,
420 * or <CODE>null</CODE>
421 */
422 public PdfArray getAsArray(int idx) {
423 PdfArray array = null;
424 PdfObject orig = getDirectObject(idx);
425 if (orig != null && orig.isArray())
426 array = (PdfArray) orig;
427 return array;
428 }
429
430 /**
431 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfStream</CODE>,
432 * resolving indirect references.
433 *
434 * The object corresponding to the specified index is retrieved and
435 * resolved to a direct object.
436 * If it is a <CODE>PdfStream</CODE>, it is cast down and returned as such.
437 * Otherwise <CODE>null</CODE> is returned.
438 *
439 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
440 * @return the corresponding <CODE>PdfStream</CODE> object,
441 * or <CODE>null</CODE>
442 */
443 public PdfStream getAsStream(int idx) {
444 PdfStream stream = null;
445 PdfObject orig = getDirectObject(idx);
446 if (orig != null && orig.isStream())
447 stream = (PdfStream) orig;
448 return stream;
449 }
450
451 /**
452 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfString</CODE>,
453 * resolving indirect references.
454 *
455 * The object corresponding to the specified index is retrieved and
456 * resolved to a direct object.
457 * If it is a <CODE>PdfString</CODE>, it is cast down and returned as such.
458 * Otherwise <CODE>null</CODE> is returned.
459 *
460 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
461 * @return the corresponding <CODE>PdfString</CODE> object,
462 * or <CODE>null</CODE>
463 */
464 public PdfString getAsString(int idx) {
465 PdfString string = null;
466 PdfObject orig = getDirectObject(idx);
467 if (orig != null && orig.isString())
468 string = (PdfString) orig;
469 return string;
470 }
471
472 /**
473 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfNumber</CODE>,
474 * resolving indirect references.
475 *
476 * The object corresponding to the specified index is retrieved and
477 * resolved to a direct object.
478 * If it is a <CODE>PdfNumber</CODE>, it is cast down and returned as such.
479 * Otherwise <CODE>null</CODE> is returned.
480 *
481 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
482 * @return the corresponding <CODE>PdfNumber</CODE> object,
483 * or <CODE>null</CODE>
484 */
485 public PdfNumber getAsNumber(int idx) {
486 PdfNumber number = null;
487 PdfObject orig = getDirectObject(idx);
488 if (orig != null && orig.isNumber())
489 number = (PdfNumber) orig;
490 return number;
491 }
492
493 /**
494 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfName</CODE>,
495 * resolving indirect references.
496 *
497 * The object corresponding to the specified index is retrieved and
498 * resolved to a direct object.
499 * If it is a <CODE>PdfName</CODE>, it is cast down and returned as such.
500 * Otherwise <CODE>null</CODE> is returned.
501 *
502 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
503 * @return the corresponding <CODE>PdfName</CODE> object,
504 * or <CODE>null</CODE>
505 */
506 public PdfName getAsName(int idx) {
507 PdfName name = null;
508 PdfObject orig = getDirectObject(idx);
509 if (orig != null && orig.isName())
510 name = (PdfName) orig;
511 return name;
512 }
513
514 /**
515 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfBoolean</CODE>,
516 * resolving indirect references.
517 *
518 * The object corresponding to the specified index is retrieved and
519 * resolved to a direct object.
520 * If it is a <CODE>PdfBoolean</CODE>, it is cast down and returned as
521 * such. Otherwise <CODE>null</CODE> is returned.
522 *
523 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
524 * @return the corresponding <CODE>PdfBoolean</CODE> object,
525 * or <CODE>null</CODE>
526 */
527 public PdfBoolean getAsBoolean(int idx) {
528 PdfBoolean bool = null;
529 PdfObject orig = getDirectObject(idx);
530 if (orig != null && orig.isBoolean())
531 bool = (PdfBoolean) orig;
532 return bool;
533 }
534
535 /**
536 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfIndirectReference</CODE>.
537 *
538 * The object corresponding to the specified index is retrieved.
539 * If it is a <CODE>PdfIndirectReference</CODE>, it is cast down and
540 * returned as such. Otherwise <CODE>null</CODE> is returned.
541 *
542 * @param idx The index of the <CODE>PdfObject</CODE> to be returned
543 * @return the corresponding <CODE>PdfIndirectReference</CODE> object,
544 * or <CODE>null</CODE>
545 */
546 public PdfIndirectReference getAsIndirectObject(int idx) {
547 PdfIndirectReference ref = null;
548 PdfObject orig = getPdfObject(idx); // not getDirect this time.
549 if (orig != null && orig.isIndirect())
550 ref = (PdfIndirectReference) orig;
551 return ref;
552 }
553 }
554