001/* 002 * $Id: PdfArray.java 4925 2011-07-08 10:51:25Z redlab_b $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.pdf; 045 046import java.io.IOException; 047import java.io.OutputStream; 048import java.util.ArrayList; 049import java.util.Iterator; 050import java.util.List; 051import java.util.ListIterator; 052 053/** 054 * <CODE>PdfArray</CODE> is the PDF Array object. 055 * <P> 056 * An array is a sequence of PDF objects. An array may contain a mixture of 057 * object types. 058 * An array is written as a left square bracket ([), followed by a sequence of 059 * objects, followed by a right square bracket (]).<BR> 060 * This object is described in the 'Portable Document Format Reference Manual 061 * version 1.7' section 3.2.5 (page 58). 062 * 063 * @see PdfObject 064 */ 065public class PdfArray extends PdfObject implements Iterable<PdfObject> { 066 067 // CLASS VARIABLES 068 069 /** this is the actual array of PdfObjects */ 070 protected ArrayList<PdfObject> arrayList; 071 072 // constructors 073 074 /** 075 * Constructs an empty <CODE>PdfArray</CODE>-object. 076 */ 077 public PdfArray() { 078 super(ARRAY); 079 arrayList = new ArrayList<PdfObject>(); 080 } 081 082 /** 083 * Constructs an <CODE>PdfArray</CODE>-object, containing 1 084 * <CODE>PdfObject</CODE>. 085 * 086 * @param object a <CODE>PdfObject</CODE> that has to be added to the array 087 */ 088 public PdfArray(final PdfObject object) { 089 super(ARRAY); 090 arrayList = new ArrayList<PdfObject>(); 091 arrayList.add(object); 092 } 093 094 /** 095 * Constructs a <CODE>PdfArray</CODE>-object, containing all 096 * <CODE>float</CODE> values in a specified array. 097 * 098 * The <CODE>float</CODE> values are internally converted to 099 * <CODE>PdfNumber</CODE> objects. 100 * 101 * @param values an array of <CODE>float</CODE> values to be added 102 */ 103 public PdfArray(final float values[]) { 104 super(ARRAY); 105 arrayList = new ArrayList<PdfObject>(); 106 add(values); 107 } 108 109 /** 110 * Constructs a <CODE>PdfArray</CODE>-object, containing all 111 * <CODE>int</CODE> values in a specified array. 112 * 113 * The <CODE>int</CODE> values are internally converted to 114 * <CODE>PdfNumber</CODE> objects. 115 * 116 * @param values an array of <CODE>int</CODE> values to be added 117 */ 118 public PdfArray(final int values[]) { 119 super(ARRAY); 120 arrayList = new ArrayList<PdfObject>(); 121 add(values); 122 } 123 124 /** 125 * Constructs a <CODE>PdfArray</CODE>, containing all elements of a 126 * specified <CODE>ArrayList</CODE>. 127 * 128 * @param l an <CODE>ArrayList</CODE> with <CODE>PdfObject</CODE>s to be 129 * added to the array 130 * @throws ClassCastException if the <CODE>ArrayList</CODE> contains 131 * something that isn't a <CODE>PdfObject</CODE> 132 * @since 2.1.3 133 */ 134 public PdfArray(final List<PdfObject> l) { 135 this(); 136 for (PdfObject element : l) 137 add(element); 138 } 139 140 /** 141 * Constructs an <CODE>PdfArray</CODE>-object, containing all 142 * <CODE>PdfObject</CODE>s in a specified <CODE>PdfArray</CODE>. 143 * 144 * @param array a <CODE>PdfArray</CODE> to be added to the array 145 */ 146 public PdfArray(final PdfArray array) { 147 super(ARRAY); 148 arrayList = new ArrayList<PdfObject>(array.arrayList); 149 } 150 151 // METHODS OVERRIDING SOME PDFOBJECT METHODS 152 153 /** 154 * Writes the PDF representation of this <CODE>PdfArray</CODE> as an array 155 * of <CODE>byte</CODE> to the specified <CODE>OutputStream</CODE>. 156 * 157 * @param writer for backwards compatibility 158 * @param os the <CODE>OutputStream</CODE> to write the bytes to. 159 */ 160 @Override 161 public void toPdf(final PdfWriter writer, final OutputStream os) throws IOException { 162 os.write('['); 163 164 Iterator<PdfObject> i = arrayList.iterator(); 165 PdfObject object; 166 int type = 0; 167 if (i.hasNext()) { 168 object = i.next(); 169 if (object == null) 170 object = PdfNull.PDFNULL; 171 object.toPdf(writer, os); 172 } 173 while (i.hasNext()) { 174 object = i.next(); 175 if (object == null) 176 object = PdfNull.PDFNULL; 177 type = object.type(); 178 if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING) 179 os.write(' '); 180 object.toPdf(writer, os); 181 } 182 os.write(']'); 183 } 184 185 /** 186 * Returns a string representation of this <CODE>PdfArray</CODE>. 187 * 188 * The string representation consists of a list of all 189 * <CODE>PdfObject</CODE>s contained in this <CODE>PdfArray</CODE>, 190 * enclosed in square brackets ("[]"). Adjacent elements are separated 191 * by the characters ", " (comma and space). 192 * 193 * @return the string representation of this <CODE>PdfArray</CODE> 194 */ 195 @Override 196 public String toString() { 197 return arrayList.toString(); 198 } 199 200 // ARRAY CONTENT METHODS 201 202 /** 203 * Overwrites a specified location of the array, returning the previous 204 * value 205 * 206 * @param idx The index of the element to be overwritten 207 * @param obj new value for the specified index 208 * @throws IndexOutOfBoundsException if the specified position doesn't exist 209 * @return the previous value 210 * @since 2.1.5 211 */ 212 public PdfObject set(final int idx, final PdfObject obj) { 213 return arrayList.set(idx, obj); 214 } 215 216 /** 217 * Remove the element at the specified position from the array. 218 * 219 * Shifts any subsequent elements to the left (subtracts one from their 220 * indices). 221 * 222 * @param idx The index of the element to be removed. 223 * @throws IndexOutOfBoundsException the specified position doesn't exist 224 * @since 2.1.5 225 */ 226 public PdfObject remove(final int idx) { 227 return arrayList.remove(idx); 228 } 229 230 /** 231 * Get the internal arrayList for this PdfArray. Not Recommended. 232 * 233 * @deprecated 234 * @return the internal ArrayList. Naughty Naughty. 235 */ 236 @Deprecated 237 public ArrayList<PdfObject> getArrayList() { 238 return arrayList; 239 } 240 241 /** 242 * Returns the number of entries in the array. 243 * 244 * @return the size of the ArrayList 245 */ 246 public int size() { 247 return arrayList.size(); 248 } 249 250 /** 251 * Returns <CODE>true</CODE> if the array is empty. 252 * 253 * @return <CODE>true</CODE> if the array is empty 254 * @since 2.1.5 255 */ 256 public boolean isEmpty() { 257 return arrayList.isEmpty(); 258 } 259 260 /** 261 * Adds a <CODE>PdfObject</CODE> to the end of the <CODE>PdfArray</CODE>. 262 * 263 * The <CODE>PdfObject</CODE> will be the last element. 264 * 265 * @param object <CODE>PdfObject</CODE> to add 266 * @return always <CODE>true</CODE> 267 */ 268 public boolean add(final PdfObject object) { 269 return arrayList.add(object); 270 } 271 272 /** 273 * Adds an array of <CODE>float</CODE> values to end of the 274 * <CODE>PdfArray</CODE>. 275 * 276 * The values will be the last elements. 277 * The <CODE>float</CODE> values are internally converted to 278 * <CODE>PdfNumber</CODE> objects. 279 * 280 * @param values An array of <CODE>float</CODE> values to add 281 * @return always <CODE>true</CODE> 282 */ 283 public boolean add(final float values[]) { 284 for (int k = 0; k < values.length; ++k) 285 arrayList.add(new PdfNumber(values[k])); 286 return true; 287 } 288 289 /** 290 * Adds an array of <CODE>int</CODE> values to end of the <CODE>PdfArray</CODE>. 291 * 292 * The values will be the last elements. 293 * The <CODE>int</CODE> values are internally converted to 294 * <CODE>PdfNumber</CODE> objects. 295 * 296 * @param values An array of <CODE>int</CODE> values to add 297 * @return always <CODE>true</CODE> 298 */ 299 public boolean add(final int values[]) { 300 for (int k = 0; k < values.length; ++k) 301 arrayList.add(new PdfNumber(values[k])); 302 return true; 303 } 304 305 /** 306 * Inserts the specified element at the specified position. 307 * 308 * Shifts the element currently at that position (if any) and 309 * any subsequent elements to the right (adds one to their indices). 310 * 311 * @param index The index at which the specified element is to be inserted 312 * @param element The element to be inserted 313 * @throws IndexOutOfBoundsException if the specified index is larger than the 314 * last position currently set, plus 1. 315 * @since 2.1.5 316 */ 317 public void add(final int index, final PdfObject element) { 318 arrayList.add(index, element); 319 } 320 321 /** 322 * Inserts a <CODE>PdfObject</CODE> at the beginning of the 323 * <CODE>PdfArray</CODE>. 324 * 325 * The <CODE>PdfObject</CODE> will be the first element, any other elements 326 * will be shifted to the right (adds one to their indices). 327 * 328 * @param object The <CODE>PdfObject</CODE> to add 329 */ 330 public void addFirst(final PdfObject object) { 331 arrayList.add(0, object); 332 } 333 334 /** 335 * Checks if the <CODE>PdfArray</CODE> already contains a certain 336 * <CODE>PdfObject</CODE>. 337 * 338 * @param object The <CODE>PdfObject</CODE> to check 339 * @return <CODE>true</CODE> 340 */ 341 public boolean contains(final PdfObject object) { 342 return arrayList.contains(object); 343 } 344 345 /** 346 * Returns the list iterator for the array. 347 * 348 * @return a ListIterator 349 */ 350 public ListIterator<PdfObject> listIterator() { 351 return arrayList.listIterator(); 352 } 353 354 /** 355 * Returns the <CODE>PdfObject</CODE> with the specified index. 356 * 357 * A possible indirect references is not resolved, so the returned 358 * <CODE>PdfObject</CODE> may be either a direct object or an indirect 359 * reference, depending on how the object is stored in the 360 * <CODE>PdfArray</CODE>. 361 * 362 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 363 * @return A <CODE>PdfObject</CODE> 364 */ 365 public PdfObject getPdfObject(final int idx) { 366 return arrayList.get(idx); 367 } 368 369 /** 370 * Returns the <CODE>PdfObject</CODE> with the specified index, resolving 371 * a possible indirect reference to a direct object. 372 * 373 * Thus this method will never return a <CODE>PdfIndirectReference</CODE> 374 * object. 375 * 376 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 377 * @return A direct <CODE>PdfObject</CODE> or <CODE>null</CODE> 378 */ 379 public PdfObject getDirectObject(final int idx) { 380 return PdfReader.getPdfObject(getPdfObject(idx)); 381 } 382 383 // DOWNCASTING GETTERS 384 // @author Mark A Storer (2/17/06) 385 386 /** 387 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfDictionary</CODE>, 388 * resolving indirect references. 389 * 390 * The object corresponding to the specified index is retrieved and 391 * resolvedto a direct object. 392 * If it is a <CODE>PdfDictionary</CODE>, it is cast down and returned as such. 393 * Otherwise <CODE>null</CODE> is returned. 394 * 395 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 396 * @return the corresponding <CODE>PdfDictionary</CODE> object, 397 * or <CODE>null</CODE> 398 */ 399 public PdfDictionary getAsDict(final int idx) { 400 PdfDictionary dict = null; 401 PdfObject orig = getDirectObject(idx); 402 if (orig != null && orig.isDictionary()) 403 dict = (PdfDictionary) orig; 404 return dict; 405 } 406 407 /** 408 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfArray</CODE>, 409 * resolving indirect references. 410 * 411 * The object corresponding to the specified index is retrieved and 412 * resolved to a direct object. 413 * If it is a <CODE>PdfArray</CODE>, it is cast down and returned as such. 414 * Otherwise <CODE>null</CODE> is returned. 415 * 416 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 417 * @return the corresponding <CODE>PdfArray</CODE> object, 418 * or <CODE>null</CODE> 419 */ 420 public PdfArray getAsArray(final int idx) { 421 PdfArray array = null; 422 PdfObject orig = getDirectObject(idx); 423 if (orig != null && orig.isArray()) 424 array = (PdfArray) orig; 425 return array; 426 } 427 428 /** 429 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfStream</CODE>, 430 * resolving indirect references. 431 * 432 * The object corresponding to the specified index is retrieved and 433 * resolved to a direct object. 434 * If it is a <CODE>PdfStream</CODE>, it is cast down and returned as such. 435 * Otherwise <CODE>null</CODE> is returned. 436 * 437 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 438 * @return the corresponding <CODE>PdfStream</CODE> object, 439 * or <CODE>null</CODE> 440 */ 441 public PdfStream getAsStream(final int idx) { 442 PdfStream stream = null; 443 PdfObject orig = getDirectObject(idx); 444 if (orig != null && orig.isStream()) 445 stream = (PdfStream) orig; 446 return stream; 447 } 448 449 /** 450 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfString</CODE>, 451 * resolving indirect references. 452 * 453 * The object corresponding to the specified index is retrieved and 454 * resolved to a direct object. 455 * If it is a <CODE>PdfString</CODE>, it is cast down and returned as such. 456 * Otherwise <CODE>null</CODE> is returned. 457 * 458 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 459 * @return the corresponding <CODE>PdfString</CODE> object, 460 * or <CODE>null</CODE> 461 */ 462 public PdfString getAsString(final int idx) { 463 PdfString string = null; 464 PdfObject orig = getDirectObject(idx); 465 if (orig != null && orig.isString()) 466 string = (PdfString) orig; 467 return string; 468 } 469 470 /** 471 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfNumber</CODE>, 472 * resolving indirect references. 473 * 474 * The object corresponding to the specified index is retrieved and 475 * resolved to a direct object. 476 * If it is a <CODE>PdfNumber</CODE>, it is cast down and returned as such. 477 * Otherwise <CODE>null</CODE> is returned. 478 * 479 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 480 * @return the corresponding <CODE>PdfNumber</CODE> object, 481 * or <CODE>null</CODE> 482 */ 483 public PdfNumber getAsNumber(final int idx) { 484 PdfNumber number = null; 485 PdfObject orig = getDirectObject(idx); 486 if (orig != null && orig.isNumber()) 487 number = (PdfNumber) orig; 488 return number; 489 } 490 491 /** 492 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfName</CODE>, 493 * resolving indirect references. 494 * 495 * The object corresponding to the specified index is retrieved and 496 * resolved to a direct object. 497 * If it is a <CODE>PdfName</CODE>, it is cast down and returned as such. 498 * Otherwise <CODE>null</CODE> is returned. 499 * 500 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 501 * @return the corresponding <CODE>PdfName</CODE> object, 502 * or <CODE>null</CODE> 503 */ 504 public PdfName getAsName(final int idx) { 505 PdfName name = null; 506 PdfObject orig = getDirectObject(idx); 507 if (orig != null && orig.isName()) 508 name = (PdfName) orig; 509 return name; 510 } 511 512 /** 513 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfBoolean</CODE>, 514 * resolving indirect references. 515 * 516 * The object corresponding to the specified index is retrieved and 517 * resolved to a direct object. 518 * If it is a <CODE>PdfBoolean</CODE>, it is cast down and returned as 519 * such. Otherwise <CODE>null</CODE> is returned. 520 * 521 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 522 * @return the corresponding <CODE>PdfBoolean</CODE> object, 523 * or <CODE>null</CODE> 524 */ 525 public PdfBoolean getAsBoolean(final int idx) { 526 PdfBoolean bool = null; 527 PdfObject orig = getDirectObject(idx); 528 if (orig != null && orig.isBoolean()) 529 bool = (PdfBoolean) orig; 530 return bool; 531 } 532 533 /** 534 * Returns a <CODE>PdfObject</CODE> as a <CODE>PdfIndirectReference</CODE>. 535 * 536 * The object corresponding to the specified index is retrieved. 537 * If it is a <CODE>PdfIndirectReference</CODE>, it is cast down and 538 * returned as such. Otherwise <CODE>null</CODE> is returned. 539 * 540 * @param idx The index of the <CODE>PdfObject</CODE> to be returned 541 * @return the corresponding <CODE>PdfIndirectReference</CODE> object, 542 * or <CODE>null</CODE> 543 */ 544 public PdfIndirectReference getAsIndirectObject(final int idx) { 545 PdfIndirectReference ref = null; 546 PdfObject orig = getPdfObject(idx); // not getDirect this time. 547 if (orig != null && orig.isIndirect()) 548 ref = (PdfIndirectReference) orig; 549 return ref; 550 } 551 552 /** 553 * @return an iterator that iterates over the {@link PdfObject}s in this PdfArray. 554 */ 555 public Iterator<PdfObject> iterator() { 556 return arrayList.iterator(); 557 } 558}