1 package com.etymon.pjx.util; 2 3 import java.io.*; 4 import java.util.*; 5 import com.etymon.pjx.*; 6 7 12 public class PdfFieldTree { 13 14 17 protected Stack _nested; 18 19 22 protected PdfManager _m; 23 24 27 protected PdfCatalog _catalog; 28 29 32 protected static Set _inheritable; 33 34 38 protected static Set _inheritableAcroForm; 39 40 protected static final PdfName PDFNAME_ACROFORM = new PdfName("AcroForm"); 41 protected static final PdfName PDFNAME_KIDS = new PdfName("Kids"); 42 protected static final PdfName PDFNAME_FIELDS = new PdfName("Fields"); 43 protected static final PdfName PDFNAME_PARENT = new PdfName("Parent"); 44 protected static final PdfName PDFNAME_T = new PdfName("T"); 45 protected static final PdfName PDFNAME_TYPE = new PdfName("Type"); 46 47 51 public PdfFieldTree(PdfManager manager) { 52 53 _m = manager; 54 _catalog = new PdfCatalog(manager); 55 56 _inheritable = new HashSet(13); 57 _inheritable.add(new PdfName("FT")); 58 _inheritable.add(new PdfName("Ff")); 59 _inheritable.add(new PdfName("V")); 60 _inheritable.add(new PdfName("DV")); 61 _inheritable.add(new PdfName("DR")); 62 _inheritable.add(new PdfName("DA")); 63 _inheritable.add(new PdfName("Q")); 64 _inheritable.add(new PdfName("Opt")); 65 _inheritable.add(new PdfName("MaxLen")); 66 _inheritable.add(new PdfName("TI")); 67 _inheritable.add(new PdfName("I")); 68 _inheritable.add(new PdfName("Filter")); 69 _inheritable.add(new PdfName("Flags")); 70 71 _inheritableAcroForm = new HashSet(3); 72 _inheritableAcroForm.add(new PdfName("DR")); 73 _inheritableAcroForm.add(new PdfName("DA")); 74 _inheritableAcroForm.add(new PdfName("Q")); 75 76 } 77 78 91 protected PdfObject getAcroForm() throws IOException, PdfFormatException { 92 synchronized (this) { 93 synchronized (_m) { 94 95 Object obj = _m.getObjectIndirect(_catalog.getCatalog()); 96 if ( !(obj instanceof PdfDictionary) ) { 97 throw new PdfFormatException( 98 "Catalog is not a dictionary."); 99 } 100 PdfDictionary catalog = (PdfDictionary)obj; 101 102 obj = catalog.getMap().get(PDFNAME_ACROFORM); 103 if (obj == null) { 104 return null; 105 } 106 if ( ( !(obj instanceof PdfReference) ) && 107 ( !(obj instanceof PdfDictionary) ) ) { 108 throw new PdfFormatException( 109 "AcroForm is not a dictionary or indirect reference."); 110 } 111 return (PdfObject)obj; 112 113 } 114 } 115 } 116 117 125 public String getFullyQualifiedName(PdfDictionary field) throws IOException, PdfFormatException { 126 synchronized (this) { 127 synchronized (_m) { 128 129 int approxStringLength = 0; 134 135 ArrayList names = new ArrayList(); 138 139 PdfDictionary fieldNode = field; 142 143 boolean done = false; 144 do { 145 146 Map fieldMap = fieldNode.getMap(); 147 148 Object obj = fieldMap.get(PDFNAME_T); 150 if (PdfNull.isNull(obj) == false) { 151 if ( !(obj instanceof PdfObject) ) { 152 throw new PdfFormatException( 153 "Field name (T) is not a PDF object."); 154 } 155 obj = _m.getObjectIndirect((PdfObject)obj); 156 if (PdfNull.isNull(obj) == false) { 157 if ( !(obj instanceof PdfString) ) { 158 throw new PdfFormatException( 159 "Field name (T) is not a string."); 160 } 161 String fieldName = ((PdfString)obj).getString(); 164 if (fieldName.length() > 0) { 165 names.add(fieldName); 166 approxStringLength += fieldName.length() + 1; 167 } 168 } 169 } 170 171 obj = fieldMap.get(PDFNAME_PARENT); 173 if (PdfNull.isNull(obj) == true) { 174 done = true; 175 } else { 176 if ( !(obj instanceof PdfObject) ) { 177 throw new PdfFormatException( 178 "Field parent is not a PDF object."); 179 } 180 obj = _m.getObjectIndirect((PdfObject)obj); 181 if (PdfNull.isNull(obj) == true) { 182 done = true; 183 } else { 184 if ( !(obj instanceof PdfDictionary) ) { 185 throw new PdfFormatException( 186 "Field parent is not a dictionary."); 187 } 188 fieldNode = (PdfDictionary)obj; 189 } 190 } 191 192 } while (!done); 193 194 StringBuffer sb = new StringBuffer (approxStringLength); 196 boolean first = true; 197 int namesSize = names.size(); 198 for (int x = namesSize - 1; x >= 0; x--) { 199 String name = (String )names.get(x); 200 if (first) { 202 first = false; 203 } else { 204 sb.append('.'); 205 } 206 sb.append(name); 207 } 208 209 return sb.toString(); 210 211 } 212 } 213 } 214 215 231 public PdfDictionary inheritAttributes(PdfDictionary field) throws IOException, PdfFormatException { 232 synchronized (this) { 233 synchronized (_m) { 234 235 Map fieldM = field.getMap(); 236 237 Map newMap = new HashMap(field.getMap()); 239 240 Set unused = new HashSet(_inheritable.size()); 243 for (Iterator t = _inheritable.iterator(); t.hasNext(); ) { 244 245 PdfName attr = (PdfName)t.next(); 246 Object obj = fieldM.get(attr); 247 248 if ( (obj == null) || (obj instanceof PdfNull) ) { 249 unused.add(attr); 250 } 251 252 } 253 254 boolean done = false; 255 256 do { 257 258 if (unused.isEmpty()) { 262 done = true; 263 break; 264 } 265 266 Object obj = fieldM.get(PDFNAME_PARENT); 268 if (obj == null) { 269 done = true; 275 obj = getAcroForm(); 276 if (obj == null) { 277 break; 278 } 279 unused.retainAll(_inheritableAcroForm); 284 if (unused.isEmpty()) { 285 break; 286 } 287 } 288 if ( !(obj instanceof PdfObject) ) { 289 throw new PdfFormatException( 290 "Parent object is not a PDF object."); 291 } 292 obj = _m.getObjectIndirect((PdfObject)obj); 293 if ( !(obj instanceof PdfDictionary) ) { 294 throw new PdfFormatException( 295 "Parent object is not a dictionary."); 296 } 297 fieldM = ((PdfDictionary)obj).getMap(); 298 299 for (Iterator t = unused.iterator(); t.hasNext(); ) { 301 302 PdfName attr = (PdfName)t.next(); 303 304 obj = fieldM.get(attr); 306 if ( (obj != null) && ( !(obj instanceof PdfNull) ) ) { 307 t.remove(); 308 newMap.put(attr, obj); 309 } 310 311 } 312 313 } while ( !done ); 314 315 return new PdfDictionary(newMap); 316 317 } 318 } 319 } 320 321 332 public PdfFieldTreeIterator getIterator() throws IOException, PdfFormatException { 333 return new FieldTreeIterator(this, _m); 334 } 335 336 340 protected class FieldTreeIterator implements PdfFieldTreeIterator { 341 342 345 protected PdfManager _m; 346 347 350 protected PdfFieldTree _ft; 351 352 359 public FieldTreeIterator(PdfFieldTree ft, PdfManager m) throws IOException, PdfFormatException { 360 361 _ft = ft; 362 _m = m; 363 _nested = new Stack(); 364 365 Object obj = m.getObjectIndirect(getAcroForm()); 367 368 if (obj != null) { 369 370 if ( !(obj instanceof PdfDictionary) ) { 371 throw new PdfFormatException( 372 "AcroForm is not a dictionary."); 373 } 374 PdfDictionary acroForm = (PdfDictionary)obj; 375 376 obj = acroForm.getMap().get(PDFNAME_FIELDS); 378 if ( !(obj instanceof PdfObject) ) { 379 throw new PdfFormatException( 380 "Fields array is not a PDF object."); 381 } 382 obj = m.getObjectIndirect((PdfObject)obj); 383 if ( !(obj instanceof PdfArray) ) { 384 throw new PdfFormatException( 385 "Fields array is not an array."); 386 } 387 List fields = ((PdfArray)obj).getList(); 388 389 _nested.push(newList(fields)); 390 391 } 392 393 } 394 395 protected List newList(List list) { 396 return new ArrayList(list); 397 } 398 399 408 protected PdfReference descendTree() throws IOException, PdfFormatException { 409 410 List kidsM; 411 PdfReference node; 412 413 do { 414 415 List fieldsM = (List)_nested.peek(); 422 node = (PdfReference)fieldsM.get(0); 423 424 fieldsM.remove(0); 426 427 Object obj = _m.getObjectIndirect(node); 429 if ( !(obj instanceof PdfDictionary) ) { 430 throw new PdfFormatException( 431 "Field node is not a dictionary."); 432 } 433 Map fieldNode = ((PdfDictionary)obj).getMap(); 434 435 437 obj = fieldNode.get(PDFNAME_KIDS); 438 439 if (obj == null) { 440 441 kidsM = null; 442 443 } else { 444 445 if ( !(obj instanceof PdfObject) ) { 446 throw new PdfFormatException( 447 "Kids array is not a PDF object."); 448 } 449 obj = _m.getObjectIndirect((PdfObject)obj); 450 if ( !(obj instanceof PdfArray) ) { 451 throw new PdfFormatException( 452 "Kids array is not an array object."); 453 } 454 List kidsL = ((PdfArray)obj).getList(); 455 if (kidsL.isEmpty()) { 456 throw new PdfFormatException( 457 "Kids array is empty."); 458 } 459 460 kidsM = newList(kidsL); 461 462 } 463 468 if (kidsM != null) { 472 _nested.push(kidsM); 473 } 474 475 } while (kidsM != null); 476 479 return node; 480 481 } 482 483 486 protected void cleanUp() { 487 488 while ( ( _nested.empty() == false ) && 489 ( ((List)_nested.peek()).isEmpty() ) ) { 490 491 _nested.pop(); 492 493 } 494 495 } 496 497 public boolean hasNext() throws PdfFormatException { 499 synchronized (_m) { 500 synchronized (_ft) { 501 502 cleanUp(); 503 504 return !(_nested.empty()); 505 506 } 507 } 508 } 509 510 514 public PdfReference next() throws NoSuchElementException, IOException, PdfFormatException { 515 synchronized (_m) { 516 synchronized (_ft) { 517 518 if ( !hasNext() ) { 521 throw new NoSuchElementException(); 522 } 523 524 return descendTree(); 527 528 } 529 } 530 } 531 532 } 533 534 } 535 | Popular Tags |